Cypress recording - cypress

just wanted to ask if this is possible to change the location folder for recorded file? I am running tests for two different applications, one after another, and when tests are finished for both of them, I can only access the latest recording.
Thanks in advance!

You can add videosFolder attribute in your cypress config file with the folder path.
videosFolder: 'cypress/videos_project_2'
You can override the videosFolder path from the CLI, something like this:
npx cypress run --config videosFolder=cypress/videos_project_2
In your package.json, create two scripts like this:
"scripts": {
"test:project1": "npx cypress run --config videosFolder=cypress/videos_project_1",
"test:project2": "npx cypress run --config videosFolder=cypress/videos_project_2",
}
Then as per the project, directly run the commands:
npm run test:project1
//or
npm run test:project2

The easiest way is to set trashAssetsBeforeRuns.
See Videos
Cypress clears any existing videos before a cypress run. If you do not want to clear your videos folder before a run, you can set trashAssetsBeforeRuns to false.
cypress.config.js
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
video: true,
trashAssetsBeforeRuns: false
},
});

Related

Is there a way I can run a specified .spec file once all "x" .spec files have been run? Cypress

I want to do some clearing up after all .spec files have been run by Cypress. For this I created another .spec file that does several API calls. I need Cypress to run this .spec file only after all tests form all the other files have ran. One more thing, my .spec files are being run by Cypress in parallel mode, via 4 machines.
I found out there are the "after" hooks I could use, but as far as I read, these hooks apply per only one .spec file, not all of them.
This is not exactly the answer you are looking for, but maybe this information can be useful to you in some way:
One of the antipatterns I have heard multiple times from Cypress gurus is cleaning the application state using after or afterEach hooks.
If I remember correctly, the reasoning was that if the test fails or some step of the after hook fails, it will never get to the end of the script, thus we cannot be sure that the application state is prepared for the future tests.
That's why it is suggested to use before or beforeEach hooks, to prepare application state right before running tests.
If you decide to run some scripts before or after tests in different specs, then the support file can be useful, because it is rendered before each spec:
https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests#Support-file
As a final thought, if you want something to happen before or after running Cypress, then maybe the best way to accomplish this is to prepare a separate script and run it using whatever you use to run Cypress (node, docker, etc.).
Sorry that this answer got so long :)
To conclude my thoughts:
Better prepare the state for the tests, not clean up after them
Separate scripts can be run before or after tests, and they do not have to be inside Cypress (using node, bash, docker...)
Hope this helps!
To run a single spec out of process, take a look at the Module Api.
With this you can create a node script that can be run after all parallel processes have completed.
./scripts/e2e-run-cleanup.js
const cypress = require('cypress')
cypress
.run({
spec: './cypress/e2e/cleanup.cy.js', // your cleanup spec
})
.then((results) => {
console.log(results)
})
.catch((err) => {
console.error(err)
})
Some configuration:
cypress.config.js
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:1234',
excludeSpecPattern: ['cleanup.cy.js'], // exclude this one from the normal run
}
})
package.json
"scripts": {
...
"test:headless": "yarn cypress:run",
...
"cleanup": "yarn ./scripts/e2e-run-cleanup.js", // script to kick off
"posttest:headless": "yarn cleanup", // also after local run
// "post" prefix automatically
// runs this after "test:headless" script
...
}
main.yml
...
jobs:
install:
...
ui-chrome-tests:
...
cleanup:
...
needs: ui-chrome-tests # ensure tests have run
steps:
- run: yarn cleanup
You can use the After Run API for this use case:
module.exports = (on, config) => {
on('after:run', (results) => {
// run some code after the run
})
}
or
const { defineConfig } = require('cypress')
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
on('after:run', (results) => {
// run some code after the run
})
}
}
})

Running Cypress tests with TailwindCSS 3

I've been running my component tests via cypress open-ct for a while now, relying on importing /node_modules/tailwindcss/dist/tailwindcss.min.css.
Since upgrading to Tailwind v3 some of my tests are failing as there is no prebuilt CSS file I can import - everything is generated just in time.
For example, testing if a modal closes when clicking on a overlay that is fixed and full width fails as the whole modal is rendered so that it is inaccessible by Cypress.
Another side-issue that stems from not having access to Tailwind classes is that videos recorded when running tests in CI are unusable as they are just a bunch of random native elements.
I've been importing Tailwind like this at the top of each Test file (before describes)
import { mount } from '#cypress/vue'
import '/node_modules/tailwindcss/dist/tailwind.min.css'
import MultiSelectField from './MultiSelectField.vue'
import { ref } from "vue";
Any ideas how to include Tailwind (preferably globally) so tests won't fail?
You can use the Tailwind CLI to generate your stylesheet on the fly.
Add this plugin in cypress/plugins/tailwind.js (be sure to change the -i source from ./src/styles/globals.css to your base CSS file):
before(() => {
cy.exec('npx tailwindcss -i ./src/styles/globals.css -m').then(
({ stdout }) => {
if (!document.head.querySelector('#tailwind-style')) {
const link = document.createElement('style')
link.id = 'tailwind-style'
link.innerHTML = stdout
document.head.appendChild(link)
}
},
)
})
Then, load the plugin by importing it in cypress/support/index.js:
import '../plugins/tailwind'
You should also set up a separate config file for your component tests, such as cypress/support/component.js, and specify that in your cypress.json config file:
{
"component": {
"supportFile": "cypress/support/component.js",
},
"e2e": {
"supportFile": "cypress/support/e2e.js"
}
}
Then, only include import '../plugins/tailwind' in your cypress/support/component.js config file, so that you don't perform the JIT compilation for your E2E tests (since it's unnecessary).
Michael Hays' solution works, but it rebuilds the whole .css file every time changes to the code are made, which slows tests down. An alternative would be to run tailwind externally in watch mode.
npm i -D concurrently
package.json
"scripts": {
"test": "concurrently \"tailwindcss -i ./src/index.css -o ./dist/index.css --watch\" \"cypress open\" "
},
cypress/support/component.ts
import "../../dist/index.css";
I see you're using import '/node_modules/tailwindcss/dist/tailwind.min.css' which expects a pre-compiled bundle. If you have any customization added to the tailwind config, those would not be covered.
But if you can't use the generated css and don't have any tailwind customization, you could use the cdn version from https://cdn.tailwindcss.com/
Because you are running it in a test and don't want to add to possible "flakyness" of using remote dependency, you'll likely want to download that file and keep it in the repo and update it manually from time to time. You can also use some automation for getting the correct version from the cdn before running the test, but Ideally you'd use the generated css, since that's what you're shipping so that's the resource that should be getting tested.

NG-ANTD nz-tslint-rules migration not working

I was trying to update our production project which holds 500+ modules and we certainly need this tool to make it work because manually doing so would be a nightmare. I've been the whole afternoon trying to make it work even copying and pasting your import example and haven't manage to do so.
Our imports are like following in the whole project:
import {
NzTableModule,
NzCheckboxModule,
NzInputModule,
NzFormModule,
NzSelectModule,
NzDrawerModule,
NzDividerModule,
NzToolTipModule,
NzDatePickerModule,
} from 'ng-zorro-antd';
I'm using the following config:
{
"rulesDirectory": [
"nz-tslint-rules"
],
"rules": {
"nz-secondary-entry-imports": true
}
}
package.json:
"ng-zorro-antd": "^9.3.0",
"typescript": "~3.8.3",
"nz-tslint-rules": "^0.901.2",
"#angular/core": "~9.1.12",
I'm executing the following command from the app root:
"tslint --project ."
I've managed to be sure about the script execution with a console log in the nzSecondaryEntryImportsRule.js file
Also I've notice that:
tsutils.isImportDeclaration(node)
Always returns false therefore it continues to the next iteration in the for loop
I'd appreciate any help on this.
I guess because the global version is too low.
here are three solutions:
upgrade your global tslint
npm install tslint -g
add the command to the scripts in package.json, and then use npm run lint:fix
{
"scripts": {
"lint:fix": "tslint --project tsconfig.json --fix"
}
}
run from node_modules/.bin/tslint
node_modules/.bin/tslint --project tsconfig.json --fix

jestjs - how to parametrize test execution from cli in ci?

i have 4 environments :
dev (developers area)
test (test area)
preprod (pre production environment)
production (production environment)
these environments needs different configuration to execute tests (differents urls, usernames, assets, and so on).
how to pass there configurations to jest as a parameter in continous integration?
As you can read here, jest would not permits to pass custom arguments you can use to handle custom configuration loaded at runtime.
i propose a workaround working for me.
create a configuration file, e.g. config.js
edit config.js and exports modules switching for the environment
switch (env) {
case "test":
module.exports = {
baseUrl: 'https://test.website.com'
}
break;
case "production":
module.exports = {
baseUrl: 'https://production.website.com'
}
break;
}
create a javascript files for every environment you need
test-configuration.js
production-configuration.js
edit these files writing in the environment variables
for example test-configuration.js will be
process.env.ENVIRONMENT = "test"
load configuration for your test files as it was a static file
const config = require('./config.js')
use jest setupFiles to add a setupFiles that load the environment variables.
for example, running
jest --setupFiles=./test-configuration.js
jest will load the test-configuration.js file that will set "test" on the "process.env.ENVIRONMENT" variables, so config.js file will "switch" on the "test" environment and all your test will use it.
so now you can (or CI can) loads configuration as needed.
For anyone facing the same issue – can't pass environment url to your custom setup file and tests. The solution might be dumb but it works without modifying the code much.
In package.json modify your scripts to export environment before running jest:
"scripts": {
"test": "jest",
"test:dev": "export ENVIRONMENT=https://dev.environment/ && jest",
"test:prod": "export ENVIRONMENT=https://prod.environment/ && jest"
}
Then you can access your code:
const page = await browser.newPage();
await page.goto(process.env.ENVIRONMENT);
console.log(process.env.ENVIRONMENT);

How to run mocha tests with webpack when you don't have a single entry point to tests?

I'm trying to convert a project from browserify+mochify to webpack.
The webpack docs demonstrate how to use mocha-loader to run the tests with webpack-dev-server, but assumes a single entry point into the tests.
All the existing tests were designed with mochify in mind which does not require a single entry point as it recursively bundles ./test/*.js.
The setup below sort of works for me. It still uses mochify to run the tests (because it has all the phantomjs interfacing), but doesn't rely on anything from browserify. If you run webpack --watch, it reruns all tests when a file changes.
webpack.config.js:
var path = require("path");
var child_process = require('child_process');
module.exports = {
entry: {
tests: "./tests.js"
},
output: {
filename: "tests.js", // Should be a unique name
path: "/tmp"
},
plugins: [
// Automatically run all tests when webpack is done
function () {
this.plugin("done", function (stats) {
child_process.execSync('mochify /tmp/tests.js', { stdio: 'inherit'});
});
}
],
};
tests.js:
// List all test dirs here if you have multiple
var contexts = [
require.context('./dir1/test', true, /\.js$/),
require.context('./dir2/test', true, /\.js$/)
];
contexts.forEach(function (context) {
context.keys().forEach(context);
});
Another approach is described here: https://stackoverflow.com/a/32386750/675011
This is not exactly an answer, but it solved the problem for me. The reason I wanted to combine mochify and webpack was that I wanted to use the browser console to debug my mocha tests. Since my mocha tests themselves don't rely on a browser, it was enough for me to finally realize I could use a node debugger and it would bring up the Chrome console, (almost) solving my problem. node-inspector is the node debugger, but I'm using babel, so I needed babel-node-debug, but that doesn't yet work with babel6, but there's an unmerged pull request that fixes it: https://github.com/CrabDude/babel-node-debug/pull/12.

Resources