Skip to content

build: add karma task for easier cross-browser debugging #7796

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 18, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 48 additions & 34 deletions tools/gulp/tasks/unit-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import {buildConfig, sequenceTask} from 'material2-build-tools';
// There are no type definitions available for these imports.
const runSequence = require('run-sequence');

const {packagesDir, projectDir} = buildConfig;
// Default Karma options.
const defaultOptions = {
configFile: join(buildConfig.projectDir, 'test/karma.conf.js'),
autoWatch: false,
singleRun: false
};

/** Builds everything that is necessary for karma. */
task(':test:build', sequenceTask(
Expand All @@ -23,10 +28,7 @@ task('test:single-run', [':test:build'], (done: () => void) => {
// Load karma not outside. Karma pollutes Promise with a different implementation.
const karma = require('karma');

new karma.Server({
configFile: join(projectDir, 'test/karma.conf.js'),
singleRun: true
}, (exitCode: number) => {
new karma.Server({...defaultOptions, singleRun: true}, (exitCode: number) => {
// Immediately exit the process if Karma reported errors, because due to
// potential still running tunnel-browsers gulp won't exit properly.
exitCode === 0 ? done() : process.exit(exitCode);
Expand All @@ -35,39 +37,51 @@ task('test:single-run', [':test:build'], (done: () => void) => {

/**
* [Watch task] Runs the unit tests, rebuilding and re-testing when sources change.
* Does not inline resources. Note that this doesn't use Karma's built-in file
* watching. Due to the way our build process is set up, Karma ends up firing
* it's change detection for every file that is written to disk, which causes
* it to run tests multiple time and makes it hard to follow the console output.
* This approach runs the Karma server and then depends on the Gulp API to tell
* Karma when to run the tests.
* Does not inline resources.
*
* This task should be used when running unit tests locally.
*/
task('test', [':test:build'], () => {
const patternRoot = join(packagesDir, '**/*');
// Load karma not outside. Karma pollutes Promise with a different implementation.
const karma = require('karma');
task('test', [':test:build'], karmaWatchTask());

// Configure the Karma server and override the autoWatch and singleRun just in case.
const server = new karma.Server({
configFile: join(projectDir, 'test/karma.conf.js'),
autoWatch: false,
singleRun: false
});
/**
* Runs a Karma server which will run the unit tests against any browser that connects to it.
* This is identical to `gulp test`, however it won't launch and manage Chrome automatically,
* which makes it convenient debugging unit tests against multiple different browsers.
*/
task('test:static', [':test:build'], karmaWatchTask({browsers: []}));

// Refreshes Karma's file list and schedules a test run.
// Tests will only run if TypeScript compilation was successful.
const runTests = (err?: Error) => {
if (!err) {
server.refreshFiles().then(() => server._injector.get('executor').schedule());
}
};
/**
* Returns a Gulp task that spawns a Karma server and reloads whenever the files change.
* Note that this doesn't use Karma's built-in file watching. Due to the way our build
* process is set up, Karma ends up firing it's change detection for every file that is
* written to disk, which causes it to run tests multiple time and makes it hard to follow
* the console output. This approach runs the Karma server and then depends on the Gulp API
* to tell Karma when to run the tests.
* @param overrides Karma options to use on top of the defaults.
*/
function karmaWatchTask(options?: any) {
return () => {
const patternRoot = join(buildConfig.packagesDir, '**/*');
// Note: Karma shouldn't be required from the outside, because it
// pollutes the global Promise with a custom implementation.
const karma = require('karma');

// Boot up the test server and run the tests whenever a new browser connects.
server.start();
server.on('browser_register', () => runTests());
// Configure the Karma server and override the autoWatch and singleRun just in case.
const server = new karma.Server({...defaultOptions, ...options});

// Whenever a file change has been recognized, rebuild and re-run the tests.
watch(patternRoot + '.+(ts|scss|html)', () => runSequence(':test:build', runTests));
});
// Refreshes Karma's file list and schedules a test run.
// Tests will only run if TypeScript compilation was successful.
const runTests = (error?: Error) => {
if (!error) {
server.refreshFiles().then(() => server._injector.get('executor').schedule());
}
};

// Boot up the test server and run the tests whenever a new browser connects.
server.start();
server.on('browser_register', () => runTests());

// Whenever a file change has been recognized, rebuild and re-run the tests.
watch(patternRoot + '.+(ts|scss|html)', () => runSequence(':test:build', runTests));
};
}