Karma detects changes but does not run new tests - javascript

I am using babel and ng-html2js to build and test an angular app with Karma as the test runner. For the most part, things are working. If I make changes to the files, Karma will rerun the tests and pass/fail the tests as appropriately. Karma also determines when changes have been made to the test files themselves ... however, it will run the old tests rather than the new tests.
As a simple example:
/* constant.js */
angular.module("foo").constant("constant", 1);
/* constant.test.js */
let constant;
beforeEach(inject(_constant_ => constant = _constant));
describe("constant", () => {
it("is 1", () => {
expect(constant).to.equal(2);
});
});
In the above test, I am checking constant against 2, but in my original code, constant is 1.
If I change constant to 2 in constant.js, the test will rerun and pass.
If I change .to.equal(2) to .to.equal(1) and rerun the tests from scratch, they will pass.
If I change .to.equal(2) to .to.equal(1) while the tests are already running, the tests will rerun automatically but they will fail because it is still checking 1 to equal 2.
How can I get Karma to rerun the new tests when I make changes to the test files?

Related

Passing a same random number to all tests in Cypress

So I have two tests - Test1.spec.js and Test2.spec.js and I want that with every test run a random number should be generated and the same random number should be used in both the specs. I wrote a simple Math.random() function for this under support/index.js
Cypress.config('UniqueNumber', `${Math.floor(Math.random() * 10000000000000)}`)
And in the tests I am writing as:
cy.get('locator').type(Cypress.config('UniqueNumber'))
When I am trying to execute the tests using the cypress app npm cypress open and then Run All Specs, a random number is generated and the same is passed to both of the spec files correctly. But when I try to run the tests using the CLI npx cypress run for both of the spec files different random numbers are passed.
What am I doing wrong in case of executing the tests using CLI?
So as per cypress docs support/index.js is run every time before each spec file is run, so my above approach is not valid because with every run a new value would be generated. So the next approach I followed was to write the values in the fixtures/data.json file on the first test and use it throughout the tests. This way with every run a new set of values would be generated and saved in the fixture file and then the same value would be used throughout the test suite for that Test Run. Below is the way how I wrote to fixtures/data.json file:
const UniqueNumber = `${Math.floor(Math.random() * 10000000000000)}`
cy.readFile("cypress/fixtures/data.json", (err, data) => {
if (err) {
return console.error(err);
};
}).then((data) => {
data.username = UniqueNumber
cy.writeFile("cypress/fixtures/data.json", JSON.stringify(data))
})
})

Jest gives "Your test suite must contain at least one test" when certain file is imported even though there is a valid test

Whenever I import a certain file from my test file, Jest produces an error that I do not have any tests in the test file, even though there is one with just constants that should pass.
This is running inside a create-react-app folder, but I am using a global install of Jest for the server-side testing.
The Error
FAIL server/__tests__/server.test.js
● Test suite failed to run
Your test suite must contain at least one test.
at onResult (../../../../usr/lib/node_modules/jest/node_modules/#jest/core/build/TestScheduler.js:173:18)
A simplified version of the test file:
const timer = require("./timer.js");
test("should pass", () => {
expect(1 + 2).toBe(3);
});
A simplified version of timer.js:
class Timer {
constructor(ms, onCompleteFunction) {
this.ms = ms;
this.startTime = Date.now();
setTimeout(onCompleteFunction, ms);
}
}
test = () => {
let timer = new Timer(5000, () => console.log("Test Done!"));
};
test();
module.exports = Timer;
(This is a self-answer)
Before adding real testing with Jest, in the Timer.js file I had added a quick test function, just to verify that it was working without running the whole app.
Unfortunately, the function, named test, was not prefixed with var, let, or const. From what I can tell, it overrode the test function from the Jest library, and this error message was the result. When test = 1 or similar was present, the error was
TypeError: test is not a function
This is an extreme edge case due to poor coding practices and something I would have thought was a syntax error on my part, so I don't fault the error message for being unhelpful. I hope this can help someone in the future anyways.

Isolating js files that are needed for one test suite

I am using karma/mocha/chrome headless for my test stack.
--js 1
document.addEventListener('test', ...);
do sth more.
--js 2
document.addEventListener('test', ...);
do sth more differently.
-- test suite 1
require(test1)
i am dispatching the test event here to test js 1
-- test suite 2
require(test2)
I am dispatchinh the test event here to test js 2
The problem is that both of these files will be now available globally. When I am running the test suite 2, both js1 and js2 events are going to listen my dispatch because js1 will be still globally available.
My perfect scenario would be. Load js1 to test suite 1 and encapsulate it there. Hacky way would be remove it after the tests are ran.
My question is, how to make sure that needed js files are loaded locally in the scope of one test suite? Basically load only nesseccary files for the specific test suite and keep them isolated from rest of test suites.
Thanks.
If I understand the question correctly, you want to scope your modules to the relevant test file?
If that's the case then you can load your modules like so:
const sharedModule = require('some/shared/module');
describe('some test', function() {
const scopedModule = require('some/path/to/module');
it('should...', function() {
// Test code...
})
)
This would result in your module being loaded only when the test begins to execute, being scoped inside that block.

Using tags with nightwatch - Special case

So I'm currently using Nightwatch.js to run some tests on a web platform. We have nightwatch configured with Saucelabs so we can run multiple tests at the same time and see recordings of each test. However, our test cases are split up into multiple files rather than multiple steps in a single file.
Since sauce labs doesn't like to run multiple files within a single browser session, we had to do a little hack:
extend = function(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function (source) {
for (var prop in source) {
target[prop] = source[prop];
}
});
return target;
}
require("./login.spec.js");
module.exports = extend(module.exports,login);
require("./getCustomLink.js");
module.exports = extend(module.exports,getCustLink);
Essentially, you use 'require' and the file path the test and just add on to your current test module. So if the test doesn't end in "browser.end()" then it will continue to run through the tests in the order specified. My question is: I'm going to be having multiples of these kinds of files with different orders of test cases for different cases. How exactly would I add a '#tags' to this so I can just call the tag when running:
npm test --tags #tagHere
and it will just run the master file and the order of tests I specified?

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.

Categories