How to pass values from command line to cypress spec file? - cypress

I have a few different environments in which I am running Cypress tests (i.e. envA, envB, envC)
I run the tests like so:
npm run cypress:open -- --env apiEndpoint=https://app-envA.mySite.com
npm run cypress:open -- --env apiEndpoint=https://app-envB.mySite.com
npm run cypress:open -- --env apiEndpoint=https://app-envC.mySite.com
As you can see, the apiEndpoint varies based on the environment.
In one of my Cypress tests, I am testing a value that changes based on the environment being tested.
For example:
expect(resourceTiming.name).to.eq('https://cdn-envA.net/myPage.html')
As you can see the text envA appears in this assertion.
The issue I'm facing is that if I run this test in envB, it will fail like so:
Expected: expect(resourceTiming.name).to.eq('https://cdn-envB.net/myPage.html')
Actual: expect(resourceTiming.name).to.eq('https://cdn-envA.net/myPage.html')
My question is - how can I update the spec files so that the correct URL is asserted when I run in the different environments?
I am wondering if there's a way to pass a value from the command line to the spec file to tell the spec file which environment I'm in, but I'm not sure if that's possible.

You can directly use the Cypress.env('apiEndpoint') in your assertions, so that whatever you're passing via CLI, your spec files has the same value -
expect(resourceTiming.name).to.eq(Cypress.env('apiEndpoint'))
And if you want to check that when you pass https://app-envA.mySite.com and the url you expect in the spec file is https://cdn-envA.net/myPage.html, You can use:
expect(resourceTiming.name).to.eq(Cypress.env('apiEndpoint').replace('app', 'cdn').replace('mySite.com', 'net') + '/myPage.html')

Your best bet, in my opinion, is to utilize environment configs (envA.json, envB.json, etc)
Keep all of the property names in the configs identical, and then apply the values based on the environment:
// envA.json file
"env": {
"baseUrl": "yourUrlForEnvA.com"
}
// envB.json file
"env": {
"baseUrl": "yourUrlForEnvB.com"
}
That way, you can call Cypress.env('baseUrl') in your test, and no matter what, the right property should be loaded in.
You would call your environment from the command line with the following syntax:
"cypress run --config-file cypress\\config\\envA.json",
This sets up the test run to grab the right config from the start.
Calling the url for login, for example, would be something like:
cy.login(Cypress.env('baseUrl'))
Best of luck to you!

Related

Using different URLs for local and CI testing

I want to use Cypress to test locally and on CI at the same time. On CI, I would like to test a production version of my application, which has a different baseUrl than the local version, obviously. I am using the https://github.com/bjowes/cypress-ntlm-auth package to ause windows authentication for the CI, and to do so I have to call cy.ntlm line in my tests. I want to make an IF function that calls the cy.ntlm line ONLY if the baseUrl matches the production one. If the baseUrl is localhost then I would like the cy.ntlm line to be ignored. So my bottom line questions are, how do I let cypress know that I want to use 2 different URLs and how do I pack that into an IF statement? Thank you
You can check the baseUrl to conditionally call cy.ntlm,
const baseUrl = Cypress.config('baseUrl')! // use non-null assertion operator
const isLocal = baseUrl.includes('localhost')
if (!isLocal) {
cy.ntlm(...)
}
When using Typescript with Cypress you will get complaints because Typescript has no idea if you have set the baseUrl configuration or not.
You can overcome that by adding ! after getting the baseUrl value.
Ref Typescript - Non-null assertion operator
I separated the steps to make it clearer.
Assuming your cypress config file has the baseUrl. You can then update the baseUrl using the CLI during run time. For this create two different scripts with the staging and production URL's in your package.json like this:
"scripts": {
"test:local": "cypress run --config baseUrl=https://example.com/staging",
"test:ci": "cypress run --config baseUrl=https://example.com/production"
}
Then to run the scripts in CI use npm run test:ci and for local use npm run test:local.

How can I switch between env files based on the build command using godotenv?

I'm planning to use godotenv to setup different environments for my project but I am not sure how to switch between files like dev.env, uat.env, prod.env
I want to be able to just pass a value in my Docker command like RUN go build -o my-project --prod . and have godotenv pickup the relative env file - in this case prod.env (assuming this is the correct way.
Also, how can I make sure that the other env files don't get included in the build of a particular env.
I will advice you use the -X flag as suggested by Go Documentation on Command Line
-X importpath.name=value
Set the value of the string variable in importpath named name to value.
This is only effective if the variable is declared in the source code either uninitialized or initialized to a constant string expression. -X will not work if the initializer makes a function call or refers to other variables.
Note that before Go 1.5 this option took two separate arguments.
Such that you can then call any of your .env file referencing it location.
E.g. go build -ldflags="-X 'package_path.variable_name=new_value'"
That is
go build -ldflags "-X 'my/main/config.Version=v1.0.0'" -o $(MY_BIN) $(MY_SRC)
Hard coding your environment at the build stage seems odd to me. You don't want to build a diff image per env, that's wasteful.
The module documentation suggests a better approach:
Existing envs take precedence of envs that are loaded later.
The convention for managing multiple environments (i.e. development, test, production) is to create an env named {YOURAPP}_ENV and load envs in this order:
env := os.Getenv("FOO_ENV")
if "" == env {
env = "development"
}
godotenv.Load(".env." + env + ".local")
if "test" != env {
godotenv.Load(".env.local")
}
godotenv.Load(".env." + env)
godotenv.Load() // The Original .env

Does Cypress support pre-execution checks?

I run Cypress from the terminal using an npm script. I would like to run a series of checks before any tests in any spec are executed (e.g. to ensure env variables are set as expected).
If any check fails, I'd like to log some debug info and Cypress to mark each spec as failed.
Is something like this possible without having to have a custom script that executes before Cypress is started?
I've played around with the support file, but logging to the terminal and failing all test specs seems problematic.
Yes you can use Before Run API
on('before:run', (details) => {
/* ... */
})

Cypress browser refreshes browser on changing test file

I am using Cypress for end to end testing, and I would like to be able to see all run test suites, in the browser, even after they are run. Currently, after each test suite is completed (test which are stored in separate files), the browser reloads and I cannot see previously run tests, and after the final test suite, the browser closes. Is there an option to change this behavior so that I can run all test files, have all the results visible in the browser and that the browser doesn't close at the end?
I am currently running tests using this command: ./node_modules/.bin/cypress run --headed --spec 'cypress/integration/tests/*'
where /tests is the folder where I currently have my files.
I have added --no-exit but in this case cypress doesn't move to the next test file and only the first one runs.
A workaround solution could be to generate reports with Mochawsome, for each Test Spec, and then merge and view those rendered reports. The reports will contain the results from the tests, test bodies, any errors that occurred and some other bits of information.
If you read through the page in the link it shows you how to generate individual reports then combine them together, and then render them as HTML. These can then be viewed in the browser.
This command can be used to install what's needed npm install --save-dev mochawesome mochawesome-merge mochawesome-report-generator
and then add the Reporter configuration to the cypress.json:
{
"reporter": "mochawesome",
"reporterOptions": {
"reportDir": "cypress/results",
"overwrite": false,
"html": false,
"json": true
}
}
Keep in mind that it may not give you the level of detail that is contained in the Cypress Dashboard in the browser, for example, what was yielded from a request.
Cypress has a lot of possible command with a lot of possible config too.
Read this.
And if you use npm just run like this :
npm run cypress:open
and in your package.json :
"scripts": {
"cypress:open": "cypress open"
}

How can I use different Cypress.env() variables for Circle testing?

I am doing some automatic testing on Circleci, with different enviromental variables: I need one port for my local testing and a different one for Circleci.
How can I make Cypress do that? I tried making cypress.env.circle, but that does not seem to work
The cypress docs explain 5 ways to set variables.
To use one port locally and one on CircleCI I would:
Add a default port to cypress.json under the env section for local use so you don't have to think about it, and anyone else contributing will have a working version.
Set an environment variable in CircleCI named cypress_VAR_NAME which will override default in cypress.json
cypress.json example
{
"env": {
"the_port": 5000
}
}
CircleCI variable would then be cypress_the_port and you would read it in your specs as parseInt(Cypress.env('the_port')) (assuming your spec needs an integer for port)

Resources