how I can run cypress script with the variable provided by user - cypress

I have cypress script that runs on different environment and the spec files look like this
describe('Whitelabel Login', () => {
it('Whitelabel Login', () => {
const whitelabelBaseUrl = whitelabelUrl =>
whitelabelUrl.replace('://', '://motivaction.')
cy.visit(whitelabelBaseUrl(Cypress.config('whitelabelUrl')))
cy.screenshot('Whitelbel Login page', { capture: 'fullPage' })
cy.visit(`${whitelabelBaseUrl(Cypress.config('whitelabelUrl'))}/logout`)
cy.screenshot('Whitelbel Logout page', { capture: 'fullPage' })
})
})```
So when I am running the script npx cypress run --env name=qa wl=seedling
then I want `motivaction` to be replaces by seedling is there any way that I can achieve it

You can reference variables passed in through the --env flag in the CLI via Cypress.env('var-name'). Cypress documentation here
const whitelabelBaseUrl = whitelabelUrl.replace('://', `://${Cypress.env('wl')}.`)
Also, pass several env variables using commas and no space. See docs here
npx cypress run --env name=qa,wl=seedling

Related

Cypress - Unable to run multiple tests

I am very new to cypress automation and have been following though some examples and have ran into an issue that does not appear to be addressed in any video I have seen, where multiple tests in the same 'describe' do not run as expected.
If I create the following code & run it, it all works perfectly:-
describe('My First Test', () => {
it('Open Google', () => {
cy.visit('https://google.co.uk')
cy.get('#L2AGLb > .QS5gu').click()
cy.get('.gLFyf').type('Automation Step by Step{Enter}')
})
})
I have then attempted to split up the test into individual tests, as follows:-
describe('My First Test', () => {
it('Open Google', () => {
cy.visit('https://google.co.uk')
})
it('Confirm warning', () => {
cy.get('#L2AGLb > .QS5gu').click()
cy.get('.gLFyf').type('Automation Step by Step{Enter}')
})
it('Confirm warning', () => {
cy.get('.gLFyf').type('Automation Step by Step{Enter}')
})
})
The problem now is that after opening Chrome and then going into the next test, which should allow me to type the text, a 'default blank page' is displayed and the tests then fail.
What am I missing here to be able to run these three tests fully?
Code in VS Code
Error after opening Chrome & attempting to type in box
As above really, I was hoping to be able to run all three simple tests together.
EDIT - I rolled back my version of Cypress to 10.10.0 and it works perfectly, so no idea what has changed on the latest version released yesterday.
Try it with Test Isolation turned to false.
Best Practice: Tests should always be able to be run independently from one another and still pass
This was added in Cypress 12.0.0.
But if you want to play without it,
Test Isolation Disabled
testIsolation
beforeEach test
true
- clears page by visiting about:blank
- clears cookies in all domains
- local storage in all domains
- session storage in all domains
false
does not alter the current browser context
cypress.config.js
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
testIsolation: false,
},
})
You should visit your page for every test. You can put the cy.visit in a beforeEach function.

Cypress + yarn/npm won’t run a CLI command in `after:run`, only in `before:run`

I want Cypress to execute custom scripts before and after running the specs suite.
The before:run and after:run APIs look perfect for that.
But the same snippet that works perfectly in before:run doesn’t seem to work in after:run:
module.exports = {
e2e: {
setupNodeEvents(on, config) {
on("before:run", details => {
console.log("Before run:")
exec("npm run cal", {}, handleExecOutput)
})
on("after:run", results => {
console.log("After run:")
exec("npm run cal", {}, handleExecOutput)
})
},
},
};
The cal script is defined in package.json as simply calling the native cal command, as a minimal test.
This is logging "Before run" and the calendar (not exactly together) before running the specs, and only "After run" after running the specs. However, if I change npm run cal to simply cal, the command is executed in both cases.
I’ve tried it with and without promises, with yarn and npm, always the same result. What am I missing?

Cypress: How do I conditionally skip a test by checking the URL

How do I conditionally skip a test if the URL contains "xyz"?
some tests that run in the QA environment "abc" should not be run in Production "xyz" environment.
I've not been able to find a good example of conditionally checking for environment to trigger a test. The baseURL needs to be checked dynamically and the test skipped preferably in the beforeEach.
running cypress 6.2.0
beforeEach(() => {
login.loginByUser('TomJones');
cy.visit(`${environment.getBaseUrl()}${route}`);
});
it('test page', function () {
if environment.getBaseUrl().contains("xyz")
then *skip test*
else
cy.intercept('GET', '**/some-api/v1/test*').as('Test'););
cy.get('#submitButton').click();
})
Potential Solution (tested and tried successfully):
I used a combination of filtering (grouping) and folder structures via CLI
I set folders /integrations/smokeTest/QA and /integrations/smokeTest/Prod/
1.QA Test Run:
npm run *cy:filter:qa* --spec "cypresss/integration/smokeTests/QA/*-spec.ts"
2.Run All (both QA and PROD tests)
npm run cypress:open --spec "cypresss/integration/smokeTests/*/*-spec.ts"
3. Prod Test Run:
npm run cy:filter:prod --spec "cypresss/integration/smokeTests/PROD*/*-spec.ts"
Normally I wouldn't write a custom command just to exercise one Cypress command, but in this case it's useful to obtain the global test context this.
Using the function form of callback with the custom command allows access to this, then you are free to use arrow functions on the test themselves.
Cypress.Commands.add('skipWhen', function (expression) {
if (expression) {
this.skip()
}
})
it('test skipping with arrow function', () => {
cy.skipWhen(Cypress.config('baseUrl').includes('localhost'));
// NOTE: a "naked" expect() will not be skipped
// if you call your custom command within the test
// Wrap it in a .then() to make sure it executes on the command queue
cy.then(() => {
expect('this.stackOverflow.answer').to.eq('a.better.example')
})
})
I would add a helper method which you can call from any Mocha.Context (at the time of writing, any it, describe, or context block).
// commands.ts
declare global {
// eslint-disable-next-line #typescript-eslint/no-namespace
namespace Cypress {
interface Chainable {
/**
* Custom command which will skip a test or context based on a boolean expression.
*
* You can call this command from anywhere, just make sure to pass in the the it, describe, or context block you wish to skip.
*
* #example cy.skipIf(yourCondition, this);
*/
skipIf(expression: boolean, context: Mocha.Context): void;
}
}
}
Cypress.Commands.add(
'skipIf',
(expression: boolean, context: Mocha.Context) => {
if (expression) context.skip.bind(context)();
}
);
And from your spec:
describe('Events', () => {
const url = `${environment.getBaseUrl()}${route}`;
before(function () {
cy.visit(url);
cy.skipIf(url.includes('xyz'), this);
});
context('Nested context', () => {
it('test', function () {
cy.skipIf(url.includes('abc'), this);
expect(this.stackOverflow.answer).to.be('accepted');
});
});
});
Now you have a reusable custom command that you can call from anywhere to conditionally skip tests based on any expression that evaluates to a boolean. Careful of classic JS equality and definition gotchas (read more about equality in JS here).

Directory path is incorrect when running from cypress test runner

When I login from normal browser the login is successful with the URL : http://neelesh.zapto.org:8084/EnrolMe/indHome.html
But when I run the script from Cypress the directory location is not appended and the new URL after login is formed as : http://neelesh.zapto.org:8084/__/indHome.html
I have tried setting cypress.json with
{
"chromeWebSecurity": false,
"modifyObstructiveCode" : false
}
I have tried on chrome/electron(head and headless).
Below is my code snippet:
describe('My First Test Suite', function() {
it('My First test case', function() {
cy.visit("http://neelesh.zapto.org:8084/EnrolMe")
cy.get("#login").click()
cy.get("input[value='Individual']").click()
cy.get("#username").type('1234567890')
cy.get("#pwd").type('0646')
Cypress.Cookies.debug(true)
cy.clearCookies()
cy.get("#login").click()
cy.wait(6000)
})
})
When I run the script from Cypress the directory location is not appended and the new URL after login is formed as : http://neelesh.zapto.org:8084/__/indHome.html
It should be redirected as : http://neelesh.zapto.org:8084/EnrolMe/indHome.html
Can anyone help me on this?
This sounds like an issue with "Frame Busting". There's a related discussion for Cypress GitHub Issue #992 which may lend some help.
Your application code may contain problematic frame busting code like the following:
if (window.top !== window.self) {
window.top.location.href = window.self.location.href;
}
You can get around this by changing your application code's reference to window.self from the Application Window to the Cypress Test Runner window (window.top).
Cypress emits a series of events as it runs in your browser. You can use the emitted window:before:load application event to ensure it's done before you attempt to login.
// cypress/support/index.js
Cypress.on('window:before:load', (win) => {
Object.defineProperty(win, 'self', {
get: () => {
return window.top
}
})
})

Protractor passing parameters in script run command

I need to pass the credentials in command running a script.
For now, I am using in protractor file following part:
onPrepare: function () {
jasmine.getEnv().addReporter(new SpecReporter({
spec: {
displayStacktrace: true
}
}));
if (browser.params.Url == 'http://devel/') {
browser.params.webmaster='abc';
browser.params.webmaspass='foo';
}
//(other environments)
else {
console.log('-------------error during log in');
}*/
}
and it was working fine, but I need to change it - I can't pass credentials in this way. I thought about changing it to:
if (browser.params.Url == 'http://devel/') {
browser.params.webmaster='';
browser.params.webmaspass='';
}
and run the script using
npm run dev-script --browser.params.Url='http://devel/' --browser.params.webmaster='abc' --browser.params.webmaspass='foo'
where package.json I have:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev-script": "protractor --params.Url=http://devel/ --browser.params.webmaster='' --browser.params.webmaspass=''"
},
(or any variation) But it fails - I can't update params during running script, I need to write down the credentials in the code (which I find a little unsafe)
I found issues like Protractor needs password for login => insecure? but it about Google Auth problems
Any idea?
You need to remove the variable assignment in the onPrepare. You are overwriting what you are passing in from the command line by setting it to an empty string.
When you pass them in from the command line they will be availble on the params object. There is no need to set them again in your onPrepare. Add a console.log() in your onPrepare and you will see.
Run it from the command line like this: protractor conf.js --params.webmaster=abc --params.webmaspass=foo --params.url=http://devel/
Again, if you log them in your onPrepare you will see that it is working. The way you currently have it you are just overwriting the values you are passing in through the command line.
onPrepare: function () {
jasmine.getEnv().addReporter(new SpecReporter({
spec: {
displayStacktrace: true
}
}));
if (browser.params.Url == 'http://devel/') {
consoel.log(browser.params.webmaster) //should be abc
console.log(browser.params.webmaspass) //should be foo
}
//(other environments)
else {
console.log('-------------error during log in');
}*/
}
Another way you can do this is to set some environment variables before your test run and then you can access them in your scripts by using process.env.envVariableName or ${envVariableName}. Both ways will work.
set DEVEL_WEBMASTER=abc
set DEVEL_WEBMASPASS=foo
onPrepare: function () {
jasmine.getEnv().addReporter(new SpecReporter({
spec: {
displayStacktrace: true
}
}));
if (browser.params.Url == 'http://devel/') {
browser.params.webmaster=process.env.DEVEL_WEBMASTER;
browser.params.webmaspass=process.env.DEVEL_WEBMASPASS;
}
//(other environments)
else {
console.log('-------------error during log in');
}*/
}
Just remember that if you use this method you would have to set the variables for each session. If you are planning to automate these tests using a CI environment you can just add them there as secret variables (if you have that option) and they will always be there ready and waiting. There will be no need to set them manually during each build.
What I did it here was create the scripts in my package.json:
scripts: {
"automation-test": "concurrently --raw --kill-others \"./node_modules/.bin/webdriver-manager start\" \"sleep 5 && ./node_modules/.bin/protractor configuration/protractor.config.js\"",
"automation:pending": "TAGS=#pending npm run automation-test"
}
And in my protractor.conf.js I just assign the value to a variable so I can use in my config. Like this:
let tags = process.env.TAGS;
Then the command that I run is just this:
npm run automation:pending
but I could pass the TAGS like this as well:
npm run automation-test TAGS=#pending
I have not seen the configuration file on the parameters of the command line. you must specify the configuration file:
example: protractor config.js --params ......
Do this in your script file: i have added a config file after the command protractor
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev-script": "protractor config.js --params.Url=http://devel/ --browser.params.webmaster='' --browser.params.webmaspass=''"
},

Resources