Skip to content

Commit

Permalink
NODE - simpler partial watch logic
Browse files Browse the repository at this point in the history
We now try to match the dependencies e.g
/foo/bar/baz.spec.js baz
/src/baz.js          baz
If we cannot match we pick the first
  • Loading branch information
Christoffer Åström committed Nov 17, 2017
1 parent 6ea8d8c commit ada5dc6
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 34 deletions.
12 changes: 12 additions & 0 deletions src/cdp/options.js
Expand Up @@ -15,6 +15,18 @@ module.exports = {
default: ['test/**/*.spec.js'],
type: 'array',
},
watch: {
description: 'Watch changes',
default: false,
type: 'boolean',
alias: 'w',
},
watchGlob: {
description: 'Watch glob',
default: ['src/**/*.{js,ts}', 'test/**/*.{js,ts}'],
type: 'array',
alias: 'wg',
},
coverage: {
description: 'Generate coverage?',
default: false,
Expand Down
44 changes: 31 additions & 13 deletions src/cdp/runner.js
@@ -1,13 +1,15 @@
/* eslint no-console: 0, class-methods-use-this: 0 */
const path = require('path');
const chromeLauncher = require('chrome-launcher');
const unmirror = require('chrome-unmirror');
const chokidar = require('chokidar');
const Mediator = require('./mediator');
const connect = require('./connect');
const utils = require('../terminal-utils');

class Runner {
constructor(options = { chrome: { chromeFlags: [] }, client: {} }, nyc) {
this.options = options;
constructor(argv = { chrome: { chromeFlags: [] }, client: {} }, nyc) {
this.argv = argv;
this.nyc = nyc;
this.mediator = new Mediator();
this.chromeLauncher = chromeLauncher;
Expand All @@ -19,7 +21,7 @@ class Runner {
this.started = false;
}
bind() {
if (!this.options.url) {
if (!this.argv.url) {
this.fail('`options.url` must be specified to run tests');
}
this.mediator.on('width', () => {
Expand All @@ -32,7 +34,7 @@ class Runner {
});
this.mediator.on('started', (tests) => {
this.started = true;
if (this.options.coverage) {
if (this.argv.coverage) {
this.nyc.reset();
}
const loadingEnd = process.hrtime(this.loadingStart);
Expand Down Expand Up @@ -98,12 +100,12 @@ class Runner {
return this.chromeLauncher.launch(options);
}
async setup(files) {
if (this.options.chrome.launch) {
this.chrome = await this.launch(this.options.chrome);
if (this.argv.chrome.launch) {
this.chrome = await this.launch(this.argv.chrome);
const { port } = this.chrome;
this.options.client.port = port;
this.argv.client.port = port;
}
this.client = await connect(this.options, files);
this.client = await connect(this.argv, files);
if (!this.client) {
this.fail('CDP Client could not connect');
return;
Expand All @@ -116,22 +118,35 @@ class Runner {
}
async navigate() {
if (this.loadError) {
this.fail(`Failed to load the url: ${this.options.url}`);
this.fail(`Failed to load the url: ${this.argv.url}`);
return;
}
console.log(`Navigating to ${this.options.url}`);
await this.client.Page.navigate({ url: this.options.url });
console.log(`Navigating to ${this.argv.url}`);
await this.client.Page.navigate({ url: this.argv.url });
}
watch() {
chokidar.watch(this.argv.watchGlob).on('change', async (f) => {
const relativeFile = path.relative(path.dirname(this.argv.url), path.resolve(f));
const injectAwFiles = `window.awFiles = ${JSON.stringify([relativeFile])};`;
// const madge = require('madge');
// const res = await madge(f);
// console.log(res.obj());
await this.client.Page.reload({ ignoreCache: true, scriptToEvaluateOnLoad: injectAwFiles });
});
}
async run(files) {
await this.setup(files);
await this.navigate();
if (this.argv.watch) {
this.watch();
}
}
async extractCoverage() {
const { result: { value } } = await this.client.Runtime.evaluate({ expression: 'window.__coverage__', returnByValue: true });
return value;
}
async exit(code) {
if (this.options.coverage) {
if (this.argv.coverage) {
const coverageStart = process.hrtime();
global.__coverage__ = await this.extractCoverage(); // eslint-disable-line
this.nyc.writeCoverageFile();
Expand All @@ -140,8 +155,11 @@ class Runner {
console.log(`Coverage write time: ${coverageEnd[0]}s ${coverageEnd[1] / 1000000}ms`);
console.log('');
}
if (this.argv.watch) {
return;
}
await this.client.close();
if (this.options.chrome.launch) {
if (this.argv.chrome.launch) {
await this.chrome.kill();
}
this.mediator.emit('exit', code);
Expand Down
52 changes: 35 additions & 17 deletions src/node/index.js
@@ -1,4 +1,4 @@
/* eslint no-console: 0, max-len: 0, global-require: 0, import/no-dynamic-require: 0, object-curly-newline: 0 */
/* eslint no-console: 0, max-len: 0, global-require: 0, import/no-dynamic-require: 0, object-curly-newline: 0, class-methods-use-this: 0 */
const readline = require('readline');
const globby = require('globby');
const Mocha = require('mocha');
Expand Down Expand Up @@ -36,36 +36,44 @@ class Runner {
console.log(` \u001b[90m${f}\u001b[0m`);
});
console.log('\nSave\u001b[90m a test file or source file to run only affected tests\u001b[0m');
console.log('\u001b[90mPress\u001b[0m a \u001b[90mto run all\u001b[0m');
console.log('\u001b[90mPress\u001b[0m a \u001b[90mto run all tests\u001b[0m');
return this;
}
matchDependency(found, testName, extCnt) {
let use = found;
if (found.length > 1) {
const matchName = found.filter(id => path.basename(id).slice(0, extCnt) === testName);
if (matchName.length === 1) {
use = matchName;
} else {
use = found.splice(0, 1);
}
}
return use;
}
setOnlyFilesFromTestFile(testFile) {
this.onlyTestFiles = [testFile];
const testName = path.basename(testFile).slice(0, -8);
const mod = require.cache[testFile];
const found = mod
.children
.filter(m => this.srcFiles.indexOf(m.id) !== -1)
.map(m => m.id);
this.onlySrcFiles = [...new Set([...found])];
const use = this.matchDependency(found, testName, -3);
this.onlySrcFiles = [...new Set([...use])];
}
setOnlyFilesFromSrcFile(srcFile) {
const srcName = path.basename(srcFile).slice(0, -3);
const found = this.testFiles.filter((f) => {
const mod = require.cache[f];
return mod
.children
.filter(m => m.id === srcFile).length !== 0;
});
this.onlyTestFiles = [...new Set([...found])];
const use = this.matchDependency(found, srcName, -8);
this.onlyTestFiles = [...new Set([...use])];
this.onlySrcFiles = [srcFile];
}
setOnlyFiles(file) {
const isTestFile = this.testFiles.indexOf(file) !== -1;
if (isTestFile) {
this.setOnlyFilesFromTestFile(file);
} else {
this.setOnlyFilesFromSrcFile(file);
}
}
setTestFiles() {
this.testFiles = globby.sync(this.argv.glob).map(f => path.resolve(f));
if (!this.testFiles.length) {
Expand Down Expand Up @@ -188,14 +196,24 @@ class Runner {
.setup(testFiles, srcFiles)
.runTests();
}
onWatch(f) {
const isTestFile = this.testFiles.indexOf(f) !== -1;
const isSrcFile = this.srcFiles.indexOf(f) !== -1;
if (!isTestFile && !isSrcFile) {
return;
}
this.all = false;
if (isTestFile) {
this.setOnlyFilesFromTestFile(f);
} else {
this.setOnlyFilesFromSrcFile(f);
}
this.setupAndRunTests(this.onlyTestFiles, this.onlySrcFiles);
}
run() {
this.setupAndRunTests(this.testFiles, this.srcFiles);
if (this.argv.watch) {
this.libs.chokidar.watch(this.argv.watchGlob).on('change', (f) => {
this.all = false;
this.setOnlyFiles(path.resolve(f));
this.setupAndRunTests(this.onlyTestFiles, this.onlySrcFiles, true);
});
this.libs.chokidar.watch(this.argv.watchGlob).on('change', f => this.onWatch(path.resolve(f)));
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/node/options.js
Expand Up @@ -28,7 +28,7 @@ module.exports = {
},
watchGlob: {
description: 'Watch glob',
default: ['src/**/*.{js,ts}', 'test/**/*.{js,ts}'],
default: ['src/**/*.{js,ts}', 'test/**/*.spec.{js,ts}'],
type: 'array',
alias: 'wg',
},
Expand Down
5 changes: 2 additions & 3 deletions test/unit/node/index.spec.js
Expand Up @@ -202,11 +202,10 @@ describe('Node command', () => {
const chokidar = { watch };
const runner = new Runner({ watch: true, watchGlob }, { chokidar });
runner.setupAndRunTests = sandbox.stub();
runner.findFiles = sandbox.stub();
runner.onWatch = sandbox.stub();
runner.run();
on.callArg(1, 'foo.js');
expect(runner.all).to.equal(false);
expect(runner.setupAndRunTests.callCount).to.equal(2);
expect(runner.onWatch).to.have.been.calledWithExactly(path.resolve('foo.js'));
});

describe('configure', () => {
Expand Down

0 comments on commit ada5dc6

Please sign in to comment.