Passing a location.search parameter to a Jasmine (Karma) test - javascript

I have a javascript file that uses location.search for some logic. I want to test it using Karma. When I simply set the location (window.location.search = 'param=value' in the test), Karma complains I'm doing a full page reload. How do I pass a search parameter to my test?

Without seeing some code it's a little tricky to know what you exactly want, however it sounds like you want some sort of fixture/mock capability added to your tests. If you check out this other answer to a very similar problem you will see that it tells you to keep the test as a "unit".
Similar post with Answer
What this means is that we're not really concerned with testing the Window object, we'll assume Chrome or Firefox manufacturers will do this just fine for us. In your test you will be able to check and respond to your mock object and investigate that according to your logic.
When running in live code - as shown - the final step of actually handing over the location is dealt with by the browser.
In other words you are just checking your location setting logic and no other functionality. I hope this can work for you.

Related

Cypress How to handle erors

I'm testing a lot of things but some of them are not too important(like caption text fail)I want to add optional parameter (if its wrong thats okay continue testing)
I used to work with Katalon Studio, it has Change failure options(stop,fail,continue) Can I make it with Cypress for my test cases.
Sample image
As Mikkel mentioned already Cypress doesn't like optional testing. There is a way how you could do that by using an if-statement as explained in this question: In Cypress, is there a way to avoid a failure depending on a daily message?
But to do that for every test you optionally want to test can make a big pile up of your code. So if you don't care if it succeeds or fails, just don't test it.
Another way you can try to be more resilient is by cutting up the tests further more. But you have to make sure that the scenarios don't rely on each other otherwise they will still fail.

How to debug timed out waiting for asynchronous Angular tasks? Failure to find elements on angular page occurring

Edit: Note that I found the root of my problem after help from #ernst-zwingli, so if you have this same error one of his noted fixes might help you out. My problem is a known issue with Protractor itself, if you think this may be you, I've expanded on my steps to pinpoint the root of the problem after my original question.
I'm trying to use Protractor in an Angular2 (just Angular) application built using angular-cli.
My problem: Elements on an Angular app page are not being found when browser.waitForAngularEnabledis at it's default setting of true (as in 'I believe I am on an angular page and would like for Protractor to do it's magic'). They are being found just fine if I set browser.waitForAngularEnabledto false (as in 'I am not on an angular page and would like to handle this myself, take a seat Protractor'). How do I track down what's causing this on my definitely Angular pages?
I have a product with a non-Angular Auth0 login page that gates access to the rest of the product that is written in Angular (Angular 4.3.2 to be exact). I have successfully traversed logging in on the non-Angular login page. I flipped the waitForAngularEnabled switched to false to facilitate the non-Angular login. I turned it back to true at the point where I expected my initial landing page (Angular) to be loaded, after clicking the submit button. Code is as follows:
browser.waitForAngularEnabled(false);
browser.driver.get('https://dashboard.net/projects');
browser.driver.sleep(10000);
browser.driver.findElement(By.css("[type='email']"));
browser.driver.findElement(By.css("[type='email']")).sendKeys("email#example.com");
browser.driver.findElement(By.css(".auth0-label-submit")).click();
browser.driver.findElement(By.id("passwordInput")).sendKeys("password");
browser.driver.findElement(By.id("submitButton")).click();
browser.driver.sleep(5000); // needed if not waiting for Angular
//browser.waitForAngularEnabled(true); // Back to Protractor land we go
let elementToFind = element(by.className("header-text"));
elementToFind.isDisplayed().then(function() {grabTheDarnLocalStorage()});
expect(elementToFind.isDisplayed()).toBeTruthy();
If I uncomment the browser.waitForAngularEnabled(true); line to state that I'm back in Angular code I get the error trace as follows:
Failed: Timed out waiting for asynchronous Angular tasks to finish after 30 seconds. This may be because the current page is not an Angular application. Please see the FAQ for more details: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular
While waiting for element with locator - Locator: By(css selector, .header-text)
ScriptTimeoutError: asynchronous script timeout: result was not received in 30 seconds
(Session info: chrome=61.0.3163.100)
(Driver info: chromedriver=2.32.498550 (9dec58e66c31bcc53a9ce3c7226f0c1c5810906a),platform=Windows NT 10.0.14393 x86_64)
at WebDriverError (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\error.js:27:5)
at ScriptTimeoutError (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\error.js:203:5)
at Object.checkLegacyResponse (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\error.js:505:15)
at parseHttpResponse (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\http.js:509:13)
at doSend.then.response (C:\Users\c-shouston\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\http.js:440:13)
at process._tickCallback (internal/process/next_tick.js:109:7)
From: Task: Protractor.waitForAngular() - Locator: By(css selector, .header-text)
I've referenced the FAQ: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular
I have my devs stating that they don't use $timeout (they use (Edit: NOT $interval) Observable Interval thank you very much) and they're not sure about $http.
I found this solution about the canonical way to debug protractor Angular sync issue issue: Canonical way to debug Protractor-to-Angular sync issues
but I'm not sure the solution works without access to modifying the dev code to run the programmatic tracker. (Edit: I never did figure out how to get this to work)
I also found this about a long timeout you add before each test, but I feel this is unnecessary overhead that makes your overall test execution take longer than it should without understanding the root cause of the problem: https://stackoverflow.com/a/37217167/2718402 (Edit: yeah, this is a bad idea and adds unnecessary time to your tests, please don't do this)
The frustrating bit is that this seems to be a common occurrence and there doesn't seem to be a streamlined documentation on how to deal with it. Logging in with a non-Angular page only to transition to an Angular page. Angular pages not being picked up properly by Protractor. All of the examples I find online are bits of code that I don't have a reference for where they should be at in my overall test framework. I would kill for a full example of someone testing a non-Angular login that transitions to a fully Angular website, with a setup config and real world test cases. (Edit: This is still true, but I can't make one myself as my application is in a bad grey area, note my RCA below for more details.)
I just want the ability to do my login and then successfully transition over to my Angular pages and be able to rely on Protractor to work with my Angular pages. I need to know what to look for that may be a long running asynchronous process (What specifically can I check for in the Chrome dev tools?). I would love to understand what Protractor needs as defaults in order to successfully work with the Angular parts of my app/website (Is there something beyond the presence of <app-root _nghost-c0="" ng-version="4.3.2"> in the HTML?). Before this job I worked in Java, so all of this asynchronicity and Angular is new to me, so I know I'm missing the known things that a seasoned Javascript dev is aware of.
My Solution/Root Cause Analysis
Starting down the list suggested by #ernst-zwingli:
for Angular(2) Check if the object window.getAllAngularRootElements returns at least one value.
It returned at least one value, so I moved on.
useAllAngular2AppRoots: true,
I tried this and still ran into the async timeout.
And if $interval or other long lasting asynchronous tasks are used, there can be issues, because of the zones
Previously #ernst-zwingli also mentioned looking at the testability method, except it was the old way. Through research and testing I found the window object also has a getAllAngularTestabilities method. This led down an interesting rabbit hole. An example output from the Chrome console (put window.getAllAngularTestabilities() in the Chrome console window, look at the resulting list) is as follows:
t:
_callbacks:...,
_didWork:true,
_isZoneStable: true (this looks promising, but why isn't Protractor working then?!?)
_ngZone:
hasPendingMacrotasks: true,
hasPendingMicrotasks: false,
isStable: true
I would think isZoneStable would be enough, but apparently not so for Protractor. Then looking at Macrotasks being true, I had to look up what the heck a Macrotask was: What does hasPendingMacrotasks and hasPendingMicrotasks check for?.
A macrotask can be:
i.e. setTimeout, setInterval, setImmediate
Thus #ernst-zwingli's note about interval's causing problems in the zones was remembered and something finally clicked.
First github issue, about zone instability
Another github issue complaining about the necessity of using browser.driver to get things done along with browser.waitForAngularEnabled. Apparently this is expected behavior, it led me to issue #3349
Issue #3349 - The actual root cause of my issue. My developers do not actively jump in and out of zones around observables. Even though these observables only have one subscriber. Since they live in the angular zone at this time, they are a long running "Macrotask" that Protractor waits infinitely on.
I can't rewrite the code with these wrappers as I am not currently versed enough in Angular to do it safely and we are currently hurtling toward a November deadline. I think I'll have to deal with using browser.driver for the time being and hope I can't get it fixed later. Hopefully my RCA was helpful for you.
In the following I list a set of potential causes and possibilities to fix/resolve them.
How does AngularJS and Angular(2) Work / What can I check in the Browser Dev Mode
I can't explain it as well as Andrey Agibalov in his Blog here, so check it out (also for developers).
Basically, the objects required by Protractor you can check in your Chrome Dev.
for AngularJS
Check if the object window.angular is properly defined, i.e. lookup window.angular.version and also try window.angular.getTestability of your Root element
for Angular(2)
Check if the object window.getAllAngularRootElements returns at least one value.
Root Element (AngularJS)
Potentially your Angular App is somewhere wrapped within the Body as something like <div ng-app="my-app">.
In that case, you must adjust your rootElement: body inside config.ts. Check this answer for details.
Angular(2)
If you're using Angular (aka Angular2), then there are ngZone's introduced. In this case your config.js should additionally contain this:
exports.config = {
framework: 'jasmine',
seleniumAddress: 'http://localhost:4444/wd/hub',
specs: ['spec.js'],
useAllAngular2AppRoots: true,
// rootElement: 'root-element'
};
check in your browser for window.getAllAngularRootElements as the additional line in conf.js is about this.
If you can, maybe use the advantage of multiple zones possible. Create a 2nd zone, configure rootElement: 'root-element'
to only focus on one zone and then move some asynchronous tasks into the other zone until you found, which task(s) lead to timeout. Keep those tasks (if possible) in the separate zone, so Protractor ignores those tasks.
And if $interval or other long lasting asynchronous tasks are used, there can be issues, because of the zones. Repeatedly or long lasting tasks should be started outside the zone and then be moved into the zone as else Protractor could run into timeouts. There is a workaround for developers to apply, in order to avoid these problems for Protractor.
read all about it here
browser.driver. - side remark
browser.driver.get() works as if ignoreSynchronization = true, since you directly assign the Browser Driver and you kind of bypass the synchronization logic of Protractor.
Read more about it in this answer here.
Hope I could give you some more input and you can solve your issue. Please let me know the results.
Could you please set
browser.ignoreSynchronization = true;
and try

Protractor Accessibility reporting

I am trying to use Accessibility plugin that comes with Protractor. From what I see it does checking for a11y of last page that I am located.
Is there a way to have 2 test scripts executed one after another one and provide different reports or put all in one report but separated.
Example:
access.js
access1.js
Output file:
resultJsonOutputFile: 'result/result.json'
I tried to this way in conf.js:
specs: ['../test/access.js', '../test/access1.js'],
or
specs: ['../test/access*.js'],
but still get result for last script executed
I tried also creating suites:
suites: {
homepage: '../test/homepage/access.js',
catalogpage: '../test/catalogpage/access1.js'
},
but when I check JSON file, if 2 scripts executed, then 1st one is ok with no issues and provides error for 2nd script. However, if to run 1st script alone, Protractor provides errors
Also I tried to create in one js file as different scenarios, but still same issue
With the current implementation, the accessibility plugin is set to run exactly once per invocation of the Protractor runner, on the last page. So unfortunately, no modification of the suites or test files will make it run more than once.
You can create separate configuration files for each set of test files you'd like to run, or using shardTestFiles to make sure that each file is run in its own process. See the referenceConf for more details on sharding.
Alternatively, you could use aXe to do your accessibility testing. In order to use it with e2e tests in protractor and Webdriver, do the following:
npm install --save-dev axe-webdriverjs
Then in your e2e test files, you do:
var AxeBuilder = require('path_to_the/axe-webdriverjs');
to get hold of the AxeBuilder and then wherever you need to run a test, you:
AxeBuilder(browser.driver)
.analyze(function (results) {
expect(results.violations.length).toBe(0);
});
The above example is using Jasmine but you can extrapolate for any other assertion library.
Also: there is a sample project you can clone and run here https://github.com/dylanb/UITestingFramework
Disclaimer: I am associated with the aXe project and therefore not neutral
I ran into that problem too - as another poster stays the plugin isn't really designed to operate that way.
I wrote a derivative of that plugin which does what you're looking for - protractor-axe-report-plugin.
You make a call to runAxeTest (or runAxeTestWithSelector) whenever you have a page open in the browser that you want to test, and it generates reports using the aXe engine.
Continuum can be used for your use case where it seems the accessibility plugin that comes with Protractor cannot. Here's some documentation on a Protractor-based sample project that uses Continuum. It can be downloaded from webaccessibility.com under 'Continuum for Protractor'. If you look at the source code of the sample project, it basically just boils down to this:
const continuum = require('../js/Continuum.js').Continuum;
continuum.setUp(driver, "../js/AccessEngine.community.js");
continuum.runAllTests().then(() => {
const accessibilityConcerns = continuum.getAccessibilityConcerns();
// accessibilityConcerns.length will be 0 if no accessibility concerns are found
});
(For more information on the above, you can check out the API documentation.)
You can execute that continuum.runAllTests bit wherever in your tests that you like. That includes multiple times from within the same test too, if desired, which if I understand correctly is ultimately what you're after.
Of course, no automated accessibility testing tool is a replacement for manual accessibility testing. It seems like you're just looking to get a baseline level of compliance right now though, so Continuum seems appropriate for your use case to tackle the low-hanging fruit.

Browser.ExecScript() stopped working after updating windows

I've set up a simple testbed for WatiN (ver 2.1) which reads:
var browser = new IE();
browser.GoTo("http://www.google.co.il"); // webpage doesn't matter really
browser.RunScript("alert(123)");
This works only if KB3025390 is not installed. Installing it breaks the above test with an UnAuthorizedAccessException which has HRESULT set to E_ACCESSDENIED. What gives? Is there any workaround?
Update: Using IWebBrowser2.Navigate2 along with "javascript:console.log(123)" type of scripts works however
it makes me feel uneasy using such a backchannel
the scripts run through this back-channel of .Navigate2() may only have a max length of about 2070 chars (give or take) otherwise they get forcibly truncated to this length leading to javascript errors upon attempting to run them
using .Navigate2(), even with the most trivial script, will clog the ready state of Internet Explorer for good in the sense that it will be set to READYSTATE_LOADING without any hope of getting rid of it. In simple terms this means that once you use this hack, you either have to perform every single subsequent operation in WatiN in a "dont-wait-for-webpage-to-load" fashion (GoToNoWait, ClickNoWait etc) lest your code freezes upon waiting for the browser to turn back to READYSTATE_COMPLETE (which will never come about ofcourse as already mentioned).
there appears to be a much broader issue here in the sense that I can't even access the properties of an IHtmlWindow2 object p.e. window.document throws an unauthorized exception again making it virtually impossible to transfer over to the C# world the return-values of the scripts I'm running (using Expando etc) for documents other than window.top.document (for the window.top.document window there is IWebBrowser2.Document which does the trick)
Update#2: The folks over at the selenium project have also noticed this issue:
https://code.google.com/p/selenium/issues/detail?id=8302
A bug report has been created as well:
https://connect.microsoft.com/IE/feedback/details/1062093/installation-of-kb3025390-breaks-out-of-process-javascript-execution-in-ie11
Update#3: IHTMLWindow2.setInterval and IHTMLWindow2.setTimeout also throw UnauthorizedAccess exceptions. These methods are not marked as deprecated in:
http://msdn.microsoft.com/ko-kr/library/windows/desktop/aa741505%28v=vs.85%29.aspx
yet they have wounded up suffering from the same cutbacks all the same.
Update#4: I gave the approach recommended in this post a shot:
https://stackoverflow.com/a/18546866/863651
In order to dynamically invoke the "eval" method of the IHTMLWindow2 object (or any other method really). Got the same "System.UnauthorizedAccessException" as above. So no joy here either.
Microsoft recommends using "eval" over "execscript" however after the above experiment I suspect that they are refering to accessing "eval" only from within the browser.
As far as I can tell thus far, when it comes to the full-fledged IE11+ using "eval" out-of-process (via COM) appears to have been completely prohibited along with any other function-invocation of the window object, the only exception being the back-channel of the .Navigate2() mentioned above.
It turns out Microsoft eventually backpedaled on its decision to kill off .execScript at COM-level. Just install the latest updates for Windows including kb3025390: One of the updates for IE that came after kb3025390 brings back .execScript functionality at COM-level
Note, however, that .execScript is not accessible through IE's javascript anymore. In that context it's gone for good.
fyi: this one is also not working
ieInstance.Document.Script.<methodNameString>(<commaSeperatedParameterString>)
try this worked for me at some places but not all places
ieObject.Navigate "javascript:<methodNameString>(<commaSeperatedParameterString>)", Null, "_parent"
or
ieObject.Navigate2 "javascript:"<methodNameString>(<commaSeperatedParameterString>)", Null, "_parent"
now trying to find out solution using eval
I have found a way around the problem of an update installing automatically. You can just create a simple batch file with following content.
{code}
#echo off
wusa /uninstall /kb:3025390/quiet /norestart
END
{code}
Then go to task scheduler, create a new task for this batch file to run every one hour or day as per your requirements. Add it as a system task so it runs in the background and does not affect the running automations.

Calling a function in a JavaScript file with Selenium IDE

So, I'm running these Selenium IDE tests against a site I'm working on. Everything about the tests themselves is running fine, except I would like to do a bit of clean-up once I'm done. In my MVC3 Razor based site, I have a JavaScript file with a function that gets a JsonResult from a Controller of mine. That Controller handles the database clean-up that Selenium IDE otherwise couldn't handle.
However, I'm having a hard time finding any sort of documentation on how to do this. I know I can do JavaScript{ myJavascriptGoesHere } as one of the Values for a line in the test, but I can't seem to find a way to tell it to go find my clean-up function.
Is it even possible for Selenium IDE to do this sort of thing?
If it comes down to it, I can just make a separate View to handle the clean-up, but I'd really like to avoid that if possible.
Thanks!
If you want to execute your own JavaScript function that exists in your test page from Selenium IDE, you need to make sure you access it via the window object. If you look at the reference for storeEval for instance, it says:
Note that, by default, the snippet will run in the context of the
"selenium" object itself, so this will refer to the Selenium object.
Use window to refer to the window of your application, e.g.
window.document.getElementById('foo')
So if you have your own function e.g. myFunc(). You need to refer to it as window.myFunc().
This can be very handy for exercising client-side validation without actually submitting the form, e.g. if you want to test a variety of invalid and valid form field values.
If you use runScript, that should already run in the window's context.
This works for me.
IJavaScriptExecutor js = driver as IJavaScriptExecutor;
string title = (string)js.ExecuteScript("myJavascriptGoesHere");
Make sure your javascript works first before using it here!
Actually to access your page javascript space, you need to get the real window of your page : this.browserbot.getUserWindow()
See this statement to get the jQuery entry point in your page (if it has jQuery of course ^^ )
https://stackoverflow.com/a/54887281/2143734

Categories

Resources