From 9d3559338aab8c3de800404b2652747399fc1709 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Sun, 6 Mar 2022 06:11:32 -0800 Subject: [PATCH] Warn when unsupported ava.config.json files are encountered Co-authored-by: Mark Wubben --- lib/cli.js | 9 ++++- lib/eslint-plugin-helper-worker.js | 2 +- lib/load-config.js | 33 +++++++++++++---- .../unsupported-configs/ava.config.js | 3 ++ .../unsupported-configs/ava.config.json | 1 + .../fixtures/unsupported-configs/package.json | 3 ++ test/config/loader.js | 8 +++-- test/config/next-gen.js | 35 +++++++++++++++---- 8 files changed, 76 insertions(+), 18 deletions(-) create mode 100644 test/config/fixtures/unsupported-configs/ava.config.js create mode 100644 test/config/fixtures/unsupported-configs/ava.config.json create mode 100644 test/config/fixtures/unsupported-configs/package.json diff --git a/lib/cli.js b/lib/cli.js index 80d49a69f..482766850 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -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}`)); } diff --git a/lib/eslint-plugin-helper-worker.js b/lib/eslint-plugin-helper-worker.js index e53bca401..fb7ce6054 100644 --- a/lib/eslint-plugin-helper-worker.js +++ b/lib/eslint-plugin-helper-worker.js @@ -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}; })); diff --git a/lib/load-config.js b/lib/load-config.js index e02809ed3..e3c70fd70 100644 --- a/lib/load-config.js +++ b/lib/load-config.js @@ -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}); } }; @@ -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); @@ -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 = []; @@ -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); @@ -139,5 +160,5 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau } } - return config; + return {config, unsupportedFiles}; } diff --git a/test/config/fixtures/unsupported-configs/ava.config.js b/test/config/fixtures/unsupported-configs/ava.config.js new file mode 100644 index 000000000..4a9fb4c27 --- /dev/null +++ b/test/config/fixtures/unsupported-configs/ava.config.js @@ -0,0 +1,3 @@ +export default { + failFast: true, +}; diff --git a/test/config/fixtures/unsupported-configs/ava.config.json b/test/config/fixtures/unsupported-configs/ava.config.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/test/config/fixtures/unsupported-configs/ava.config.json @@ -0,0 +1 @@ +{} diff --git a/test/config/fixtures/unsupported-configs/package.json b/test/config/fixtures/unsupported-configs/package.json new file mode 100644 index 000000000..bedb411a9 --- /dev/null +++ b/test/config/fixtures/unsupported-configs/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/test/config/loader.js b/test/config/loader.js index 1be2d0ec7..8f4c5ae54 100644 --- a/test/config/loader.js +++ b/test/config/loader.js @@ -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()) => { diff --git a/test/config/next-gen.js b/test/config/next-gen.js index 5e62efd21..2bcf4b872 100644 --- a/test/config/next-gen.js +++ b/test/config/next-gen.js @@ -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(); @@ -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(); @@ -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',