Skip to content

Commit

Permalink
cleanup mocha implementation
Browse files Browse the repository at this point in the history
* Fixes depcheck#287
* Fixes depcheck#241
  • Loading branch information
43081j committed Feb 3, 2019
1 parent aab8370 commit 4f7773d
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 23 deletions.
85 changes: 63 additions & 22 deletions src/special/mocha.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,82 @@
import fs from 'fs';
import path from 'path';
import lodash from 'lodash';
import requirePackageName from 'require-package-name';
import { getScripts } from '../utils';

function getOpts(script) {
const argvs = script.split(' ').filter(argv => argv);
const knownReporters = [
'dot', 'doc', 'tap', 'json', 'html', 'list',
'min', 'spec', 'nyan', 'xunit', 'markdown', 'progress',
'landing', 'json-stream',
];

function getOptsConfig(root, config) {
const argvs = config.split(/\s+/);
const optsIndex = argvs.indexOf('--opts');
return optsIndex !== -1 ? argvs[optsIndex + 1] : null;

if (optsIndex === -1) {
return null;
}

const optsPath = argvs[optsIndex + 1];

if (!optsPath) {
return null;
}

return fs.readFileSync(path.resolve(root, '..', optsPath), 'utf-8');
}

function getRequires(content, deps) {
return content
.split('\n')
.map(line => line.trim())
.filter(line => line.indexOf('--require ') === 0)
.map(line => line.substring('--require '.length).trim())
function getDependencies(content, deps) {
const lines = content.split(/\s+/);
const result = [];

lines.forEach((line, idx) => {
if (line === '--require') {
const val = lines[idx + 1];
if (val && !val.startsWith('--')) {
result.push(val);
}
}
if (line === '--reporter') {
const val = lines[idx + 1];
if (val && !val.startsWith('--') && !knownReporters.includes(val)) {
result.push(val);
}
}
});

return result
.map(requirePackageName)
.filter(name => deps.indexOf(name) !== -1);
.filter((v, k, arr) => arr.indexOf(v) === k)
.filter(name => deps.includes(name));
}

export default function parseMocha(content, filepath, deps, rootDir) {
const defaultOptPath = path.resolve(rootDir, 'test/mocha.opts');
let config;

if (filepath === defaultOptPath) {
return getRequires(content, deps);
config = content;
} else {
const scripts = getScripts(filepath, content);
const mochaScript = scripts.find(s => s.indexOf('mocha') !== -1);
if (mochaScript) {
config = mochaScript.slice(mochaScript.indexOf('mocha'));
}
}

if (!config) {
return [];
}

const requires = [];
const optsConfig = getOptsConfig(filepath, config);

if (optsConfig) {
requires.push(...getDependencies(optsConfig, deps));
}

// get mocha.opts from scripts
const requires = lodash(getScripts(filepath, content))
.filter(script => script.indexOf('mocha') !== -1)
.map(script => getOpts(script))
.filter(opts => opts)
.map(opts => path.resolve(filepath, '..', opts))
.map(optPath => fs.readFileSync(optPath, 'utf-8')) // TODO async read file
.map(optContent => getRequires(optContent, deps))
.flatten()
.value();
requires.push(...getDependencies(config, deps));

return requires;
}
6 changes: 6 additions & 0 deletions src/utils/get-scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ import lodash from 'lodash';

const scriptCache = {};

export function clearCache() {
Object.keys(scriptCache).forEach((key) => {
scriptCache[key] = undefined;
});
}

function getCacheOrFile(key, fn) {
if (scriptCache[key]) {
return scriptCache[key];
Expand Down
70 changes: 69 additions & 1 deletion test/special/mocha.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
/* global describe, it */
/* global describe, it, beforeEach */

import 'should';
import fs from 'fs';
import path from 'path';
import parse from '../../src/special/mocha';
import { clearCache } from '../../src/utils/get-scripts';

describe('mocha special parser', () => {
beforeEach(() => {
clearCache();
});

it('should ignore when filename is not supported', () => {
const result = parse('content', 'not-supported.txt', [], __dirname);
result.should.deepEqual([]);
Expand Down Expand Up @@ -33,4 +38,67 @@ describe('mocha special parser', () => {
const result = parse(packageContent, packagePath, dependencies, rootDir);
result.should.deepEqual(['babel', 'chai']);
});

it('should recognise requires from scripts', () => {
const result = parse(`{
"scripts": {
"test": "mocha --require chai --require chai/index *"
}
}`, path.resolve(__dirname, 'package.json'), [
'chai',
], __dirname);
result.should.deepEqual(['chai']);
});

it('should recognise reporters from scripts', () => {
const result = parse(`{
"scripts": {
"test": "mocha --reporter custom-reporter *"
}
}`, path.resolve(__dirname, 'package.json'), [
'custom-reporter',
], __dirname);
result.should.deepEqual(['custom-reporter']);
});

it('should recognise requires from complex scripts', () => {
const result = parse(`{
"scripts": {
"test": "someci command --require ignoreme && mocha --require chai *"
}
}`, path.resolve(__dirname, 'package.json'), [
'chai',
], __dirname);
result.should.deepEqual(['chai']);
});

it('should recognise reporters from opts', () => {
const optPath = path.resolve(__dirname, 'test/mocha.opts');
const result = parse('--reporter foo-bar', optPath, ['foo-bar'], __dirname);
result.should.deepEqual(['foo-bar']);
});

it('should ignore invalid flags', () => {
const optPath = path.resolve(__dirname, 'test/mocha.opts');
const result = parse('--reporter --require --reporter', optPath, [], __dirname);
result.should.deepEqual([]);
});

it('should ignore opts flag', () => {
const optPath = path.resolve(__dirname, 'test/mocha.opts');
const result = parse('--opts', optPath, [], __dirname);
result.should.deepEqual([]);
});

[
'dot', 'doc', 'tap', 'json', 'html', 'list',
'min', 'spec', 'nyan', 'xunit', 'markdown', 'progress',
'landing', 'json-stream',
].forEach((reporter) => {
it(`should ignore built-in reporters (${reporter})`, () => {
const optPath = path.resolve(__dirname, 'test/mocha.opts');
const result = parse(`--reporter ${reporter}`, optPath, [], __dirname);
result.should.deepEqual([]);
});
});
});

0 comments on commit 4f7773d

Please sign in to comment.