Skip to content

Commit 51433be

Browse files
committed
Implement helper for our ESLint plugin
1 parent c10e38c commit 51433be

File tree

8 files changed

+152
-5
lines changed

8 files changed

+152
-5
lines changed

eslint-plugin-helper.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use strict';
2+
const babelPipeline = require('./lib/babel-pipeline');
3+
const normalizeExtensions = require('./lib/extensions');
4+
const {hasExtension, normalizeGlobs, classify} = require('./lib/globs');
5+
const loadConfig = require('./lib/load-config');
6+
7+
const cache = new Map();
8+
9+
function load(projectDir) {
10+
if (cache.has(projectDir)) {
11+
return cache.get(projectDir);
12+
}
13+
14+
const conf = loadConfig(projectDir);
15+
const babelConfig = babelPipeline.validate(conf.babel);
16+
const extensions = normalizeExtensions(conf.extensions || [], babelConfig);
17+
const globs = {cwd: projectDir, ...normalizeGlobs(conf.files, conf.helpers, conf.sources, extensions.all)};
18+
19+
const helper = Object.freeze({
20+
classifyFile: file => classify(file, globs),
21+
classifyImport: importPath => {
22+
if (hasExtension(globs.extensions, importPath)) {
23+
// The importPath has one of the test file extensions: we can classify
24+
// it directly.
25+
return classify(importPath, globs);
26+
}
27+
28+
// Add the first extension. If multiple extensions are available, assume
29+
// patterns are not biased to any particular extension.
30+
return classify(`${importPath}.${globs.extensions[0]}`, globs);
31+
}
32+
});
33+
cache.set(projectDir, helper);
34+
return helper;
35+
}
36+
37+
exports.load = load;

lib/globs.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ exports.normalizeGlobs = normalizeGlobs;
9292

9393
const hasExtension = (extensions, file) => extensions.includes(path.extname(file).slice(1));
9494

95+
exports.hasExtension = hasExtension;
96+
9597
const findFiles = async (cwd, patterns) => {
9698
const files = await globby(patterns, {
9799
absolute: true,

lib/load-config.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ const pkgConf = require('pkg-conf');
77
const NO_SUCH_FILE = Symbol('no ava.config.js file');
88
const MISSING_DEFAULT_EXPORT = Symbol('missing default export');
99

10-
function loadConfig(defaults = {}) {
11-
const packageConf = pkgConf.sync('ava');
10+
function loadConfig(resolveFrom = process.cwd(), defaults = {}) {
11+
const packageConf = pkgConf.sync('ava', {cwd: resolveFrom});
1212
const filepath = pkgConf.filepath(packageConf);
13-
const projectDir = filepath === null ? process.cwd() : path.dirname(filepath);
13+
const projectDir = filepath === null ? resolveFrom : path.dirname(filepath);
1414

1515
let fileConf;
1616
try {

profile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ function resolveModules(modules) {
3232

3333
Promise.longStackTraces();
3434

35-
const conf = loadConfig({
35+
const conf = loadConfig(undefined, {
3636
babel: {
3737
testOptions: {}
3838
},

test/eslint-plugin-helper.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
'use strict';
2+
const path = require('path');
3+
const {test} = require('tap');
4+
5+
const {load} = require('../eslint-plugin-helper');
6+
7+
const projectDir = path.join(__dirname, 'fixture/eslint-plugin-helper');
8+
9+
test('caches loaded configuration', t => {
10+
const expected = load(projectDir);
11+
const actual = load(projectDir);
12+
t.is(expected, actual);
13+
t.end();
14+
});
15+
16+
test('classifies files according to the configuration', t => {
17+
const helper = load(projectDir);
18+
t.deepEqual(helper.classifyFile(path.join(projectDir, 'tests/test.foo')), {
19+
isHelper: false,
20+
isSource: false,
21+
isTest: true
22+
});
23+
t.deepEqual(helper.classifyFile(path.join(projectDir, 'tests/_helper.foo')), {
24+
isHelper: true,
25+
isSource: false,
26+
isTest: false
27+
});
28+
t.deepEqual(helper.classifyFile(path.join(projectDir, 'helpers/helper.foo')), {
29+
isHelper: true,
30+
isSource: false,
31+
isTest: false
32+
});
33+
t.deepEqual(helper.classifyFile(path.join(projectDir, 'source.foo')), {
34+
isHelper: false,
35+
isSource: true,
36+
isTest: false
37+
});
38+
t.deepEqual(helper.classifyFile(path.join(projectDir, 'tests/test.js')), {
39+
isHelper: false,
40+
isSource: false,
41+
isTest: false
42+
});
43+
t.end();
44+
});
45+
46+
test('classifies imports with extension according to the configuration', t => {
47+
const helper = load(projectDir);
48+
t.deepEqual(helper.classifyImport(path.join(projectDir, 'tests/test.foo')), {
49+
isHelper: false,
50+
isSource: false,
51+
isTest: true
52+
});
53+
t.deepEqual(helper.classifyImport(path.join(projectDir, 'tests/_helper.foo')), {
54+
isHelper: true,
55+
isSource: false,
56+
isTest: false
57+
});
58+
t.deepEqual(helper.classifyImport(path.join(projectDir, 'helpers/helper.foo')), {
59+
isHelper: true,
60+
isSource: false,
61+
isTest: false
62+
});
63+
t.deepEqual(helper.classifyImport(path.join(projectDir, 'source.foo')), {
64+
isHelper: false,
65+
isSource: true,
66+
isTest: false
67+
});
68+
t.end();
69+
});
70+
71+
test('classifies imports without extension according to the configuration', t => {
72+
const helper = load(projectDir);
73+
t.deepEqual(helper.classifyImport(path.join(projectDir, 'tests/test')), {
74+
isHelper: false,
75+
isSource: false,
76+
isTest: true
77+
});
78+
t.deepEqual(helper.classifyImport(path.join(projectDir, 'tests/_helper')), {
79+
isHelper: true,
80+
isSource: false,
81+
isTest: false
82+
});
83+
t.deepEqual(helper.classifyImport(path.join(projectDir, 'helpers/helper')), {
84+
isHelper: true,
85+
isSource: false,
86+
isTest: false
87+
});
88+
t.deepEqual(helper.classifyImport(path.join(projectDir, 'source')), {
89+
isHelper: false,
90+
isSource: true,
91+
isTest: false
92+
});
93+
t.end();
94+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export default {
2+
babel: false,
3+
files: ['tests/**/*'],
4+
helpers: ['helpers/*'],
5+
extensions: ['foo']
6+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

test/load-config.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ test('finds config in package.json', t => {
2121
t.end();
2222
});
2323

24+
test('loads config from a particular directory', t => {
25+
changeDir('throws');
26+
const conf = loadConfig(path.resolve(__dirname, 'fixture', 'load-config', 'package-only'));
27+
t.is(conf.failFast, true);
28+
t.end();
29+
});
30+
2431
test('throws a warning of both configs are present', t => {
2532
changeDir('package-yes-file-yes');
2633
t.throws(loadConfig);
@@ -32,7 +39,7 @@ test('merges in defaults passed with initial call', t => {
3239
const defaults = {
3340
files: ['123', '!456']
3441
};
35-
const {files, failFast} = loadConfig(defaults);
42+
const {files, failFast} = loadConfig(undefined, defaults);
3643
t.is(failFast, true, 'preserves original props');
3744
t.is(files, defaults.files, 'merges in extra props');
3845
t.end();

0 commit comments

Comments
 (0)