Cypress tests removing certain attributes from the page - error-handling

Has anyone faced this with Cypress?
When I run my test using cypress, a particular test, keeps failing because hidden element is not showing up but when I run the same test manually, I can see the element with the hidden element showing up as soon as I enter value.
There is a field in our UI where if I pass invalid characters, then it should immediately show the hidden error element using aria, but this is not happening when running through cypress.
Desired behavior
When I run the same above test manually on the same field the result I am getting is this.
Cypress test Result:
Actual Result:
Code :

I think with <pvd-system-message> you have a shadow-root preventing access to the text inside you element.
Try
cy.get('#address-cityNameError')
.should('have.attr', 'message')
.shadow() // inside shadow-root
.should('contain', 'City contains invalid characters')
In case there are other tests with this problem, add includeShadowDom option to your config.
Ref Configuration options
cypress.config.js
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:1234',
includeShadowDom: true
}
})

Related

Cypress - run test in iframe

I'm trying to find elements in iframe but it doesn't work.
Is there anyone who have some system to run tests with Cypress in iframe? Some way to get in iframe and work in there.
It's a known issue mentioned here. You can create your own custom cypress command which mocks the iframe feature. Add following function to your cypress/support/commands.js
Cypress.Commands.add('iframe', { prevSubject: 'element' }, ($iframe, selector) => {
Cypress.log({
name: 'iframe',
consoleProps() {
return {
iframe: $iframe,
};
},
});
return new Cypress.Promise(resolve => {
resolve($iframe.contents().find(selector));
});
});
Then you can use it like this:
cy.get('#iframe-id')
.iframe('body #elementToFind')
.should('exist')
Also, because of CORS/same-origin policy reasons, you might have to set chromeWebSecurity to false in cypress.json (Setting chromeWebSecurity to false allows you to access cross-origin iframes that are embedded in your application and also navigate to any superdomain without cross-origin errors).
This is a workaround though, it worked for me locally but not during CI runs.
This works for me locally and via CI. Credit: Gleb Bahmutov iframes blog post
export const getIframeBody = (locator) => {
// get the iframe > document > body
// and retry until the body element is not empty
return cy
.get(locator)
.its('0.contentDocument.body').should('not.be.empty')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
// https://on.cypress.io/wrap
.then(cy.wrap)
}
spec file:
let iframeStripe = 'iframe[name="stripe_checkout_app"]'
getIframeBody(iframeStripe).find('button[type="submit"] .Button-content > span').should('have.text', `Buy me`)
that is correct. Cypress doesn't support Iframes. It is simple not possible at the moment. You can follow (and upvote) this ticket: https://github.com/cypress-io/cypress/issues/136

Vue CLI 3 Nightwatch page object configuration

I'm using Vue CLI 3 version 3.0.5.
In project configuration, I use Nightwatch as e2e test tool.
I try to use page objects, so I had nightwatch.config.js file in project root, and add page_objects_path inside like below:
{
page_objects_path : "/tests/e2e/page-objects"
}
Then I create page-objects folder as this path: /tests/e2e/page-objects.
Then I setup a page object Entry.js under that folder and try to use it in test:
/tests/e2e/page-objects/Entry.js
vmodule.exports = {
'Test Page Object': browser => {
browser
.url(process.env.VUE_DEV_SERVER_URL)
.waitForElementVisible('#app', 5000)
browser.page.Entry().sayHello()
browser.end()
}
}
And the error message shows:
Cannot read property 'Entry' of undefined .
It looks like my page object setup is not correct...
Could anyone help providing a correct implementation of NightWatch page object in Vue CLI v3.0.5 ? Thanks...
Ah, I know why it won't work.
Because nightwatch.config.js is a javascript file, I should export it first, then the plugin can read it.
module.export = {
page_objects_path : "/tests/e2e/page-objects"
}
Sorry for the dumb question.

Protractor - pass parameters from console to conf.js

I have config.js like below:
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
params: {
browser: 'chrome'
},
capabilities: {
'browserName': (params.browser || 'chrome'),
},
...
}
Now I would like to pass 'browser' parameter from console to run it on IE instead of Chrome by default:
protractor e2e/protractor.conf.js --params.browser='internet explorer'
or
protractor e2e/protractor.conf.js -- --params.browser='internet explorer'
I've tried many configuration but everytime I get:
[14:17:00] E/configParser - Error code: 105
[14:17:00] E/configParser - Error message: failed loading configuration file e2e/protractor.conf.js
[14:17:00] E/configParser - ReferenceError: params is not defined
Can anyone help how to do that?
not enough reputation for clarification :)
Are you sure that you call properly this part params.browser ? I mean params.
To my mind params is not defined. You work with object, so try this one: this.params.browser
If you define your config in config.js, why did you call protractor.conf.js ?
Finally, protractor has it's own globals. And there are some entry points where you can use it. For example you can use global protractor object "browser" in onPrepare(). To get access to the params should work something like "browser.params.browser". I am not sure that you can get access to globals within main conf file while it parsing. May be some workaround with process.argv will help you. Or rework your logic structure.
If your problem is to specify the browser name from cmd line, you can do as following:
protractor e2e/protractor.conf.js --browser='internet explorer'
And you can specify following params as same way:
--seleniumAddress=
--specs="['./src/**/*.e2e-spec.ts', '']"
--capabilities=<json string>
--suite=
Besides above reserved params, you can specify any params through --params.xxx format in cmd line and use browser.params.xxx format in script to use the xxx.
But the browser variable can't be used in anywhere in conf.js, it's only inited after the browser opened.
As protractor website said, you can use browser in onPrepare function and any place where is executed after protractor call onPrepare function.

Trying with Nightwatch + Browserstack to set up a simple login test, failing

Using "nightwatch": "^1.0.11" and "browserstack-local": "^1.3.4"
I have tried this many ways, but I cannot get the examples in the documentation to run.
I have a simple login page with a page object
module.exports = {
url: function() {
return this.api.launchUrl + '/login';
},
elements: {
email: {
selector: '#user_login_email'
},
password: {
selector: '#user_login_password'
},
button: {
selector: '#login-btn'
}
}
};
I then want to run a test to login into the site (NOTE: The first screenshot is fine)
module.exports = {
before(client) {
client.maximizeWindow();
},
'Login' : function (client) {
var login = client.page.login();
login.navigate();
client.waitForElementPresent('body', 500)
.saveScreenshot('tests_output/login.png');
login.setValue('#email', 'test#user.email')
.setValue('#password', 'Pa55w0rd')
.click('#button');
client.pause(1000)
.saveScreenshot('tests_output/login-complete.png');
},
after(client) {
client.end();
}
};
I get the following errors when trying to run the test through browserstack (with the local URL)
✖ login.test
– Login (5.196s)
An error occurred while running .setValue() command on <Element [name=#email]>: Error: First argument passed to .elementIdValue() should be a web element ID string. Received object.
at Function.validateElementId (node_modules/nightwatch/lib/api/protocol.js:36:19)
at ProtocolActions.elementIdValue (node_modules/nightwatch/lib/api/protocol.js:951:25)
at transport.locateElement.then.result (node_modules/nightwatch/lib/api-loader/element-command.js:106:54)
at process._tickCallback (internal/process/next_tick.js:68:7)
at process._tickCallback (internal/process/next_tick.js:68:7)
at process._tickCallback (internal/process/next_tick.js:68:7)
An error occurred while running .setValue() command on <Element [name=#password]>: Error: First argument passed to .elementIdValue() should be a web element ID string. Received object.
[...]
An error occurred while running .click() command on <Element [name=#button]>: Error: First argument passed to .elementIdClick() should be a web element ID string. Received object.
[...]
I have gotten successful tests to run; just not using the documented examples.
For example, the below code works fine to close a cookie message
client
.waitForElementPresent('.cookie-message__button', 5, true, function(result) {
client.elementIdClick(result.value[0].ELEMENT);
})
.saveScreenshot('tests_output/cookie-closed.png');
But obviously it's really long winded.
Any help for what I'm doing wrong would be awesome.
Using the following as an example for the Nightwatch config: https://github.com/browserstack/nightwatch-browserstack/blob/master/conf/local.conf.js with the local runner and running tests in parallel in 3 browsers: https://github.com/browserstack/nightwatch-browserstack/blob/master/scripts/local.runner.js
TL;DR: Documentation examples don't work with version 1.0.11; but Nightwatch and Browserstack are configured correctly as can get a suite to run (in Travis and locally), just with very long-winded code, which I hacked together.
I have created sample project for page objects model here. Also, sample login test is added using page_objects_path.
The compatibility for latest nightwatch version is also added. The latest version of nightwatch seems to have changes which are in compliant with w3c. So we need to use 'browserName' as capability instead of 'browser'

Concern regarding automation using Protractor

Am new to protractor. I found some errors while automating the URL using protractor. And I can access the URL manually and does not find any issues. Please find the code mentioned below and kindly clarify my concern.
Screenshot of cmd while executing the code
exports.config={
specs: ['try.js'],
//seleniumArgs: ['-browserTimeout=60']
capabilities:{
'browserName':'chrome',
},
baseUrl:'',
allScriptsTimeout:3000,
//getPageTimeout:5000,
framework:'jasmine2',
jasmineNodeOpts: {
defaultTimeoutInterval:56000,
isVerbose: true,
}
}
spec: try.js
===========
describe('first try',function(){
var EW=protractor.ExpectedConditions;
beforeEach(function(done){
ignoreSynchronization=true;
browser.get('');
});
it('open PO',function(){
//clicking login button
var login=element(by.linkText('Login'));
browser.wait(EW.presenceOf(login),10000);
login.click();
//clicking open Po dashboard icon/link
var po=element(by.linkText('Open PO'));
browser.wait(EW.presenceOf(po),20000);
po.click();
//entering value 100 in the fiter field
var e=element.all(by.repeater('colFilter in col.filters')).get(00).element(by.tagName('input'));
browser.wait(EW.presenceOf(e),10000);
e.sendKeys(100);
//selecting the filterd values and printing it in console
element.all(by.repeater('col in colContainer.renderedColumns track by col.uid').column('Entity')).getText().then(console.log);
});
});
Make sure you have ng-app defined on all of your pages. Protractor requires it to run. If the page has redirects or just takes some time before it loads, try something like this:
browser.get(websiteUrl);
browser.wait(function () {
return browser.executeScript('return !!window.angular');
}, 10000, 'Error: Angular was not found on the page within ten seconds');
This will wait up to ten seconds for angular to load up, and fail if it is not there.