Protractor: How to properly wait after a click? - selenium

I am using Protractor for e2e testing. The tests should first enter too short username and passwords and because of Angular validators when clicked on a submit button (which is disabled) get rejected and stay put (this works!), then it should enter an username of correct length with also a password of a correct length, click on the submit button and NOT get redirected, because it's a false login. This fails... The last test requires to input correct login details and click on submit and should get redirected to the dashboard.
According to this answer https://stackoverflow.com/a/21785088/12360035 is all it would take to solve my problem that seems to throw the
- Failed: script timeout
(Session info: chrome=79.0.3945.130)
(Driver info: chromedriver=79.0.3945.16 (93fcc21110c10dbbd49bbff8f472335360e31d05-refs/branch-heads/3945#{#262}),platform=Windows NT 10.0.18362 x86_64)```
error for both of my tests.
How do I fix this?
My tests are written this way:
it('should enter too short username and password and NOT get redirected => stay put', () => {
element(by.css('#inputUser')).sendKeys('bah');
element(by.css('#inputPassword')).sendKeys('bah');
const btn = element(by.css('#loginSubmit'));
btn.click();
const curUrl = browser.getCurrentUrl();
expect(curUrl).toBe('http://localhost:4200/avior/login');
});
it('should enter incorrect username and password and NOT get redirected => stay put', () => {
const ele1 = element(by.css('#inputUser'));
const ele2 = element(by.css('#inputPassword'));
const btn = element(by.css('#loginSubmit'));
ele1.clear();
ele2.clear();
ele1.sendKeys('bah');
ele2.sendKeys('bahbahbah');
btn.click();
browser.waitForAngular();
const curUrl = browser.getCurrentUrl();
expect(curUrl).toBe('http://localhost:4200/avior/login');
});
it('should enter correct username and password and get redirected to /avior/dashboard', () => {
const ele1 = element(by.css('#inputUser'));
const ele2 = element(by.css('#inputPassword'));
const btn = element(by.css('#loginSubmit'));
ele1.clear();
ele2.clear();
ele1.sendKeys('Chad');
ele2.sendKeys('chadchad');
btn.click();
browser.waitForAngular();
const curUrl = browser.getCurrentUrl();
expect(curUrl).toBe('http://localhost:4200/avior/dashboard');
});
UPDATE
A jwt token is sent as a cookie in response, that might be part of the problem. I can't seem to find info online on how to handle cookies with Protractor..

Waits in Protractor
Wait for the element to Present
this.waitForElementPresent = function (element) {
return browser.wait(() => (element.isPresent()), 30000);
}
Wait for the element to Display
this.waitForElementDisplayed = function (element) {
return browser.wait(() => (element.isDisplayed()), 30000);
}
Sleep Condition
this.sleep = function (sec) {
browser.sleep(sec * 1000);
}
Expected Conditions
this.waitForElementVisibility = function () {
let EC = ExpectedConditions;
return browser.wait(EC.visibilityOf(), 30000);
}

According to this question Failed: script timeout: result was not received in 11 seconds From: Task: Protractor.waitForAngular() - Locator: By(css selector, #my-btn) adding browser.waitForAngularEnabled(false); before the button clicks seems to have solved the errors..

Related

AssertionError: Timed out retrying after 4000ms: Expected to find element: `//*[#id="nav-link-accountList-nav-line-1"]`, but never found it

LoginPage.js
class Login{
elements =
verifyUserName(verifyUserName){
this.elements.verifyLogin().should('have.text',verifyUserName);
}
}
//export default Login;
export default new Login();
LoginTest.cy.js
import Login from "../PageObjects/LoginPage";
describe('Page Object Model Pattern in Cypress', () => {
beforeEach(() => {
cy.visit('/')
});
it('Should Login to Home Page Test', () => {
cy.fixture('testData').then((data) => {
Login.verifyUserName(data.expectedusername)
})
})
})
HTML of the element-
<span id="nav-link-accountList-nav-line-1" class="nav-line-1 nav-progressive-content">Hello, S*****N</span>
When I'm trying to run these two files in cypress getting assertion error
"assertexpected <span#nav-link-accountList-nav-line-1.nav-line-1.nav-progressive-content> to have text Hello, S****N".
Basically it's fetching the id & class and asserting with the expected text. Can anyone please suggest any solutions? TIAyour text
I understood that you need to grab text of an element and assert that grabbed text is equal to some expected text.
//grabbed element via Id and saved into $ele using .then command
cy.get("#nav-link-accountList-nav-line-1").then(($ele) => {
//grabbed text value of the element in const txtvalue
const txtValue = $ele.text()
//did chai assertion to be equal to expected text
expect(txtValue).to.be.eq("Hello, S*****N")}

How to fix assertion error using playwright?

I'm using playwright to do e2e testing to check if the email is exists or not, and while I run my tests its said :
"Finished test flow with status passed"
But its show me that the test is failed because i have assertion error and not because i do something wrong
this is a piece my code:
const fillEmail = async (page: Page, value: string) =>
await page.fill("email-for-test", value);
const fillPassword = async (page: Page, value: string) =>
await page.fill("password-for-test", value);
await fillName(page, name);
await fillEmail(page, email);
const res = await page.locator('.email-error').innerText(); // return error string
expect(res).toContain("Email is already in used");
and i got error, you can see in the picture that I uploaded
any idea how to remove or fix this error
You code actually works. You can also use page.textContent()
const res = await page.locator('.email-error').innerText();
expect(res).toContain("Email is already in use");
const text = await page.textContent('.email-error');
expect(text).toContain("Email is already in use");
How about you just use this:
await expect(page.locator('.email-error')).toContainText(
'Email is already in used',
{timeout: 7000}
)
Also Check if the last word of the assertion message is used or use.
You can also use the text selector and assert it to be visible. Something like this:
await expect(page.locator('text=Email is already in use')).toBeVisible({
timeout: 7000,
})
i soulve this one by upgrade playwright library,
From v1.15 to v1.25

A better way to handle async saving to backend server and cloud storage from React Native app

In my React Native 0.63.2 app, after user uploads images of artwork, the app will do 2 things:
1. save artwork record and image records on backend server
2. save the images into cloud storage
Those 2 things are related and have to be done successfully all together. Here is the code:
const clickSave = async () => {
console.log("save art work");
try {
//save artwork to backend server
let art_obj = {
_device_id,
name,
description,
tag: (tagSelected.map((it) => it.name)),
note:'',
};
let img_array=[], oneImg;
imgs.forEach(ele => {
oneImg = {
fileName:"f"+helper.genRandomstring(8)+"_"+ele.fileName,
path: ele.path,
width: ele.width,
height: ele.height,
size_kb:Math.ceil(ele.size/1024),
image_data: ele.image_data,
};
img_array.push(oneImg);
});
art_obj.img_array = [...img_array];
art_obj = JSON.stringify(art_obj);
//assemble images
let url = `${GLOBAL.BASE_URL}/api/artworks/new`;
await helper.getAPI(url, _result, "POST", art_obj); //<<==#1. send artwork and image record to backend server
//save image to cloud storage
var storageAccessInfo = await helper.getStorageAccessInfo(stateVal.storageAccessInfo);
if (storageAccessInfo && storageAccessInfo !== "upToDate")
//update the context value
stateVal.updateStorageAccessInfo(storageAccessInfo);
//
let bucket_name = "oss-hz-1"; //<<<
const configuration = {
maxRetryCount: 3,
timeoutIntervalForRequest: 30,
timeoutIntervalForResource: 24 * 60 * 60
};
const STSConfig = {
AccessKeyId:accessInfo.accessKeyId,
SecretKeyId:accessInfo.accessKeySecret,
SecurityToken:accessInfo.securityToken
}
const endPoint = 'oss-cn-hangzhou.aliyuncs.com'; //<<<
const last_5_cell_number = _myself.cell.substring(myself.cell.length - 5);
let filePath, objkey;
img_array.forEach(item => {
console.log("init sts");
AliyunOSS.initWithSecurityToken(STSConfig.SecurityToken,STSConfig.AccessKeyId,STSConfig.SecretKeyId,endPoint,configuration)
//console.log("before upload", AliyunOSS);
objkey = `${last_5_cell_number}/${item.fileName}`; //virtual subdir and file name
filePath = item.path;
AliyunOSS.asyncUpload(bucket_name, objkey, filePath).then( (res) => { //<<==#2 send images to cloud storage with callback. But no action required after success.
console.log("Success : ", res) //<<==not really necessary to have console output
}).catch((error)=>{
console.log(error)
})
})
} catch(err) {
console.log(err);
return false;
};
};
The concern with the code above is that those 2 async calls may take long time to finish while user may be waiting for too long. After clicking saving button, user may just want to move to next page on user interface and leaves those everything behind. Is there a way to do so? is removing await (#1) and callback (#2) able to do that?
if you want to do both tasks in the background, then you can't use await. I see that you are using await on sending the images to the backend, so remove that and use .then().catch(); you don't need to remove the callback on #2.
If you need to make sure #1 finishes before doing #2, then you will need to move the code for #2 intp #1's promise resolving code (inside the .then()).
Now, for catching error. You will need some sort of error handling that alerts the user that an error had occurred and the user should trigger another upload. One thing you can do is a red banner. I'm sure there are packages out there that can do that for you.

WebdriverIO Browser.click statement gives is not a function error

I am fairly new to WebDriverIO framework, I was trying to automate below scenario:
const assert = require('assert');
describe('Second Test With WebDriverIO', () => {
it('Click the button for WebDriverIO Page', () => {
browser.url('http://www.kevinlamping.com/webdriverio-course-content/');
var title = browser.getTitle();
assert.strictEqual(title,'Robot Parts Emporium');
//browser.click('.shop-callout a');
$('.shop-callout a').click();
title = browser.getTitle();
assert.strictEqual(title,'Totally Not Evil Sentient Robot - Robot Parts Emporium');
});
});
However, I get an error mentioning "[chrome windows nt #0-0] browser.click is not a function"
But I use $('.shop-callout a').click(); instead of browser.click('.shop-callout a'); then it all works fine.
const assert = require('assert');
describe('Second Test With WebDriverIO', () => {
it('Click the button for WebDriverIO Page', () => {
browser.url('http://www.kevinlamping.com/webdriverio-course-content/');
var title = browser.getTitle();
assert.strictEqual(title,'Robot Parts Emporium');
//browser.click('.shop-callout a');
$('.shop-callout a').click();
title = browser.getTitle();
assert.strictEqual(title,'Totally Not Evil Sentient Robot - Robot Parts Emporium');
});
});
Any help would be appreciated.
Use browser.elementClick(elementId), instead of browser.click(), as this is the correct method name as per webdriver protocol.
See below:-
https://w3c.github.io/webdriver/#element-click
$(selector).click() is a custom method provided by webdriverio and they have used the same method as mentioned above.

Unable to find element and send keys

So just a brief overview, I'm unable to send keys to a edit text field for android. I've successfully sent keys to this element via browser but in order to test the mobile application fully, I'd like to run e2e tests on a device using Appium.
I've successfully got Appium to click button elements but am having a hard time getting it to send keys to an edit field element.
Am I able to find elements by model when testing with android as I have set in my forgot-pin-page.js?
pin-reset-page.js
var pinResetPage = function() {
describe('The Reset Pin Flow', function () {
forgotPinPage = forgotPinPageBuilder.getForgotPinPage(),
describe('The Forgot Pin Page', function () {
it('should allow the user to enter their MSISDN and continue',
function () {
forgotPinPage.enterMsisdn('123123123');
forgotPinPage.doForgotPin();
expect(securityPage.isOnSecurityPage()).toBe(true);
});
});
}
forgot-pin-page.js
'use strict';
var ForgotPin = function () {
var forgotPinPageContent = element(by.id('forgot')),
msisdnInput = element(by.model('data.msisdn')),
return {
enterMsisdn: function (msisdn) {
return msisdnInput.sendKeys(msisdn);
}
};
module.exports.getForgotPinPage = function () {
return new ForgotPin();
};
The error i'm getting is
? should allow the user to enter their MSISDN and continue
- Error: Timeout - Async callback was not invoked within timeout spe
cified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
Not sure if this is the correct solution but it worked for me. I downgraded jasmine2 to jasmine and that seemed to resolved the async timeouts I was having.