Selenium driver.getTitle() is not working - webdriver

driver.getTitle() does not return the title of the page. It returns null. I have the below html structure in the web page:
<head>
<!-- needed for translation of titles -->
<!-- needed for gomez.jsp -->
<script type="text/javascript" async="" src="https://ssl.google-analytics.com/ga.js"> </script><script type="text/javascript"> … </script><script src="https://B001E0.t.axf8.net/js/gtag5.js" type="text/javascript"></script>
<title>
Applications
</title>
so on....
Could somebody explain whats the problem here.. Thanks in advance

Then you might want to put explicit waits like below:
void waitForLoad(WebDriver driver) {
ExpectedCondition pageLoads = new
ExpectedCondition() {
public Boolean apply(WebDriver driver) {
return (Boolean)((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
}
};
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(pageLoads);
}
And then you can perform below action:
driver.getTitle()

I think it might be late for you but I am just putting it so that other can get the help.
1st lame way is that you can just add
Thread.sleep(2000);
//(2000 is the time in milliseconds) before the the
driver.getTitle();
You can give the time what every you want, what it will do is just slow down your execution time for 2 seconds (in this case)
2nd you can use
WebDriverWait wait = new WebD`enter code here`riverWait(driver, 10);
wait.until(ExpectedConditions.jsReturnsValue("complete"));
driver.getTitle();
It will only work if your HTML and JS returns the text complete
now you will get the new pages title and you can use it for verification.
adding one more code to the thread:
WebDriverWait wait = new WebDriverWait(driver, 30);
try{
wait.until(ExpectedConditions.titleIs(eTitle));
Reporter.log("PASS: Title is matching.", true);
}

Related

CSS Issue with Node.JS / EJS

I know similar questions have been asked before, but I've had a good look through & unfortunately none of the answers are helping me.
My CSS file is being ignored in certain circumstances.
So in my app.js file I have this code, defining my view engine setup
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
In my index.js file I have the following the code for UserList page
/* GET Userlist page. */
router.get('/userlist', function(req, res) {
var db = req.db; // (1) Extract the db object we passed to our HTTP request
var collection = db.get('usercollection'); // (2) Tell our app which collection we want to use
// (3) Find (query) results are returned to the docs variable
collection.find({},{},function(e,docs){
res.render('userlist', { "userlist" : docs }); // (4) Render userlist by passing returend results to said variable
});
});
Finally, my userlist.ejs page looks like this:
<!DOCTYPE html>
<html>
<head>
<title>User List</title>
<link rel='stylesheet' href='/stylesheets/style.css' type="text/css" />
</head>
<body>
<h1>User List</h1>
<ul>
<%
var list = '';
for (i = 0; i < userlist.length; i++) {
list += '<li>' + userlist[i].username + '</li>';
}
return list;
%>
</ul>
</body>
</html>
But when I run my page the CSS file is not loaded. However if I exclude this code:
<%
var list = '';
for (i = 0; i < userlist.length; i++) {
list += '<li>' + userlist[i].username + '</li>';
}
return list;
%>
The CSS file is loaded and applied without issue. Can anyone tell me why this is please? Apologies for the newbie question, but I've been trying to figure this out for ages.
I should mention the 'h1' tags are ignored too. The only thing rendered is the list items.
Not sure if its relevant, but my app is connecting to MongoDB to return the user data.
Any assistance would be very much appreciated!
Thank you!
Make sure that your CSS file is either defined as an endpoint in your index.js file or make sure that public/stylesheets/style.css exists so it can be loaded through the app.use(express.static(path.join(__dirname, 'public'))); command.

How to prevent users from going back to the previous page?

I am using ASP.NET MVC (latest version).
Imagine having 2 pages:
Page-1: "Enter data" >> Page-2: "Thank you"
After submitting Page-1 you are being redirected to Page-2.
My goal: I want to make sure that you can't go back to Page-1 when you hit the browser's back button once you made it to Page-2. Instead I want you rather to stay on Page-2 (or being pushed forward to Page-2 every time you hit the back button).
I have tried all different kind of things. The following is just some simplified pseudo code ...
[NoBrowserCache]
public ActionResult Page1(int userId)
{
var user = GetUserFromDb(userId);
if (user.HasAlreadySubmittedPage1InThePast)
{
// forward to page 2
return RedirectToAction("Page2", routeValues: new { userId = userId });
}
var model = new Page1Model();
return View("Page1", model);
}
[NoBrowserCache]
[HttpPost]
public ActionResult Page1(Page1Model model)
{
var user = GetUserFromDb(model.UserId);
if (user.HasAlreadySubmittedPage1InThePast)
{
// forward to page 2
return RedirectToAction("Page2", routeValues: new { userId = model.UserId });
}
// Save posted data to the db
// ...
return RedirectToAction("Page2", routeValues: new { userId = model.UserId });
}
public class NoBrowserCache : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Haha ... tried everything I found on the web here:
// Make sure the requested page is not put in the browser cache.
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.SetNoStore();
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-cache");
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.Now);
filterContext.HttpContext.Response.Expires = 0;
}
}
If only I could make sure that a request is being sent to the server every time I hit the back button. But right now, clicking the back button just pulls Page-1 from my browser's cache without sending a request to the server. So currently, I have no chance to redirect you forward to Page-2 by server means.
Any ideas or suggestions?
Thanks, guys!
Btw: There is no login/authentication involved. So, I can't use Session.Abandon() or stuff like this. And I would rather use some server based code than javascript if possible.
EDIT 2017-5-12
Following #grek40, I made sure that the anti-chaching statements end up in the browser. I therefor completely removed the [NoBrowserCache]-ActionFilterAttribute from my C# code above. Instead I added the following statements in the <head> section of my _Layout.cshtml:
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
I confirm that these three lines are being rendered to my browser (used my browser's developer tools to inspect). However, caching still works. I can still move backward without any server requests. Tested this with Google Chrome v62, Firefox Quantum v57 and Microsoft Edge v41 (all on Win10). #
EDIT 2017-6-12
Again following #grek40's suggestions: tried Expires: 0 as well as Expires: -1. No difference. I still didn't manage, to turn off my browser's cache.
Finally I found a solution. It's javascript based, but very simple.
I just had to add the following snippet to my Page-2 (the page I don't want users to leave anymore once they got there):
<script type="text/javascript">
$(document).ready(function () {
history.pushState({ page: 1 }, "title 1", "#nbb");
window.onhashchange = function (event) {
window.location.hash = "nbb";
};
});
I found this here: how to stop browser back button using javascript
Thanks to all your support guys. But "my own" solution was the only one that worked.
This can be done by using javascript. Use the following code
<script type = "text/javascript" >
function preventBack(){window.history.forward();}
setTimeout("preventBack()", 0);
window.onunload=function(){null};
</script>
or check the following link1 and link2.
This little piece of code might help you in solving your issue.
<script type="text/javascript">
/*To retain on the same view on Back Click*/
history.pushState(null, null, window.location.href);
window.addEventListener('popstate', function (event) {
history.pushState(null, null, window.location.href);
event.preventDefault();
});
</script>
You can add a line of javascript to every page for a client-side solution:
history.forward();
See docs on MDN. When there is a page to go forward to (which is when the used pressed the BACK button), this will force the user to that page. When the user already is at the most recent page, this does nothing (no error).
Response.Cache.SetCacheability(HttpCacheability.NoCache); // HTTP 1.1.
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
Response.AppendHeader("Expires", "0"); // Proxies.

Loading Google Places Autocomplete Async Angular 2

I am trying to instantiate a Google Places Autocomplete input within an Angular 2 component. I use this code to do it:
loadGoogle() {
let autocomplete = new google.maps.places.Autocomplete((this.ref.nativeElement), { types: ['geocode'] });
let that = this
//add event listener to google autocomplete and capture address input
google.maps.event.addListener(autocomplete, 'place_changed', function() {
let place = autocomplete.getPlace();
that.place = place;
that.placesearch = jQuery('#pac-input').val();
});
autocomplete.addListener()
}
Normally, I believe, I would use the callback function provided by the Google API to ensure that it is loaded before this function runs, but I do not have access to it within a component's scope. I am able to load the autocomplete input 90% of the time, but on slower connections I sometimes error out with
google is not defined
Has anyone figured out how to ensure the Google API is loaded within a component before instantiating.
Not sure whether this will help, but I just use a simple script tag in my index.html to load Google API and I never get any error. I believe you do the same as well. I post my codes here, hope it helps.
Note: I use Webpack to load other scripts, except for Google Map API.
<html>
<head>
<base href="/">
<title>Let's Go Holiday</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Google Map -->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?key=<your-key>&libraries=places"></script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
And then in your component:
...
declare var google: any;
export class SearchBoxComponent implements OnInit {
ngOnInit() {
// Initialize the search box and autocomplete
let searchBox: any = document.getElementById('search-box');
let options = {
types: [
// return only geocoding results, rather than business results.
'geocode',
],
componentRestrictions: { country: 'my' }
};
var autocomplete = new google.maps.places.Autocomplete(searchBox, options);
// Add listener to the place changed event
autocomplete.addListener('place_changed', () => {
let place = autocomplete.getPlace();
let lat = place.geometry.location.lat();
let lng = place.geometry.location.lng();
let address = place.formatted_address;
this.placeChanged(lat, lng, address);
});
}
...
}
I used it the same way as explained above but as per google page speed i was getting this suggestion,
Remove render-blocking JavaScript:
http://maps.googleapis.com/…es=geometry,places&region=IN&language=en
So i changed my implementation,
<body>
<app-root></app-root>
<script src="http://maps.googleapis.com/maps/api/js?client=xxxxx2&libraries=geometry,places&region=IN&language=en" async></script>
</body>
/* Now in my component.ts */
triggerGoogleBasedFn(){
let _this = this;
let interval = setInterval(() => {
if(window['google']){
_this.getPlaces();
clearInterval(interval);
}
},300)
}
You can do one more thing, emit events once the value(google) is received,& trigger your google task
inside them.

What needs to be changed in this code to make the page on top of it that loads this in a iframe change load a new url?

ok so heres my code
<html>
<head>
<title></title>
<body>
<script>
<!--
/*
Cookie Redirect. Written by PerlScriptsJavaScripts.com
Copyright http://www.perlscriptsjavascripts.com
Free and commercial Perl and JavaScripts
*/
// page to go to if cookie exists
go_to = "http://www.cookieisthere.com";
// number of days cookie lives for
num_days = 365;
function ged(noDays){
var today = new Date();
var expr = new Date(today.getTime() + noDays*24*60*60*1000);
return expr.toGMTString();
}
function readCookie(cookieName){
var start = document.cookie.indexOf(cookieName);
if (start == -1){
} else {
window.location = go_to;
}
}
readCookie("seenit");
// -->
</script>
</body>
</html>
This page will load on a page through a iframe... if the cookie is their i want the parent window to go to http://www.cookieisthere.com not the original page. After reading up on it a bit some people say use _top where the link is but i dont know how to do this. All help is much appreciated :)
Try this instead
<html>
<head>
<title></title>
<body>
<script>
<!--
/*
Cookie Redirect. Written by PerlScriptsJavaScripts.com
Copyright http://www.perlscriptsjavascripts.com
Free and commercial Perl and JavaScripts
*/
// page to go to if cookie exists
go_to = "http://www.cookieisthere.com";
// number of days cookie lives for
num_days = 365;
function ged(noDays){
var today = new Date();
var expr = new Date(today.getTime() + noDays*24*60*60*1000);
return expr.toGMTString();
}
function readCookie(cookieName){
var start = document.cookie.indexOf(cookieName);
if (start == -1){
} else {
window.top.location = go_to;
}
}
readCookie("seenit");
// -->
</script>
</body>
</html>

Pop up window not appending text

I am trying to implement a 'Trace Window' pop up window when I enter a website, and then send messages to that window throughout the website in Order to diagnose some of the more awkward issues i have with the site.
The Problem is that the page changes, if The trace window already exists, all content is removed, before the new TraceText is added.
What I want is a Window that can be sent messages from any page inside the website.
I have a javascript Script debugger.js which I include as a script in every screen (shown below) I would then call the sendToTraceWindow() function to send a message to it thoughout the website. this is currently Mostly done in vbscript at present, due to the issues i am currenctly investigating.
I think it is because i am scripting in the debugger.js into every screen, which sets the traceWindow variable = null (see code below) but I do not know how to get around this!
Any help much appreciated.
Andrew
code examples:
debugger.js:
var traceWindow = null
function opentraceWindow()
{
traceWindow = window.open('traceWindow.asp','traceWindow','width=400,height=800')
}
function sendToTracewindow(sCaller, pMessage)
{
try
{
if (!traceWindow)
{
opentraceWindow()
}
if (!traceWindow.closed)
{
var currentTrace = traceWindow.document.getElementById('trace').value
var newTrace = sCaller + ":" + pMessage + "\n" + currentTrace
traceWindow.document.getElementById('trace').value = newTrace
}
}
catch(e)
{
var currentTrace = traceWindow.document.getElementById('trace').value
var newTrace = "error tracing:" + e.message + "\n" + currentTrace
traceWindow.document.getElementById('trace').value = newTrace
}
}
traceWindow.asp - just a textarea with id='trace':
<HTML>
<head>
<title>Debug Window</title>
</head>
<body>
<textarea id="trace" rows="50" cols="50"></textarea>
</body>
</HTML>
I don't think there is any way around the fact that your traceWindow variable will be reset on every page load, therefore rendering your handle to the existing window invalid. However, if you don't mind leveraging LocalStorage and some jQuery, I believe you can achieve the functionality you are looking for.
Change your trace window to this:
<html>
<head>
<title>Debug Window</title>
<script type="text/javascript" src="YOUR_PATH_TO/jQuery.js" />
<script type="text/javascript" src="YOUR_PATH_TO/jStorage.js" />
<script type="text/javascript" src="YOUR_PATH_TO/jquery.json-2.2.js" />
<script type="text/javascript">
var traceOutput;
var traceLines = [];
var localStorageKey = "traceStorage";
$(function() {
// document.ready.
// Assign the trace textarea to the global handle.
traceOutput = $("#trace");
// load any cached trace lines from local storage
if($.jStorage.get(localStorageKey, null) != null) {
// fill the lines array
traceLines = $.jStorage.get(localStorageKey);
// populate the textarea
traceOutput.val(traceLines.join("\n"));
}
});
function AddToTrace(data) {
// append the new trace data to the textarea with a line break.
traceOutput.val(traceOutput.val() + "\n" + data);
// add the data to the lines array
traceLines[tracelines.length] = data;
// save to local storage
$.jStorage.set(localStorageKey, traceLines);
}
function ClearTrace() {
// empty the textarea
traceOutput.val("");
// clear local storage
$.jStorage.deleteKey(localStorageKey);
}
</script>
</head>
<body>
<textarea id="trace" rows="50" cols="50"></textarea>
</body>
</html>
Then, in your pages where you want to trace data, you could modify your javascript like so:
var traceWindow = null;
function opentraceWindow() {
traceWindow = window.open('traceWindow.asp','traceWindow','width=400,height=800');
}
function sendToTracewindow(sCaller, pMessage) {
traceWindow.AddToTrace(sCaller + ":" + pMessage);
}
Every time a new page is loaded and the trace window is refreshed, the existing trace data is loaded from local storage and displayed in your textarea. This should achieve the functionality that you are looking for.
Please be kind on any errors - I'm winging this on a Monday morning!
Finding the jQuery library should be trivial. You can find the jStorage library here: http://www.jstorage.info/, and you can find jquery-json here: http://code.google.com/p/jquery-json/

Resources