Commit a51d7c13 authored by Paul Gascou-Vaillancourt's avatar Paul Gascou-Vaillancourt Committed by Paul Slaughter

Remove unified tests script

Now that we have migrated all specs to Jests (except for a few
excceptions), we can remove the unified tests script and update the docs
accordingly.
parent 5ac5f7f3
......@@ -25,17 +25,19 @@ If you are looking for a guide on Vue component testing, you can jump right away
## Jest
We have started to migrate frontend tests to the [Jest](https://jestjs.io) testing framework (see also the corresponding
[epic](https://gitlab.com/groups/gitlab-org/-/epics/895)).
We use Jest to write frontend unit and integration tests.
Jest tests can be found in `/spec/frontend` and `/ee/spec/frontend` in EE.
Most examples have a Jest and Karma example. See the Karma examples only as explanation to what's going on in the code, should you stumble over some use cases during your discovery. The Jest examples are the one you should follow.
## Karma test suite
While GitLab is switching over to [Jest](https://jestjs.io) you'll still find Karma tests in our application. [Karma](http://karma-runner.github.io/) is a test runner which uses [Jasmine](https://jasmine.github.io/) as its test
framework. Jest also uses Jasmine as foundation, that's why it's looking quite similar.
While GitLab has switched over to [Jest](https://jestjs.io) you'll still find Karma tests in our
application because some of our specs require a browser and can't be easiliy migrated to Jest.
Those specs will eventually drop Karma in favor of either Jest or RSpec. You can track this migration
in the [related epic](https://gitlab.com/groups/gitlab-org/-/epics/4900).
[Karma](http://karma-runner.github.io/) is a test runner which uses
[Jasmine](https://jasmine.github.io/) as its test framework. Jest also uses Jasmine as foundation,
that's why it's looking quite similar.
Karma tests live in `spec/javascripts/` and `/ee/spec/javascripts` in EE.
......@@ -47,19 +49,6 @@ browser and you will not have access to certain APIs, such as
[`Notification`](https://developer.mozilla.org/en-US/docs/Web/API/notification),
which have to be stubbed.
### When should I use Jest over Karma?
If you need to update an existing Karma test file (found in `spec/javascripts`), you do not
need to migrate the whole spec to Jest. Simply updating the Karma spec to test your change
is fine. It is probably more appropriate to migrate to Jest in a separate merge request.
If you create a new test file, it needs to be created in Jest. This will
help support our migration and we think you'll love using Jest.
As always, please use discretion. Jest solves a lot of issues we experienced in Karma and
provides a better developer experience, however there are potentially unexpected issues
which could arise (especially with testing against browser specific features).
### Differences to Karma
- Jest runs in a Node.js environment, not in a browser. Support for running Jest tests in a browser [is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/26982).
......@@ -776,11 +765,10 @@ Please consult the [official Jest docs](https://jestjs.io/docs/en/jest-object#mo
For running the frontend tests, you need the following commands:
- `rake frontend:fixtures` (re-)generates [fixtures](#frontend-test-fixtures).
- `yarn test` executes the tests.
- `yarn jest` executes only the Jest tests.
As long as the fixtures don't change, `yarn test` is sufficient (and saves you some time).
- `rake frontend:fixtures` (re-)generates [fixtures](#frontend-test-fixtures). Make sure that
fixtures are up-to-date before running tests that require them.
- `yarn jest` runs Jest tests.
- `yarn karma` runs Karma tests.
### Live testing and focused testing -- Jest
......
......@@ -30,7 +30,6 @@
"stylelint": "yarn stylelint-file 'app/assets/stylesheets/**/*.*' 'ee/app/assets/stylesheets/**/*.*' '!app/assets/stylesheets/startup/startup-*.scss' '!**/vendors/**'",
"stylelint-file": "BROWSERSLIST_IGNORE_OLD_DATA=true node node_modules/stylelint/bin/stylelint.js",
"stylelint-create-utility-map": "node scripts/frontend/stylelint/stylelint-utility-map.js",
"test": "node scripts/frontend/test",
"webpack": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.config.js",
"webpack-vendor": "NODE_OPTIONS=\"--max-old-space-size=3584\" webpack --config config/webpack.vendor.config.js",
"webpack-prod": "NODE_OPTIONS=\"--max-old-space-size=3584\" NODE_ENV=production webpack --config config/webpack.config.js"
......
#!/usr/bin/env node
const { spawn } = require('child_process');
const { EOL } = require('os');
const program = require('commander');
const chalk = require('chalk');
const SUCCESS_CODE = 0;
const JEST_ROUTE = 'spec/frontend';
const KARMA_ROUTE = 'spec/javascripts';
const COMMON_ARGS = ['--colors'];
const jestArgs = [...COMMON_ARGS, '--passWithNoTests'];
const karmaArgs = [...COMMON_ARGS, '--no-fail-on-empty-test-suite'];
program
.usage('[options] <file ...>')
.option('-p, --parallel', 'Run tests suites in parallel')
.option(
'-w, --watch',
'Rerun tests when files change (tests will be run in parallel if this enabled)',
)
.parse(process.argv);
const shouldParallelize = program.parallel || program.watch;
const isSuccess = code => code === SUCCESS_CODE;
const combineExitCodes = codes => {
const firstFail = codes.find(x => !isSuccess(x));
return firstFail === undefined ? SUCCESS_CODE : firstFail;
};
const skipIfFail = fn => code => (isSuccess(code) ? fn() : code);
const endWithEOL = str => (str[str.length - 1] === '\n' ? str : `${str}${EOL}`);
const runTests = paths => {
if (shouldParallelize) {
return Promise.all([runJest(paths), runKarma(paths)]).then(combineExitCodes);
} else {
return runJest(paths).then(skipIfFail(() => runKarma(paths)));
}
};
const spawnYarnScript = (cmd, args) => {
return new Promise((resolve, reject) => {
const proc = spawn('yarn', ['run', cmd, ...args]);
const output = data => {
const text = data
.toString()
.split(/\r?\n/g)
.map((line, idx, { length }) =>
idx === length - 1 && !line ? line : `${chalk.gray(cmd)}: ${line}`,
)
.join(EOL);
return endWithEOL(text);
};
proc.stdout.on('data', data => {
process.stdout.write(output(data));
});
proc.stderr.on('data', data => {
process.stderr.write(output(data));
});
proc.on('close', code => {
process.stdout.write(output(`exited with code ${code}`));
// We resolve even on a failure code because a `reject` would cause
// Promise.all to reject immediately (without waiting for other promises)
// to finish.
resolve(code);
});
});
};
const runJest = args => {
return spawnYarnScript('jest', [...jestArgs, ...toJestArgs(args)]);
};
const runKarma = args => {
return spawnYarnScript('karma', [...karmaArgs, ...toKarmaArgs(args)]);
};
const replacePath = to => path =>
path
.replace(JEST_ROUTE, to)
.replace(KARMA_ROUTE, to)
.replace('app/assets/javascripts', to);
const replacePathForJest = replacePath(JEST_ROUTE);
const replacePathForKarma = replacePath(KARMA_ROUTE);
const toJestArgs = paths => paths.map(replacePathForJest);
const toKarmaArgs = paths =>
paths.reduce((acc, path) => acc.concat('-f', replacePathForKarma(path)), []);
const main = paths => {
if (program.watch) {
jestArgs.push('--watch');
karmaArgs.push('--single-run', 'false', '--auto-watch');
}
runTests(paths).then(code => {
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
if (isSuccess(code)) {
console.log(chalk.bgGreen(chalk.black('All tests passed :)')));
} else {
console.log(chalk.bgRed(chalk.white(`Some tests failed :(`)));
}
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~');
if (!isSuccess(code)) {
process.exit(code);
}
});
};
main(program.args);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment