I try to upload a file in ProTractor to the application, which is developed in Angular with Electron.
To do it manually I need to click on the "Browse" button and then select a file in the windows dialog "Open".
I managed already the part for providing of the path to the file and click on "Open" button on the dialog by using of AutoIt
var autoIt = require('autoit');
autoIt.Init();
autoIt.WinActivate("Open");
autoIt.WinWait("Open");
autoIt.ControlSetText("Open", "", "1148", appPath);
autoIt.ControlClick("Open", "", "1");
But this part of the code will be not executed after click on the "Browse" button
element(by.id('browseText')).click();
I guess that ProTractor waits for angular or for page loading, but because after clicking on the button the windows dialog is opened, the execution of further code is blocked. Also afterward I couldn't just output something in the console.
Is there an option to disable wait for page loading and to perform the action immediately after the click?
Unfortunately, the disabling of waiting for Angular didn't help as well as synchronization ignoring
browser.waitForAngularEnabled(false);
browser.ignoreSynchronization = true;
Thank you in advance for your support.
UPDATED
The problem is in the timing because when I try to execute the small following code
browser.waitForAngularEnabled(false);
element(by.id('browseText')).click()
.then(function () {
console.log("clicked");
});
browser.sleep(5000)
.then(function () {
console.log("5 sec are over!");
}); // wait 5 sec
browser.sleep(3000);
console.log("End");
The following happens:
Firstly the "End" will be added to the console without waiting for 3 seconds.
Afterward, the dialog will be opened, that means that the button was clicked
And at the end, the test will be failed with Error "function timed out, ensure the promise resolves within 90000 milliseconds".
Here is the output of this code:
[09:37:14] I/launcher - Running 1 instances of WebDriver
[09:37:14] I/direct - Using ChromeDriver directly...
..End
..F
Failures:
1) Scenario: Add an application # features\tst_General.feature:10
V Before # features\steps\DataGrid.js:20
V Before # features\steps\General.js:25
V When The "bounce" application has been added # features\steps\General.js:65
V After # features\steps\General.js:29
× After # node_modules\protractor-cucumber-framework\lib\resultsCapturer.js:2
5
Error: function timed out, ensure the promise resolves within 90000 milli
seconds
at Timeout._onTimeout (C:\Users\10050296\Documents\workspace\sm-protr
actor-automation\node_modules\cucumber\src\user_code_runner.js:61:18)
at ontimeout (timers.js:498:11)
at tryOnTimeout (timers.js:323:5)
at Timer.listOnTimeout (timers.js:290:5)
1 scenario (1 failed)
1 step (1 passed)
1m30.217s
Let's be clear.
This is work 100%:
browser.waitForAngularEnabled(false);
Protractor part, as I understand, also work. The Browser button is clicked.
So, the issue in the Autoit part. The question is - "How to run Autoit?"
Just add sleep to check is it waiting problem on the Autoit side:
element(by.id('browseText')).click();
browser.sleep(5000); // wait 5 sec
...
autoit code
...
If it works, so the issue in Autoit waiting.
Related
TestCafe 1.8.0,
Firefox 76.0 (any will do),
macOS 10.15.4.
My TestCafe tests (steps after useRole) are trying to execute even before useRole is completely done. Example:
import { Role } from 'testcafe';
const role = Role('http://example.com/login', async t => {
await t
.typeText('#login', 'username')
.typeText('#password', 'password')
.click('#sign-in'); // Redirects to http://example.com/session
});
fixture `My Fixture`;
test('My test', async t => {
await t
.navigateTo('http://example.com/')
.useRole(role);
.click()
.typeText('#search', 'query')
// Further tests.
.......
Role is being used -> user is redirected to: http://example.com/session at the end.
Once role execution is finished -> TestCafe goes back to My test AND it reloads http://example.com/ again.
This is a huge problem because between this one page reload for just a moment 'page is ready' and since TestCafe is working rapidly .click() is executed. Now page reloads so test execution stops. Once page loaded test brakes because it is trying to .typeText(...) without a .click().
Tried this solutions:
Wait until will work only first time. Second time when useRole used (from cache) code will execute even before this second page reload. .expect(getUrl()).eql('desiredurl', { timeout: 10000 })
As we all know hard wait .wait(3000) or slowing down tests .setTestSpeed(0.7) will work but it is not a good solution from code perspective. Tests still might fail from time to time and I need and want stability here.
With { preserveUrl: true } it would just reload http://example.com/session so it doesn't matter if this option is used. Reload is still happening.
Any ideas?
How can I let my test know to wait for exactly the same page reload without using any hardcoded waits, code sleep?
As far as I understand, the main issue is that the click action is executed on the wrong page for some reason. It does not wait until the page is completely reloaded. This behavior is unexpected. We would really appreciate it if you create a reproducible sample.
I agree that the use of wait or setTestSpeed is not a suitable solution.
I see that you tried to use assertions: .expect(getUrl()).eql('desiredurl', { timeout: 10000 }). I think this approach should work, but I cannot be sure because I couldn't reproduce the issue.
You can define your role with preserveUrl: true. Then, extract the useRole method as follows:
async function useRole (t, role) {
await t.useRole(role);
await t.expect(getUrl()).eql('http://example.com/session', {timeout: 10000 });
}
Now, you can use the new useRole(t, role) method, which will wait until the page is completely loaded.
Im using Protractor with Cucumber and Im facing this issue.
And Right-Click on the first record Sort Pair #
RQA\node_modules\cucumber\src\support_code_library_builder\define_helpers.js:90
TimeoutError: Wait timed out after 8109ms
at C:\Users\VBG5LLN\Documents\Automation Files\Automation RQA\node_modules\selenium-webdriver\lib\promise.js:2201:17
at ManagedPromise.invokeCallback_ (C:\Users\VBG5LLN\Documents\Automation Files\Automation RQA\node_modules\selenium-webdriver\lib\promise.js:1376:14)
at TaskQueue.execute_ (C:\Users\VBG5LLN\Documents\Automation Files\Automation RQA\node_modules\selenium-webdriver\lib\promise.js:3084:14)
at TaskQueue.executeNext_ (C:\Users\VBG5LLN\Documents\Automation Files\Automation RQA\node_modules\selenium-webdriver\lib\promise.js:3067:27)
at C:\Users\VBG5LLN\Documents\Automation Files\Automation RQA\node_modules\selenium-webdriver\lib\promise.js:2927:27
at C:\Users\VBG5LLN\Documents\Automation Files\Automation RQA\node_modules\selenium-webdriver\lib\promise.js:668:7
at processTicksAndRejections (internal/process/task_queues.js:97:5)
I already tried many changes but the error is present anyway.
I set 60000 in; allScriptsTimeout, getPageTimeout and defaultTimeoutInterval in conf.js
(And basically in every timeout flag I set an high number).
I delete all the steps in the function and the error is still present:
Then('Right-Click on the first record Sort Pair', async function (){
await browser.sleep(2000);
});
I fix the issue, in the previous step I clicked a button and wait for it with this;
await expect(browser.wait(EC.visibilityOf(ntwrkHomeObs.applyBtn), 8000));
await ntwrkHomeObs.applyBtn.click();
The button is visible since the page load and continues in the DOM after is clicked just hided inside a div that is visible again if clicks a "Show Options" button.
For some reason this causes the issue.
I deleted this line;
await expect(browser.wait(EC.visibilityOf(ntwrkHomeObs.applyBtn), 8000));
I am trying to test my website which is a non angular website through Protractor. My code is:
describe("Supplier Portal: Login ", function () {
//ui.setSmallScreenSize();
// ui.testLogger(100);
it("test", co.wrap(function* () {
browser.ignoreSynchronization = true;
yield browser.driver.get("https://cit.supplier.ext.here.com/");
yield element(by.xpath("//*[#id=\"rnav\"]/li[2]/a")).click();
var elmOK = element(by.xpath( "//*[#id=\"sign-in-email\"]"));
browser.driver.wait(protractor.until.elementIsVisible(elmOK.getWebElement()))
}));
});
But when I try to execute the code I got the following error:
Failed: No element found using locator: By(xpath, //*[#id="sign-in-email"])
But the element is there on the website.
Please advice what I'm doing wrong
Since you are working on a non-angular site and using browser.ignoreSynchronization = true, Protractor will not wait for the angular variable to become available, so it starts firing tests off because it thinks the app is ready, more info here.
You need to manipulate the Control Flow by using Expected Conditions so Protractor knows that it is waiting for something. This will make your tests more consistent and reliable.
A few examples to guide you:
Wait for an element to be loaded/present in the DOM:
var EC = protractor.ExpectedConditions;
var ele = element(by.css('div.class'));
browser.wait(EC.presenceOf(ele), 5000);
The 5000 parameter value I passed in says wait a maximum of 5 seconds, if not present in 5 seconds then fail.
Wait for an element visible:
browser.wait(EC.visibilityOf(ele), 5000);
Wait for an element to be clickable:
browser.wait(EC.elementToBeClickable(ele), 5000);
Again, it's important to note that these are implicit waits and they will wait a maximum of the time parameter provided. It is not a guaranteed amount of time to wait, they fire off ASAP when they find the element you told it to wait for.
I am looking for a solution, if it is possible to wait for the data entered by the user in protractor.
I mean test stop for a while and I can enter some value and then these data are used in further tests.
I tried to use javascript prompt, but I did not do much, maybe it is possible to enter data in OS terminal?
Please give me an example if it is possible.
I would not recommend mixing the automatic and manual selenium browser control.
That said, you can use Explicit Waits to wait for certain things to happen on a page, e.g. you can wait for the text to be present in a text input, or an element to become visible, or a page title to be equal to something you expect, there are different ExpectedConditions built-in to protractor and you can easily write your own custom Expected Conditions to wait for. You would have to set a reasonable timeout though.
Alternatively, you can pass the user-defined parameters through browser.params, see:
How can I use command line arguments in Angularjs Protractor?
Example:
protractor my.conf.js --params.login.user=abc --params.login.password=123
Then, you can access the values in your test through browser.params:
var login = element(by.id("login"));
login.sendKeys(browser.params.login.user);
If your data will reside in the console, you can get that data by using the following:
browser.manage().logs().get('browser').then(function(browserLogs) {
// browserLogs is an array which can be filtered by message level
browserLogs.forEach(function(log){
if (log.level.value < 900) { // non-error messages
console.log(log.message);
}
});
});
Then as mentioned in other posts, you can explicitly wait for a condition to be true by using driver.wait():
var started = startTestServer();
driver.wait(started, 5 * 1000,
'Server should start within 5 seconds');
driver.get(getServerUrl());
Or expected conditions if waiting for more than one condition, for example.
I had the same question. After a long search I found a solution with Protractor 5.3.2 that worked:
var EC = protractor.ExpectedConditions;
it('will pause for input...', function() {
browser.ignoreSynchronization = true
browser.waitForAngularEnabled(false);
// open web page that contains an input (in my case it was captchaInput)
browser.driver.get('https://example.com/mywebpagehere');
// waits for 15 sec for the user to enter something. The user shall not click submit
browser.wait(EC.textToBePresentInElementValue(captchaInput, '999'), 15000, "Oops :^(")
.then(function() {
console.log('Hmm... Not supposed to run!');
}, function() {
console.log('Expected timeout, not an issue');
});
browser.sleep(1000);
// submit the user input and execution proceeds (in my case, captchaButton)
captchaButton.click();
// . . .
});
I'm using angular-growl-v2 notifications in my app.
They work ok, the problem comes on my protractor tests. I have to use a TTL (around 6 seconds) as it is a requirement. Then I have the following test:
it('should send a request and notify the user about the result',function(){
detailPage.verifyEmailtButton.click().then(function(){
var expectedDiv = element(by.css('.alert-success'));
expect(expectedDiv).toBeDefined();
});
});
But it is always throwing an error:
NoSuchElementError: No element found using locator: By.cssSelector(".alert-success")
This does not happens when the TLL is -1.
Someone can help here? Thanks in advance.
angular-growl-2 uses $timeout, which doesn't play nicely with protractor: protractor waits for the timeout to end before it completes its sync with angular process.
So by the time it reaches your expect call, the timeout has elapsed and the alert is no longer there. Check out the Waiting for page synchronization section of this doc:
https://github.com/angular/protractor/blob/master/docs/timeouts.md
(This page relates to timeouts, which you don't appear to be experiencing, but since the default timeout is 11 seconds, it could well be that the entire process, including your 6 second TTL, takes place before a timeout happens)
There's a PR to angular-growl-v2 to use $interval instead of $timeout, but its currently waiting for tests:
https://github.com/JanStevens/angular-growl-2/pull/85
Explicitly wait for the alert to be present after clicking the button:
detailPage.verifyEmailtButton.click();
var EC = protractor.ExpectedConditions;
var expectedDiv = element(by.css('.alert-success'));
browser.wait(EC.presenceOf(expectedDiv), 10000, "No alert present");