Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warn when unsupported ava.config.json files are encountered #2962

Merged
merged 9 commits into from Mar 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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