From 5e5e2c102889532c5f3dac9e65234f1cc9c92775 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Sat, 14 Oct 2017 15:02:43 +0200 Subject: [PATCH] build: add karma task for easier cross-browser debugging Adds the `gulp test:static` task that is identical to `gulp test`, however it doesn't launch Chrome automatically, which is convenient for debugging any browser that isn't Chrome. Currently the debugging flow for other browsers is running the Gulp task which launches Chrome, waiting for it to finish running the tests, connect the other browser, wait for the new browser to finish and then start debugging. With the new task you can just run the Gulp task and connect and disconnect only the relevant browsers. --- tools/gulp/tasks/unit-test.ts | 82 ++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/tools/gulp/tasks/unit-test.ts b/tools/gulp/tasks/unit-test.ts index 3c70bd50f68d..96494582ea66 100644 --- a/tools/gulp/tasks/unit-test.ts +++ b/tools/gulp/tasks/unit-test.ts @@ -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( @@ -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); @@ -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)); + }; +}