Skip to content

Commit

Permalink
Implement helper for our ESLint plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
novemberborn committed May 28, 2019
1 parent c10e38c commit 51433be
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 5 deletions.
37 changes: 37 additions & 0 deletions eslint-plugin-helper.js
@@ -0,0 +1,37 @@
'use strict';
const babelPipeline = require('./lib/babel-pipeline');
const normalizeExtensions = require('./lib/extensions');
const {hasExtension, normalizeGlobs, classify} = require('./lib/globs');
const loadConfig = require('./lib/load-config');

const cache = new Map();

function load(projectDir) {
if (cache.has(projectDir)) {
return cache.get(projectDir);
}

const conf = loadConfig(projectDir);
const babelConfig = babelPipeline.validate(conf.babel);
const extensions = normalizeExtensions(conf.extensions || [], babelConfig);
const globs = {cwd: projectDir, ...normalizeGlobs(conf.files, conf.helpers, conf.sources, extensions.all)};

const helper = Object.freeze({
classifyFile: file => classify(file, globs),
classifyImport: importPath => {
if (hasExtension(globs.extensions, importPath)) {
// The importPath has one of the test file extensions: we can classify
// it directly.
return classify(importPath, globs);
}

// Add the first extension. If multiple extensions are available, assume
// patterns are not biased to any particular extension.
return classify(`${importPath}.${globs.extensions[0]}`, globs);
}
});
cache.set(projectDir, helper);
return helper;
}

exports.load = load;
2 changes: 2 additions & 0 deletions lib/globs.js
Expand Up @@ -92,6 +92,8 @@ exports.normalizeGlobs = normalizeGlobs;

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

exports.hasExtension = hasExtension;

const findFiles = async (cwd, patterns) => {
const files = await globby(patterns, {
absolute: true,
Expand Down
6 changes: 3 additions & 3 deletions lib/load-config.js
Expand Up @@ -7,10 +7,10 @@ const pkgConf = require('pkg-conf');
const NO_SUCH_FILE = Symbol('no ava.config.js file');
const MISSING_DEFAULT_EXPORT = Symbol('missing default export');

function loadConfig(defaults = {}) {
const packageConf = pkgConf.sync('ava');
function loadConfig(resolveFrom = process.cwd(), defaults = {}) {
const packageConf = pkgConf.sync('ava', {cwd: resolveFrom});
const filepath = pkgConf.filepath(packageConf);
const projectDir = filepath === null ? process.cwd() : path.dirname(filepath);
const projectDir = filepath === null ? resolveFrom : path.dirname(filepath);

let fileConf;
try {
Expand Down
2 changes: 1 addition & 1 deletion profile.js
Expand Up @@ -32,7 +32,7 @@ function resolveModules(modules) {

Promise.longStackTraces();

const conf = loadConfig({
const conf = loadConfig(undefined, {
babel: {
testOptions: {}
},
Expand Down
94 changes: 94 additions & 0 deletions test/eslint-plugin-helper.js
@@ -0,0 +1,94 @@
'use strict';
const path = require('path');
const {test} = require('tap');

const {load} = require('../eslint-plugin-helper');

const projectDir = path.join(__dirname, 'fixture/eslint-plugin-helper');

test('caches loaded configuration', t => {
const expected = load(projectDir);
const actual = load(projectDir);
t.is(expected, actual);
t.end();
});

test('classifies files according to the configuration', t => {
const helper = load(projectDir);
t.deepEqual(helper.classifyFile(path.join(projectDir, 'tests/test.foo')), {
isHelper: false,
isSource: false,
isTest: true
});
t.deepEqual(helper.classifyFile(path.join(projectDir, 'tests/_helper.foo')), {
isHelper: true,
isSource: false,
isTest: false
});
t.deepEqual(helper.classifyFile(path.join(projectDir, 'helpers/helper.foo')), {
isHelper: true,
isSource: false,
isTest: false
});
t.deepEqual(helper.classifyFile(path.join(projectDir, 'source.foo')), {
isHelper: false,
isSource: true,
isTest: false
});
t.deepEqual(helper.classifyFile(path.join(projectDir, 'tests/test.js')), {
isHelper: false,
isSource: false,
isTest: false
});
t.end();
});

test('classifies imports with extension according to the configuration', t => {
const helper = load(projectDir);
t.deepEqual(helper.classifyImport(path.join(projectDir, 'tests/test.foo')), {
isHelper: false,
isSource: false,
isTest: true
});
t.deepEqual(helper.classifyImport(path.join(projectDir, 'tests/_helper.foo')), {
isHelper: true,
isSource: false,
isTest: false
});
t.deepEqual(helper.classifyImport(path.join(projectDir, 'helpers/helper.foo')), {
isHelper: true,
isSource: false,
isTest: false
});
t.deepEqual(helper.classifyImport(path.join(projectDir, 'source.foo')), {
isHelper: false,
isSource: true,
isTest: false
});
t.end();
});

test('classifies imports without extension according to the configuration', t => {
const helper = load(projectDir);
t.deepEqual(helper.classifyImport(path.join(projectDir, 'tests/test')), {
isHelper: false,
isSource: false,
isTest: true
});
t.deepEqual(helper.classifyImport(path.join(projectDir, 'tests/_helper')), {
isHelper: true,
isSource: false,
isTest: false
});
t.deepEqual(helper.classifyImport(path.join(projectDir, 'helpers/helper')), {
isHelper: true,
isSource: false,
isTest: false
});
t.deepEqual(helper.classifyImport(path.join(projectDir, 'source')), {
isHelper: false,
isSource: true,
isTest: false
});
t.end();
});
6 changes: 6 additions & 0 deletions test/fixture/eslint-plugin-helper/ava.config.js
@@ -0,0 +1,6 @@
export default {
babel: false,
files: ['tests/**/*'],
helpers: ['helpers/*'],
extensions: ['foo']
};
1 change: 1 addition & 0 deletions test/fixture/eslint-plugin-helper/package.json
@@ -0,0 +1 @@
{}
9 changes: 8 additions & 1 deletion test/load-config.js
Expand Up @@ -21,6 +21,13 @@ test('finds config in package.json', t => {
t.end();
});

test('loads config from a particular directory', t => {
changeDir('throws');
const conf = loadConfig(path.resolve(__dirname, 'fixture', 'load-config', 'package-only'));
t.is(conf.failFast, true);
t.end();
});

test('throws a warning of both configs are present', t => {
changeDir('package-yes-file-yes');
t.throws(loadConfig);
Expand All @@ -32,7 +39,7 @@ test('merges in defaults passed with initial call', t => {
const defaults = {
files: ['123', '!456']
};
const {files, failFast} = loadConfig(defaults);
const {files, failFast} = loadConfig(undefined, defaults);
t.is(failFast, true, 'preserves original props');
t.is(files, defaults.files, 'merges in extra props');
t.end();
Expand Down

0 comments on commit 51433be

Please sign in to comment.