assert.async() never fails - sapui5

I am new to OpenUI5/QUnit testing. Sorry for the newbie question.
I have added a very basic async QUnit test into my OpenUI5 project:
QUnit.test( "Test async", function( assert ) {
var done = assert.async();
setTimeout(function() {
assert.ok(true);
done();
});
});
This test passes without errors as expected.
Then I have commented out everything except for
var done = assert.async();
The test runs indefinitely without failing. I would expect that it fails after some timeout.
Pressing the "Abort" button just changes the label to "Aborting" but does not fail the test.
I have search the QUnit documentation, that suggest adding
assert.timeout( 1000 ); // Timeout of 1 second
that should be an equivalent to global setting
QUnit.config.testTimeout( 1000 );
But using either crash my test with
assert.timeout is not a function
or
QUnit.config.testTimeout is not a function
I have tried running the test in Chrome, Firefox and IE11 with the same results.
Can anyone tell me what I am doing wrong?

I have found the answer myself. The correct syntax is:
QUnit.config.testTimeout = 1000;
It is then valid for all the subsequent tests. Alternatively I can write
assert.timeout(1000);
at the beginning of the test method - must be before assert.async()

Related

Flutter how to mock a call to rootBundle.loadString(...), then reset the mocked behavior?

In my flutter code, I have logic that does this:
final jsonString = await rootBundle.loadString('AssetManifest.json');
And I have tests that I want to return a fake AssetManifest.json when this line is reached.
To mock it, I do this in the test:
ServicesBinding.instance.defaultBinaryMessenger
.setMockMessageHandler('flutter/assets', (message) {
final Uint8List encoded =
utf8.encoder.convert('{"Foo.ttf":["Foo.ttf"]}');
return Future.value(encoded.buffer.asByteData());
});
The weird thing is, this works, but any tests that run after it hang (they all get stuck in the code when it reaches the await rootBundle.loadString('AssetManifest.json') line.
I've tried adding
ServicesBinding.instance.defaultBinaryMessenger
.setMockMessageHandler('flutter/assets', null);
But this doesn't seem to properly "clean up" the mocked behavior. In fact, if I run the above line in my setUp, the first test to run hangs.
So am I mocking the behavior wrong? Or am I not cleaning it up properly?
I ran into the same issue, and believe it's due to caching by the bundle. This will cause the above test to fail, because the message never gets sent. When calling loadString, you can specify whether to cache the result. E.g. loadString('AssetManifest.json', false).
Note that if you use loadStructuredData, implementations can cache the result and you can't tell it not to.

Protractor Failed: element not interactable

I am running an E2E test for an Angular 7.x app. The test runs straight forward on my local machine. But when I push it on the repo (GitLab), then pipeline fails and throws following error:
USER PROFILE - Check and change PROFILE
- Failed: element not interactable
(Session info: chrome=71.0.3578.80)
(Driver info: chromedriver=2.45.615279 (12b89733300bd268cff3b78fc76cb8f3a7cc44e5),platform=Linux 4.14.74-coreos x86_64)
Test Case:
it('USER PROFILE - Check and change PROFILE', () => {
page.navigateTo();
browser.sleep(1000);
expect(page.getProfileEditTagName()).toMatch('app-edit-profile');
expect(element(by.className('logged-as')).getText()).toBe( testEmail );
browser.actions().mouseMove( element.all( by.id('editIcon-salutation') ).get(0)).click().perform().then(function () {
browser.sleep(4000);
element( by.className('mat-select-arrow') ).click().then(function () {
browser.actions().mouseMove( element.all(by.className('option-value mat-option')).get(0)).click().perform();
browser.sleep(1000);
browser.actions().mouseMove( element.all( by.id('saveButton-salutation') ).get(0)).click().perform();
browser.sleep(1000);
});
});
});
navigateTo() is just a method in profile.po.ts:
navigateTo() {
browser.get('/profileComponentUrl');
}
What's confusing me and where I even can't localize the bug or what's wrong, is that it works fine locally. But once I push to repo, then it fails exactly at that test case. Any Hint please?
The reason element is not interactable could be - performing an action on hidden or obscured element.
You can try -
1. add sleep after by.className('mat-select-arrow') ).click(), as I can see you have not added any waits there.
2. Try to check if you running the test on your local and Jenkins machine with same screen resolution. (this could be the reason of obscured element)
I'd recommend to:
Enable the stacktrace in protractor config: new SpecReporter({ spec: { displayStacktrace: true } }) so you can see exactly what element is throwing the error. This won't solve it but at least should point you in the right direction.
Then if you're using tabs, buttons or other elements that hide/show/disable/enable or change the DOM view, you add a browser.sleep(100) after calling a .click()
I had a same kind of problem and I found this.
I copy pasted that (and some other minor tweaks for example force clicking on previous page in for-loop) and it worked. I believe that the browser.driver.manage().window().maximize(); was part of the solution.
One reason which i figure out is the scroll issue. You need to check the element is displaying properly or not. It may be hidden. So use scrollToTop/scrollToElement/scrollToElementView etc. You can write different scroll methods which suites the condition better.
Another reason is the locator. Try to change the locator, do not trim the locator too much. Just try with full body css locator, if it works then trim properly. Some time in chrome console it may work but not with the test case.

Protractor: Why cucumber steps shows as executed before the actual execution happened

I am new to protractor-cucumber. I am trying to execute below step definition from protractor conf.js.
this.Given(/^I go to sparqHomePage$/, function (callback) {
homepage.goToHomePage()
homepage.login(data[0].UserName,data[0].Password).then(callback);
});
this.Then(/^I create a process$/, function () {
homepage.clickDesign();
homepage.clickFlowDesigner();
console.log(params.flow.procName + ' '+ params.flow.procDesc);
designPage.createNewProc(params.flow.procName, params.flow.procDesc);
});
this.Then(/^I should see process is saved in db$/, function (callback) {
var sql = "select * from process where name = ?";
sql = mysql.format(sql, params.flow.procName);
console.log(sql);
dbConn.query(sql, function(err, rows, fields){
if(!err) {
procDbObj = rows;
console.log(rows);
expect(procDbObj[0].name).to.eventually.equal( params.flow.procName);
expect(procDbObj[0].description).to.eventually.equal(params.flow.procDesc).and.notify(callback);
}
});
});
As soon as I start the execution, the console log shows, feature file execution was completed, but the actual execution is not yet completed.
In my 3rd step I am doing some db validation based on the step 1 and step 2 actions. As cucumber trying to execute all the steps before the completion of real execution with browser, my 3rd test is always failing.
How can I make cucumber to wait for step execution is completed before moving to the next step.
You are calling
homepage.goToHomePage() and homepage.login(data[0].UserName,data[0].Password).then(callback);. Are both methods correct promises that are correctly handled? It now looks like it is calling both methods but giving a direct callback before resolving the promise.
As Ross stated, you can also chain the promises, but first be sure the promises are correctly handled
Edit:
As Ross stated, you can also chain the promises, but first be sure the promises are correctly handled.
You can also return the promise in stead of the callback, just use it as this
this.Given(/^I go to sparqHomePage$/, function () {
homepage.goToHomePage();
return homepage.login(data[0].UserName,data[0].Password);
});
homepage.goToHomePage()
homepage.login(data[0].UserName,data[0].Password).then(callback);
I'm not sure exactly what is happening in the first line but I assume thats going to be doing a click, you will need to make that return a promise and re-write it like
homepage.goToHomePage().then(()=>{
homepage.login(data[0].UserName,data[0].Password).then(callback);
})
And then follow this pattern for the rest of your code as I can see this same issue throughout

How to handle protractor test to run in a sequential order

This is my Block which contain an element.element(by.model("$ctrl.benchmark.name"));
This is not present on Dom. It give me error that element is not on page but still execute all lines of code written after it. I want this to handle in sequential way if above passes then go to next only. How can I handle these types of problem in Protractor.
it("Test BenchMark",function(){
browser.getTitle().then(function (name) {
console.log(name);
browser.sleep(2000);
element(by.linkText("Manage Benchmarks")).click();
browser.sleep(4000)
//element(by.xpath("//main[#class='ng-scope']//a[text()='Create Benchmark']")).click();
console.log("megha");
element(by.model("$ctrl.benchmark.name")).sendKeys("bench");
element(by.buttonText("Save")).click();
console.log(megha);
element(by.xpath("//button[#class='dropdown-toggle']")).click();
console.log("dropdown clicked")
});
The behavior which you are expecting will not be handled by Protractor, it will be by testing framework(ex: Jasmine). But
"Jasmine doesn't support failing early, in a single spec. The idea is to give
you all of the failures in case that helps figure out what is really wrong
in your spec"
You can use browser.wait() combined with Expected Conditions.
browser.wait() blocks control flow execution until a promise is resolved, and Expected Conditions all evaluate to a promise.
So in your case, you could use either presenceOf() and/or visibilityOf().
var EC = protractor.ExpectedConditions;
var el = element(by.model("$ctrl.benchmark.name"));
var present = EC.presenceOf(el); // wait for it to be added to DOM
var visible = EC.visibilityOf(el); // wait for it to be visible on page
browser.wait(EC.and(present, visible), 10000); // wait maximum of 10 seconds
// rest of code

How to stop automatically closing browser when writing protractor test cases

I am new to writing test cases using protractor for non angular application. I wrote a sample test case.Here the browser closes automatically after running test case.How can I prevent this. Here is my code
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
});
I was also struggling with a similar issue where i had a test case flow where we were interacting with multiple application and when using Protractor the browser was closing after executing one conf.js file. Now when I looked into the previous response it was like adding delay which depends on how quick your next action i performed or it was hit or miss case. Even if we think from debugging perspective most of the user would be performing overnight runs and they would want to have browser active for couple of hours before they analyze the issue. So I started looking into the protractor base code and came across a generic solution which can circumvent this issue, independent of any browser. Currently the solution is specific to requirement that browser should not close after one conf.js file is executed, then could be improved if someone could add a config parameter asking the user whether they want to close the browser after their run.
The browser could be reused for future conf.js file run by using tag --seleniumSessionId in command line.
Solution:
Go to ..\AppData\Roaming\npm\node_modules\protractor\built where your
protractor is installed.
Open driverProvider.js file and go to function quitDriver
Replace return driver.quit() by return 0
As far as my current usage there seems to be no side effect of the code change, will update if I came across any other issue due to this change. Snapshot of code snippet below.
Thanks
Gleeson
Snapshot of code snippet:
Add browser.pause() at the end of your it function. Within the function itself.
I found Gleeson's solution is working, and that really helped me. The solution was...
Go to %APPDATA%Roaming\npm\node_modules\protractor\built\driverProviders\
Find driverProviders.js
Open it in notepad or any other text editor
Find and Replace return driver.Quit() to return 0
Save the file
Restart your tests after that.
I am using
node v8.12.0
npm v6.4.1
protractor v5.4.1
This solution will work, only if you installed npm or protractor globally; if you have installed your npm or protractor locally (in your folder) then, you have to go to your local protractor folder and do the same.
I suggest you to use browser.driver.sleep(500); before your click operation.
See this.
browser.driver.sleep(500);
element(by.css('your button')).click();
browser.driver.sleep(500);
Add a callback function in It block and the browser window doesn't close until you call it.
So perform the action that you need and place the callback at your convenience
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function(callback) {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
// Have all the logic you need
// Then invoke callback
callback();
});
});
The best way to make browser NOT to close for some time, Use browser.wait(). Inside the wait function write logic for checking either visibilityOf() or invisibilityOf() of an element, which is not visible or it will take time to become invisible on UI. In this case wait() keep on checking the logic until either condition met or timeout reached. You can increase the timeout if you want browser visible more time.
var EC=protractor.ExpectedConditions;
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
browser.wait(function(){
EC.invisibilityOf(submitBtnElm).call().then(function(isPresent){
if(isPresent){
return true;
}
});
},20000,'error message');
});
});
I'm sure there is a change triggered on your page by the button click. It might be something as subtle as a class change on an element or as obvious as a <p></p> element with the text "Saved" displayed. What I would do is, after the test, explicitly wait for this change.
[...]
return protractor.browser.wait(function() {
return element(by.cssContainingText('p', 'Saved')).isPresent();
}, 10000);
You could add such a wait mechanism to the afterEach() method of your spec file, so that your tests are separated even without the Protractor Angular implicit waits.
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
browser.pause(); // it should leave browser alive after test
});
browser.pause() should leave browser alive until you let it go.
#Edit Another approach is to set browser.ignoreSynchronization = true before browser.get(...). Protractor wouldn't wait for Angular loaded and you could use usual element(...) syntax.
Protractor will close browsers, that it created, so an approach that I am using is to start the browser via the webdriver-reuse-session npm package.
DISCLAIMER: I am the author of this package
It is a new package, so let me know if it solves your problem. I am using it with great success.