Skip to content

Commit

Permalink
Warn when unsupported ava.config.json files are encountered
Browse files Browse the repository at this point in the history
Co-authored-by: Mark Wubben <mark@novemberborn.net>
  • Loading branch information
razor-x and novemberborn committed Mar 6, 2022
1 parent ada1a4f commit 9d35593
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 18 deletions.
9 changes: 8 additions & 1 deletion lib/cli.js
Expand Up @@ -104,7 +104,14 @@ export default async function loadCli() { // eslint-disable-line complexity
let confError;
try {
const {argv: {config: configFile}} = yargs(hideBin(process.argv)).help(false).version(false);
conf = await loadConfig({configFile});
const loaded = await loadConfig({configFile});
if (loaded.unsupportedFiles.length > 0) {
console.log(chalk.magenta(
` ${figures.warning} AVA does not support JSON config, ignoring:\n\n ${loaded.unsupportedFiles.join('\n ')}`,
));
}

conf = loaded.config;
if (conf.configFile && path.basename(conf.configFile) !== path.relative(conf.projectDir, conf.configFile)) {
console.log(chalk.magenta(` ${figures.warning} Using configuration from ${conf.configFile}`));
}
Expand Down
2 changes: 1 addition & 1 deletion lib/eslint-plugin-helper-worker.js
Expand Up @@ -41,7 +41,7 @@ const buildGlobs = ({conf, providers, projectDir, overrideExtensions, overrideFi

const resolveGlobs = async (projectDir, overrideExtensions, overrideFiles) => {
if (!configCache.has(projectDir)) {
configCache.set(projectDir, loadConfig({resolveFrom: projectDir}).then(async conf => {
configCache.set(projectDir, loadConfig({resolveFrom: projectDir}).then(async ({config: conf}) => {
const providers = await collectProviders({conf, projectDir});
return {conf, providers};
}));
Expand Down
33 changes: 27 additions & 6 deletions lib/load-config.js
Expand Up @@ -20,14 +20,15 @@ const importConfig = async ({configFile, fileForErrorMessage}) => {
};

const loadConfigFile = async ({projectDir, configFile}) => {
if (!fs.existsSync(configFile)) {
return null;
}

const fileForErrorMessage = path.relative(projectDir, configFile);
try {
await fs.promises.access(configFile);
return {config: await importConfig({configFile, fileForErrorMessage}), configFile, fileForErrorMessage};
} catch (error) {
if (error.code === 'ENOENT') {
return null;
}

throw Object.assign(new Error(`Error loading ${fileForErrorMessage}: ${error.message}`), {parent: error});
}
};
Expand Down Expand Up @@ -63,6 +64,20 @@ async function findRepoRoot(fromDir) {
return root;
}

async function checkJsonFile(searchDir) {
const file = path.join(searchDir, 'ava.config.json');
try {
await fs.promises.access(file);
return file;
} catch (error) {
if (error.code === 'ENOENT') {
return null;
}

throw error;
}
}

export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) {
let packageConf = await packageConfig('ava', {cwd: resolveFrom});
const filepath = packageJsonPath(packageConf);
Expand All @@ -74,6 +89,7 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau
const allowConflictWithPackageJson = Boolean(configFile);
configFile = resolveConfigFile(configFile);

const unsupportedFiles = [];
let fileConf = NO_SUCH_FILE;
let fileForErrorMessage;
let conflicting = [];
Expand All @@ -86,12 +102,17 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau
let searchDir = projectDir;
const stopAt = path.dirname(repoRoot);
do {
const results = await Promise.all([ // eslint-disable-line no-await-in-loop
const [jsonFile, ...results] = await Promise.all([ // eslint-disable-line no-await-in-loop
checkJsonFile(searchDir),
loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.js')}),
loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.cjs')}),
loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.mjs')}),
]);

if (jsonFile !== null) {
unsupportedFiles.push(jsonFile);
}

[{config: fileConf, fileForErrorMessage, configFile} = {config: NO_SUCH_FILE, fileForErrorMessage: undefined}, ...conflicting] = results.filter(result => result !== null);

searchDir = path.dirname(searchDir);
Expand Down Expand Up @@ -139,5 +160,5 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau
}
}

return config;
return {config, unsupportedFiles};
}
3 changes: 3 additions & 0 deletions test/config/fixtures/unsupported-configs/ava.config.js
@@ -0,0 +1,3 @@
export default {
failFast: true,
};
1 change: 1 addition & 0 deletions test/config/fixtures/unsupported-configs/ava.config.json
@@ -0,0 +1 @@
{}
3 changes: 3 additions & 0 deletions test/config/fixtures/unsupported-configs/package.json
@@ -0,0 +1,3 @@
{
"type": "module"
}
8 changes: 5 additions & 3 deletions test/config/loader.js
Expand Up @@ -10,13 +10,15 @@ const FIXTURE_ROOT = fileURLToPath(new URL('../../test-tap/fixture/load-config',

const resolve = relpath => path.resolve(FIXTURE_ROOT, relpath);

const loadFromSetup = setup => {
const loadFromSetup = async setup => {
if (typeof setup === 'string') {
return loadConfig();
const loaded = await loadConfig();
return loaded.config;
}

const {configFile, defaults, resolveFrom} = setup;
return loadConfig({configFile, defaults, resolveFrom});
const loaded = await loadConfig({configFile, defaults, resolveFrom});
return loaded.config;
};

const ok = setup => async (t, assert = tt => tt.pass()) => {
Expand Down
35 changes: 28 additions & 7 deletions test/config/next-gen.js
Expand Up @@ -10,23 +10,31 @@ const FIXTURE_ROOT = fileURLToPath(new URL('fixtures', import.meta.url));

const resolve = relpath => path.resolve(FIXTURE_ROOT, relpath);

const loadFromSetup = setup => {
const loadFromSetup = async (setup, t, assertUnsupportedFiles = (tt, files) => tt.is(files.length, 0)) => {
if (typeof setup === 'string') {
return loadConfig();
const loaded = await loadConfig();
return loaded.config;
}

const {configFile, defaults, resolveFrom} = setup;
return loadConfig({configFile, defaults, resolveFrom});
const {
configFile,
defaults,
resolveFrom,
} = setup;

const loaded = await loadConfig({configFile, defaults, resolveFrom});
assertUnsupportedFiles(t, loaded.unsupportedFiles);
return loaded.config;
};

const ok = setup => async (t, assert = tt => tt.pass()) => {
const ok = setup => async (t, assert = tt => tt.pass(), assertUnsupportedFiles = undefined) => {
const fixture = typeof setup === 'string' ? setup : setup.fixture;

const stub = sinon.stub(process, 'cwd');
t.teardown(() => stub.restore());
stub.returns(resolve(fixture));

const conf = loadFromSetup(setup);
const conf = loadFromSetup(setup, t, assertUnsupportedFiles);
await t.notThrowsAsync(conf);
const result = await t.try(assert, await conf, setup);
result.commit();
Expand All @@ -39,7 +47,7 @@ const notOk = setup => async (t, assert = (tt, error) => tt.snapshot(error.messa
t.teardown(() => stub.restore());
stub.returns(resolve(fixture));

const conf = loadFromSetup(setup);
const conf = loadFromSetup(setup, t);
const error = await t.throwsAsync(conf);
const result = await t.try(assert, error, setup);
result.commit();
Expand Down Expand Up @@ -67,6 +75,19 @@ test.serial('loads .js config as ESM', ok('js-as-esm'), (t, conf) => {
t.true(conf.failFast);
});

test.serial('finds unsupported configs',
ok({
fixture: 'unsupported-configs',
}),
(t, conf) => {
t.true(conf.failFast);
},
(t, unsupportedFiles) => {
t.is(unsupportedFiles.length, 1);
t.regex(unsupportedFiles[0], /ava\.config\.json/);
},
);

test.serial('handles errors when loading .js config as ESM', notOk({
fixture: 'js-as-esm',
configFile: 'error.js',
Expand Down

0 comments on commit 9d35593

Please sign in to comment.