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();
// . . .
});
Related
I am trying to write tow If Statements in which, if the conditions are coming alternately then my code is working fine.
But when both Statements are true together then the second If Statement always skipped because there is a time difference of 5-6 seconds after the first condition executed.
So even though second condition is valid ( waiting for a window to appear) it never went inside the second if-Statement.
I tried writing timeout but it didn't work in TestCafe.
Someone please help if there is any inbuild function to be use for If-Condition just like it is there for assertion -
// await t.expect('.boarding-pass', { timeout: 10000 });
Similar option is not working under If Condition -
// if ( '.boarding-pass'.exists, { timeout: 10000 }){ do something}
It is working only if the Boarding Pass Screen is appearing, if not then it is waiting for 10 seconds and skip second If Statement.
I am not putting the codes for now. If you really need real codes to resolve my issue then I will try to recreate it using some public application.
You can use the built-in Wait Mechanism for Selectors to conditionally execute test statements.
For example, the following code waits for two elements to appear in DOM (you can specify the timeout option), and if an element exists and is visible, clicks it.
import { Selector } from 'testcafe';
fixture('Selector')
.page('http://devexpress.github.io/testcafe/example');
test ('test1',async (t)=\> {
const selector1 = Selector('#remote-testing');
const selector2 = Selector('#remote-testing-wrong', { timeout: 10000 } ); //wrong id, it will never appear
const element1 = await selector1();
const element2 = await selector2();
if(element1 && element1.visible) {
await t.click(selector1);
}
if(element2 && element2.visible) {
await t.click(selector2);
}
});
Please note, that you should use this approach only if the page contains elements that appear occasionally and unpredictably (like a chat window from a third-party component), and you can't turn them off in a test. If an element always appears on executing the test scenario, the recommended way is to use built-in wait mechanisms for actions like click, typetext, etc
tl;dr: When I run my test case, steps executed seem to work, but the test bails out early on a failure to find an element that hasn't even loaded yet. It seems like the waits I have around locating certain elements are loaded/launched as soon as the test is launched, not when the lines should actually be executed in the test case. I think this is happening because the page is barely (correctly) loaded before the "search" for the element to verify the page has loaded bails out. How do I wrangle the event loop?
This is probably a promise question, which is fine, but I don't understand what's going on. How do I implement my below code to work as expected? I'm working on creating automated E2E test cases using Jasmine2 and Protractor 5.3.0 in an Angular2 web app.
describe('hardware sets', () => {
it('TC3780:My_Test', async function() {
const testLogger = new CustomLogger('TC3780');
const PROJECT_ID = '65';
// Test Setup
browser.waitForAngularEnabled(false); // due to nature of angular project, the app never leaves zones, leaving a macrotask constantly running, thus protractor's niceness with angular is not working on our web app
// Navigate via URL to planviewer page for PROJECT_ID
await planListingPage.navigateTo(PROJECT_ID); // go to listing page for particular project
await planListingPage.clickIntoFirstRowPlans(); // go to first plan on listing page
await planViewerPage.clickOnSetItem('100'); // click on item id 100 in the plan
});
});
planViewerPage.po.ts function:
clickOnSetItem(id: string) {
element(by.id(id)).click();
browser.wait(until.visibilityOf(element(by.css('app-side-bar .card .info-content'))), 30000); // verify element I want to verify is present and visible
return expect(element(by.css('app-side-bar .card .info-content')).getText).toEqual(id); //Verify values match, This line specifically is failing.
}
This is the test case so far. I need more verification, but it is mostly done. I switched to using async function and awaits instead of the typical (done) and '.then(()=>{' statement chaining because I prefer not having to do a bunch of nesting to get things to execute in the right order. I come from a java background, so this insanity of having to force things to run in the order you write them is a bit much for me sometimes. I've been pointed to information like Mozilla's on event loop, but this line just confuses me more:
whenever a function runs, it cannot be pre-empted and will run entirely before any other code
runs (and can modify data the function manipulates).
Thus, why does it seem like test case is pre-evaluated and the timer's set off before any of the pages have been clicked on/loaded? I've implemented the solution here: tell Protractor to wait for the page before executing expect pretty much verbatim and it still doesn't wait.
Bonus question: Is there a way to output the event-loop's expected event execution and timestamps? Maybe then I could understand what it's doing.
The behavior
The code in your function is running asynchronously
clickOnSetItem(id: string) {
element(by.id(id)).click().then(function(){
return browser.wait(until.visibilityOf(element(by.css('app-side-bar .card .info-content'))), 30000);
}).then(function(){
expect(element(by.css('app-side-bar .card .info-content')).getText).toEqual(id);
}).catch(function(err){
console.log('Error: ' + err);
})
}
Whenever I try to run an automated test script written using JavaScript with Protractor, I can see that these two are actually ran in parallel independently of each other. Example:
it("Validation of ND account", function() {
// I logged in, and navigated to the page I need
// And this is where is gets intresting
console.log("\n");
console.log("Before getting number of users");
var numberOfUsers = element(by.xpath('//div[#viewid="userList"]//div[#class="results-count ng-binding"]')).getText().then(function(text) {
console.log(text);
});
console.log("After getting number of users");
// for (i=1, i<numberOfUsers, i++) {
// console.log(i);
// }
});
I assume that I get my logs in the same order - before, number and after, but first I get JS, and then Protractor (because it takes longer to load). This is a result of running this script in console output:
Started
Before getting number of users
After getting number of users
161
With that said, my problem is that if I want to open a page, get an element text and then perform some operations with it(run a FOR loop which is commented out), it won't let do this because it will return an unresolved promise before it even load the page. More precisely what it does is starts opening a page, right away before the page is loaded, it will run that loop, which depends on element from the page. The loop fails because the element isn't appeared yet, and the program still doesn't have its text attribute. So here is the question: is it possible to strictly adhere to the script sequence (to not let JS run scripts written after protractor commands before execution of protractor commands are completed) without JS timeouts or wait functions?
You need to understand Promises and work with the callbacks to make it work sequentially.
For this particular case, you can't wait for numberOfUsers for your test to keep going, you'll have to continue inside the callback function:
console.log("\n");
console.log("Before getting number of users");
element(by.xpath('//div[#viewid="userList"]//div[#class="results-count ng-binding"]')).getText().then(function(text) {
console.log(text);
// continue working here with "text"
console.log("After getting number of users");
});
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 porting an old game from C to Javascript. I have run into an issue with display code where I would like to have the main game code call display methods without having to worry about how those status messages are displayed.
In the original code, if the message is too long, the program just waits for the player to toggle through the messages with the spacebar and then continues. This doesn't work in javascript, because while I wait for an event, all of the other program code continues. I had thought to use a callback so that further code can execute when the player hits the designated key, but I can't see how that will be viable with a lot of calls to display.update(msg) scattered throughout the code.
Can I architect things differently so the event-based, asynchronous model works, or is there some other solution that would allow me to implement a more traditional event loop?
Am I making sense?
Example:
// this is what the original code does, but obviously doesn't work in Javascript
display = {
update : function(msg) {
// if msg is too long
// wait for user input
// ok, we've got input, continue
}
};
// this is more javascript-y...
display = {
update : function(msg, when_finished) {
// show part of the message
$(document).addEvent('keydown', function(e) {
// display the rest of the message
when_finished();
});
}
};
// but makes for amazingly nasty game code
do_something(param, function() {
// in case do_something calls display I have to
// provide a callback for everything afterwards
// this happens next, but what if do_the_next_thing needs to call display?
// I have to wait again
do_the_next_thing(param, function() {
// now I have to do this again, ad infinitum
}
}
The short answer is "no."
The longer answer is that, with "web workers" (part of HTML5), you may be able to do it, because it allows you to put the game logic on a separate thread, and use messaging to push keys from the user input into the game thread. However, you'd then need to use messaging the other way, too, to be able to actually display the output, which probably won't perform all that well.
Have a flag that you are waiting for user input.
var isWaiting = false;
and then check the value of that flag in do_something (obviously set it where necessary as well :) ).
if (isWaiting) return;
You might want to implement this higher up the call stack (what calls do_something()?), but this is the approach you need.