Cypress choose what test file to launch based on a string - javascript

I am currently working in Cypress, I will try to semplify my question as much as possible:
I have several test files:
integration/testA.spec.js
integration/testB.spec.js
integration/testC.spec.js
I also have a config.js file in which I have an object containing the name of the test I want to run:
{
test: 'testA.spec.js'
}
what I want to do - if possible - is a main.spec.js file that, depending on the testproperty, runs the relative spec file.
I have prepared almost everything
describe('Test', () => {
before(() => {})
beforeEach(() => {})
after(() => {})
describe('Test Booking', () => {
// retrieves the `test`property and returns the string name
let testName = retrieveTestName()
console.log('testName', testName)
/** I want to do something like this */
if (testName === 'testA.spec.js') {
// launch testA.spec.js file
}
}
})
but I ignore if I can do something like the code above; do you think is possible?
Or do I have to create a script file that
checks for the namefile
uses the --spec option and launches the test
?

An option can be to create commands using the --spec file and add it under scripts in your package.json. Something like:
"scripts": {
"testA": "npx cypress run --spec "cypress/integration/testA.spec.js",
"testB": "npx cypress run --spec "cypress/integration/testB.spec.js",
"testC": "npx cypress run --spec "cypress/integration/testC.spec.js"
}
You can run directly run the above command depending on the test you want to execute.
npm run testA

Related

Cypress - print both on console AND on log file - Windows

I run Windows10, I have a project made on Cypress and I want to log the test results both on a file AND on console: I tried just printing on a file, using in my package.json this script:
"scripts": {
"open": "./node_modules/.bin/cypress open",
"runheadless": "./node_modules/.bin/cypress run --headless --browser chrome
--spec 'cypress/integration/webpages.spec.js' > cypresstest.log"
}
And this runs smoothly; my issue is that there are more than 100 tests and it takes very long time (like 20 minutes); so I can't check if something got frozen or is working fine, because nothing is printed on console.
So I tried with
"runheadless": "./node_modules/.bin/cypress run --headless --browser chrome
--spec 'cypress/integration/webpages.spec.js' | tee cypresstest.log"
But since I'm on windows, it says
tee is not recognized as internal or external program
Is there a way, or a plugin, or something I can do to simply print both on console AND on a file log?
Cypress-terminal-report has such a feature, or you can use a custom command including cy. task instead of cy.log - for example:
cypress plugin file
module.exports = (on, config) => {
on('task', {
log (message) {
console.log(message)
return null
}
})
}
custom command:
Cypress.Commands.add("logInAndOut", (message) => {
cy.log(message)
cy.task('log', message)
});
test file
cy.logInAndOut('My log')
Edit: I found another solution - Commands. overwrite(), and I`ll list an example, but I do not recommend it, since if other people try to use the code after you - won't know the change:
Cypress.Commands.overwrite('log', (originalFn, message, args...) => {
console.log(message, args...)
// originalFn is the existing `log` command that you need to call
// and it will receive whatever you pass in here.
//
// make sure to add a return here!
return originalFn(message, args...)
})

How to run a shell command from Grunt task function

I'm trying to move some icons in my app directory based on a function i have inside my Gruntfile.js. Would it be possible to do something like this? I've tried the following (going into dev or staging folder and copying all files to the previous directory), but coudn't get it to work. Thanks in advance.
grunt.registerTask('setAppIcon', 'Task that sets the app icon', function(environment) {
if (environment.toLowerCase() == "development") {
grunt.task.run(['exec:command:cd app/lib/extras/res/icon/ios/dev && cp -a . ../']);
} else if (environment.toLowerCase() == "staging") {
grunt.task.run(['exec:command:cd app/lib/extras/res/icon/ios/staging && cp -a . ../']);
}
});
Yes, it's possible to achieve your requirement, however, when you invoke the grunt.task.run command inside your function (i.e. custom task) you need to provide a reference to a task to run.
If you define a separate Target, (Let's call call them copy_dev and copy_staging - as shown in the example below), for each cd ... && cp ... command in the grunt-exec Task it should work successfully.
Gruntfile.js
The following Gruntfile.js gist shows how this can be achieved:
module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-exec');
grunt.initConfig({
exec: {
copy_dev: {
cmd: 'cd app/lib/extras/res/icon/ios/dev && cp -a . ../'
},
copy_staging: {
cmd: 'cd app/lib/extras/res/icon/ios/staging && cp -a . ../'
}
}
});
grunt.registerTask('setAppIcon', 'Task that sets the app icon', function() {
var environment = process.env.NODE_ENV;
// Exit early if NODE_ENV variable has not been set.
if (!environment) {
grunt.log.writeln(
'\"setAppIcon\"" task failed - NODE_ENV has not been set.'['yellow']
)
return
}
if (environment.toLowerCase() == "development") {
grunt.task.run('exec:copy_dev');
grunt.log.writeln('>> Copying icons from \"dev\"...')
} else if (environment.toLowerCase() == "staging") {
grunt.task.run('exec:copy_staging');
grunt.log.writeln('>> Copying icons from \"staging\"...')
}
});
grunt.registerTask('default', [ 'setAppIcon' ]);
};
Additional notes
Inside the custom task/function named setAppIcon we obtain the current node environment using nodes builtin process.env
When running $ grunt via your CLI (using the gist shown above), and assuming your process.env.NODE_ENV variable has not been set, or it has possibly been unset by running $ unset NODE_ENV, you will see the following message:
"setAppIcon"" task failed - NODE_ENV has not been set.
However, if the process.env.NODE_ENV variable has been set to either development or staging the files will be copied as expected.
For example running either of the following via your CLI will work successfully:
$ export NODE_ENV=development && grunt
or
$ export NODE_ENV=staging && grunt
You will also see either of the following messages logged to the console:
>> Copying icons from "dev"...
or
>> Copying icons from "staging"...
After process.env.NODE_ENV has been set to either development or staging then just running $ grunt via your CLI, will copy files according to which environment is set.

Cant configure unit tests correctly with mocha

I am trying to configure mocha on a typescript project, but not working fine
I am using book: Typescript design patterns, chapter 1.
When I run mocha it says:
Warning: Could not find any test files matching pattern: out/test/ No
test files found
mocha.opts
--require ./test/mocha.js
out/test/
mocha.js
require('chai').should();
starter.js
describe('some feature', () => {
it('should pass', () => {
'foo'.should.not.equal('bar');
});
it('should error', () => {
(() => {
throw new Error();
}).should.throw();
}); });
Based on the error, it seems that mocha is trying to look for tests in the /out directory. First off, try removing /out/test from mocha.opts or replacing it with src/test to see if that resolves the path issue.
You could also try moving mocha.js into the /src/test directory, and move the mocha.opts to the /src directory.
Then, when running mocha, make sure you run from the root of the project (which in this case seems to be src)

How to set execution order of mocha test cases in multiple files

I have two javascript files which contain mocha test cases.
//----------abc.js -------------
describe("abc file", function(){
it("test 1" , function(){
assert.equal(20 , 20);
});
});
//---------xyz.js--------------
describe("xyz file", function(){
it("test 1" , function(){
assert.equal(10 , 10);
});
});
I have put them in a folder called test and when I execute the mocha command the first file(abc.js) is always executed before xyz.js.
I thought this might be due to alphabetical ordering and renamed the files as
abc.js => xyz.js
xyz.js => abc.js
but still, the content of the xyz.js (previously abc.js) is executed first. How can I change the execution order of these test files?
In the second file, require the first one:
--- two.js ---
require("./one")
or if you are using ES modules:
--- two.js ---
import "./one"
Mocha will run the tests in the order the describe calls execute.
I follow a totally seperate solution for this.
Put all your tests in a folder named test/ and
Create a file tests.js in the root directory in the order of execution
--- tests.js ---
require('./test/one.js')
require('./test/two.js')
require('./test/three.js')
And in the tests files one.js, two.js and so on write your simple mocha tests
this way if you want to run them in the order you have defined then just run mocha tests.js
Mocha has a --sort (short -S) option that sorts test files:
$ mocha --help
[...]
-S, --sort sort test files
[...]
Since mocha sorts files in alphabetical order, I usually prefix my test files names with numbers, like:
0 - util.js
1 - something low level.js
2 - something more interesting.js
etc.
In addition to being really easy to maintain (no gulp grunt or any of that nonsense, no editing your package.json...), it provides the benefit that:
people reading your source code get an idea of the structure of your program, starting from the less interesting parts and moving up to the business layer
when a test fails, you have some indication of causality (if something failed in 1 - something.js but there are no failures in 0 - base.js then it's probably the fault of the layer covered by 1 - something.js
If you're doing real unit tests of course order should not matter, but I'm rarely able to go with unit tests all the way.
If you prefer a particular order, you can list the files (in order) as command-line arguments to mocha, e.g.:
$ mocha test/test-file-1.js test/test-file-2.js
To avoid a lot of typing every time you want to run it, you could turn this into an npm script in your package.json:
{
// ...
"scripts": {
"test": "mocha test/test-file-1.js test/test-file-2.js"
}
// ...
}
Then run your suite from the command line:
$ npm test
Or if you're using Gulp, you could create a task in your gulpfile.js:
var gulp = require('gulp');
var mocha = require("gulp-mocha");
gulp.task("test", function() {
return gulp.src([
"./test/test-file-1.js",
"./test/test-file-2.js"
])
.pipe(mocha());
});
Then run $ gulp test.
The way it worked for my tests to be executed in a specific order was to create a separate test.js file and then added a describe for each mocha test file I'd wanted to execute.
test.js:
describe('test file 1', function() {
require('./test1.js')
})
describe('test file 2', function() {
require('./test2.js')
})
Then simply run mocha test.js
I am exporting an array with all required files and that is the way I tell mocha the order of execution through index.js file in the folder with all my test files:
const Login = require('../login');
const ChangeBudgetUnit = require('./changeBudgetUnit');
const AddItemsInCart = require('./addItemsInCart');
// if the order matters should export array, not object
module.exports = [
Login,
ChangeBudgetUnit,
AddItemsInCart
];
mocha-steps allows you to write tests that run in a specific sequence, aborting the run at the first failure. It provides a drop-in replacement for it, called steps.
Example usage:
describe('my smoke test', async () => {
step('login', async () => {})
step('buy an item', async () => throw new Error('failed'))
step('check my balance', async () => {})
xstep('temporarily ignored', async () => {})
})
The repo hasn't seen much activity in three years, but it works fine with Mocha 9.

How to run a single test with Mocha?

I use Mocha to test my JavaScript stuff. My test file contains 5 tests. Is that possible to run a specific test (or set of tests) rather than all the tests in the file?
Try using mocha's --grep option:
-g, --grep <pattern> only run tests matching <pattern>
You can use any valid JavaScript regex as <pattern>. For instance, if we have test/mytest.js:
it('logs a', function(done) {
console.log('a');
done();
});
it('logs b', function(done) {
console.log('b');
done();
});
Then:
$ mocha -g 'logs a'
To run a single test. Note that this greps across the names of all describe(name, fn) and it(name, fn) invocations.
Consider using nested describe() calls for namespacing in order to make it easy to locate and select particular sets.
Depending on your usage pattern, you might just like to use only. We use the TDD style; it looks like this:
test.only('Date part of valid Partition Key', function (done) {
//...
}
Only this test will run from all the files/suites.
If you are using npm test (using package.json scripts) use an extra -- to pass the param through to mocha
e.g. npm test -- --grep "my second test"
EDIT: Looks like --grep can be a little fussy (probably depending on the other arguments). You can:
Modify the package.json:
"test:mocha": "mocha --grep \"<DealsList />\" .",
Or alternatively use --bail which seems to be less fussy
npm test -- --bail
Just use .only before 'describe', 'it' or 'context'. I run using "$npm run test:unit", and it executes only units with .only.
describe.only('get success', function() {
// ...
});
it.only('should return 1', function() {
// ...
});
run single test –by filename–
Actually, one can also run a single mocha test by filename (not just by „it()-string-grepping“) if you remove the glob pattern (e.g. ./test/**/*.spec.js) from your mocha.opts, respectively create a copy, without:
node_modules/.bin/mocha --opts test/mocha.single.opts test/self-test.spec.js
Here's my mocha.single.opts (it's only different in missing the aforementioned glob line)
--require ./test/common.js
--compilers js:babel-core/register
--reporter list
--recursive
Background: While you can override the various switches from the opts-File (starting with --) you can't override the glob. That link also has
some explanations.
Hint: if node_modules/.bin/mocha confuses you, to use the local package mocha. You can also write just mocha, if you have it installed globally.
And if you want the comforts of package.json: Still: remove the **/*-ish glob from your mocha.opts, insert them here, for the all-testing, leave them away for the single testing:
"test": "mocha ./test/**/*.spec.js",
"test-watch": "mocha -R list -w ./test/**/*.spec.js",
"test-single": "mocha",
"test-single-watch": "mocha -R list -w",
usage:
> npm run test
respectively
> npm run test-single -- test/ES6.self-test.spec.js
mind the -- which chains whatever text comes after it to the npm script
There are multiple ways by which you can do this.
If you just want to run one test from your entire list of test cases then, you can write only ahead of your test case.
it.only('<test scenario name>', function() {
// ...
});
or you can also execute the mocha grep command as below
mocha -g <test-scenario-name>
If you want to run all the test cases which are inside one describe section, then you can also write only to describe as well.
describe.only('<Description of the tests under this section>', function() {
// ...
});
If you have multiple test files & you wanted to run only one of then you can follow the below command.
npm test <filepath>
eg :
npm test test/api/controllers/test.js
here 'test/api/controllers/test.js' is filepath.
You can try "it.only"
it.only('Test one ', () => {
expect(x).to.equal(y);
});
it('Test two ', () => {
expect(x).to.equal(y);
});
in this the first one only will execute
Hi above solutions didn't work for me.
The other way of running a single test is
mocha test/cartcheckout/checkout.js -g 'Test Name Goes here'
This helps to run a test case from a single file and with specific name.
Looking into the doc, we see that simply using:
mocha test/myfile
will work. You can omit the '.js' at the end.
Using Mocha's --fgrep (or just -f) you can select tests containing string, for example:
mocha -f 'my test x'
will run all tests containing my test x in either it(), describe() or context() blocks.
For those who are looking to run a single file but they cannot make it work, what worked for me was that I needed to wrap my test cases in a describe suite as below and then use the describe title e.g. 'My Test Description' as pattern.
describe('My Test Description', () => {
it('test case 1', () => {
// My test code
})
it('test case 2', () => {
// My test code
})
})
then run
yarn test -g "My Test Description"
or
npm run test -g "My Test Description"
Not sure why the grep method is not working for me when using npm test. This works though. I also need to specify the test folder for some reason.
npm test -- test/sometest.js
Consolidate all your tests in one test.js file and add a script in your package.json:
"scripts": {
"api:test": "node_modules/.bin/mocha --timeout 10000 --recursive api_test/"
},
Type this command in your test directory:
npm run api:test

Categories