From 516000c0ffe5c8a83b8496c42af965beb0c21c2f Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Sun, 6 Feb 2022 09:58:26 -0800 Subject: [PATCH 1/9] Add ava.config.json warning --- lib/load-config.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/load-config.js b/lib/load-config.js index e02809ed3..cf395dfcf 100644 --- a/lib/load-config.js +++ b/lib/load-config.js @@ -3,9 +3,12 @@ import path from 'node:path'; import process from 'node:process'; import url from 'node:url'; +import figures from 'figures'; import {isPlainObject} from 'is-plain-object'; import {packageConfig, packageJsonPath} from 'pkg-conf'; +import {chalk} from './chalk.js'; + const NO_SUCH_FILE = Symbol('no ava.config.js file'); const MISSING_DEFAULT_EXPORT = Symbol('missing default export'); const EXPERIMENTS = new Set(); @@ -63,6 +66,13 @@ async function findRepoRoot(fromDir) { return root; } +function warnOnOldConfig(searchDir) { + const v3ConfigPath = path.join(searchDir, 'ava.config.json'); + if (fs.existsSync(v3ConfigPath)) { + console.log(chalk.magenta(` ${figures.warning} AVA does not support JSON config anymore. Ignoring ${v3ConfigPath}`)); + } +} + export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) { let packageConf = await packageConfig('ava', {cwd: resolveFrom}); const filepath = packageJsonPath(packageConf); @@ -85,6 +95,7 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau } else { let searchDir = projectDir; const stopAt = path.dirname(repoRoot); + warnOnOldConfig(searchDir); do { const results = await Promise.all([ // eslint-disable-line no-await-in-loop loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.js')}), From d5b9d4c3bf8f5a571161ae90935c81fad403e107 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Sun, 13 Feb 2022 20:48:19 -0800 Subject: [PATCH 2/9] Log unsupported configs in cli --- lib/cli.js | 12 +++++++++++- lib/load-config.js | 20 +++++++++++--------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/cli.js b/lib/cli.js index f1597950e..4d157b9a6 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -99,12 +99,22 @@ const FLAGS = { }, }; +function handleUnsupportedConfigs(unsupportedConfigs) { + if (unsupportedConfigs.length === 0) { + return; + } + + console.log(chalk.magenta( + ` ${figures.warning} AVA does not support JSON config anymore, ignoring:\n ${unsupportedConfigs.join('\n ')}` + )); +} + export default async function loadCli() { // eslint-disable-line complexity let conf; let confError; try { const {argv: {config: configFile}} = yargs(hideBin(process.argv)).help(false).version(false); - conf = await loadConfig({configFile}); + conf = await loadConfig({configFile, handleUnsupportedConfigs}); 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/load-config.js b/lib/load-config.js index cf395dfcf..89852cdb2 100644 --- a/lib/load-config.js +++ b/lib/load-config.js @@ -3,12 +3,9 @@ import path from 'node:path'; import process from 'node:process'; import url from 'node:url'; -import figures from 'figures'; import {isPlainObject} from 'is-plain-object'; import {packageConfig, packageJsonPath} from 'pkg-conf'; -import {chalk} from './chalk.js'; - const NO_SUCH_FILE = Symbol('no ava.config.js file'); const MISSING_DEFAULT_EXPORT = Symbol('missing default export'); const EXPERIMENTS = new Set(); @@ -66,14 +63,17 @@ async function findRepoRoot(fromDir) { return root; } -function warnOnOldConfig(searchDir) { - const v3ConfigPath = path.join(searchDir, 'ava.config.json'); - if (fs.existsSync(v3ConfigPath)) { - console.log(chalk.magenta(` ${figures.warning} AVA does not support JSON config anymore. Ignoring ${v3ConfigPath}`)); +function findUnsupportedConfigs(searchDir) { + const unsupportedConfig = path.join(searchDir, 'ava.config.json'); + + if (fs.existsSync(unsupportedConfig)) { + return [unsupportedConfig]; } + + return []; } -export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) { +export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}, handleUnsupportedConfigs = () => {}} = {}) { let packageConf = await packageConfig('ava', {cwd: resolveFrom}); const filepath = packageJsonPath(packageConf); const projectDir = filepath === undefined ? resolveFrom : path.dirname(filepath); @@ -87,6 +87,7 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau let fileConf = NO_SUCH_FILE; let fileForErrorMessage; let conflicting = []; + const unsupportedConfigs = []; if (configFile) { const loaded = await loadConfigFile({projectDir, configFile}); if (loaded !== null) { @@ -95,7 +96,7 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau } else { let searchDir = projectDir; const stopAt = path.dirname(repoRoot); - warnOnOldConfig(searchDir); + unsupportedConfigs.push(...findUnsupportedConfigs(searchDir)); do { const results = await Promise.all([ // eslint-disable-line no-await-in-loop loadConfigFile({projectDir, configFile: path.join(searchDir, 'ava.config.js')}), @@ -150,5 +151,6 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau } } + handleUnsupportedConfigs(unsupportedConfigs); return config; } From f573880e81fddeaa187826a7b2cf61239f61824c Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Sun, 13 Feb 2022 20:51:25 -0800 Subject: [PATCH 3/9] Add unsupported config fixtures --- test/config/fixtures/unsupported-configs/ava.config.js | 3 +++ test/config/fixtures/unsupported-configs/ava.config.json | 1 + test/config/fixtures/unsupported-configs/package.json | 3 +++ 3 files changed, 7 insertions(+) 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/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" +} From 507203dd84a273a02ebdc55d840de1f5957af189 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Sun, 13 Feb 2022 21:09:50 -0800 Subject: [PATCH 4/9] Add test for unsupported configs --- test/config/next-gen.js | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/test/config/next-gen.js b/test/config/next-gen.js index 5e62efd21..52aa0c608 100644 --- a/test/config/next-gen.js +++ b/test/config/next-gen.js @@ -10,13 +10,21 @@ const FIXTURE_ROOT = fileURLToPath(new URL('fixtures', import.meta.url)); const resolve = relpath => path.resolve(FIXTURE_ROOT, relpath); -const loadFromSetup = setup => { +const loadFromSetup = (setup, t) => { if (typeof setup === 'string') { return loadConfig(); } - const {configFile, defaults, resolveFrom} = setup; - return loadConfig({configFile, defaults, resolveFrom}); + const { + configFile, + defaults, + resolveFrom, + handleUnsupportedConfigs = t => unsupportedConfigs => { + t.is(unsupportedConfigs.length, 0); + }, + } = setup; + + return loadConfig({configFile, defaults, resolveFrom, handleUnsupportedConfigs: handleUnsupportedConfigs(t)}); }; const ok = setup => async (t, assert = tt => tt.pass()) => { @@ -26,7 +34,7 @@ const ok = setup => async (t, assert = tt => tt.pass()) => { t.teardown(() => stub.restore()); stub.returns(resolve(fixture)); - const conf = loadFromSetup(setup); + const conf = loadFromSetup(setup, t); 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', + handleUnsupportedConfigs: t => unsupportedConfigs => { + t.is(unsupportedConfigs.length, 1); + t.regex(unsupportedConfigs[0], /test\/config\/fixtures\/unsupported-configs\/ava.config.json/); + }, + }), + (t, conf) => { + t.true(conf.failFast); + }, +); + test.serial('handles errors when loading .js config as ESM', notOk({ fixture: 'js-as-esm', configFile: 'error.js', From 248d37694558f13c2c2634b2f131b514d6c82949 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Sun, 13 Feb 2022 21:22:10 -0800 Subject: [PATCH 5/9] Update warning --- lib/cli.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli.js b/lib/cli.js index 4d157b9a6..691e1f146 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -105,7 +105,7 @@ function handleUnsupportedConfigs(unsupportedConfigs) { } console.log(chalk.magenta( - ` ${figures.warning} AVA does not support JSON config anymore, ignoring:\n ${unsupportedConfigs.join('\n ')}` + ` ${figures.warning} AVA does not support JSON config, ignoring:\n\n ${unsupportedConfigs.join('\n ')}` )); } From 29710cee3a472c4f0e140e4a58b0ddf55acd2ce6 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Tue, 22 Feb 2022 11:02:55 -0800 Subject: [PATCH 6/9] Fix linter error --- lib/cli.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli.js b/lib/cli.js index 691e1f146..c1f2816b2 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -105,7 +105,7 @@ function handleUnsupportedConfigs(unsupportedConfigs) { } console.log(chalk.magenta( - ` ${figures.warning} AVA does not support JSON config, ignoring:\n\n ${unsupportedConfigs.join('\n ')}` + ` ${figures.warning} AVA does not support JSON config, ignoring:\n\n ${unsupportedConfigs.join('\n ')}`, )); } From 8ce0f0d28ced888e3b936c67eac84748fff3bb55 Mon Sep 17 00:00:00 2001 From: Evan Sosenko Date: Tue, 22 Feb 2022 11:37:51 -0800 Subject: [PATCH 7/9] Simplify test --- test/config/next-gen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/config/next-gen.js b/test/config/next-gen.js index 52aa0c608..fcbe0ca52 100644 --- a/test/config/next-gen.js +++ b/test/config/next-gen.js @@ -80,7 +80,7 @@ test.serial('finds unsupported configs', fixture: 'unsupported-configs', handleUnsupportedConfigs: t => unsupportedConfigs => { t.is(unsupportedConfigs.length, 1); - t.regex(unsupportedConfigs[0], /test\/config\/fixtures\/unsupported-configs\/ava.config.json/); + t.regex(unsupportedConfigs[0], /ava\.config\.json/); }, }), (t, conf) => { From aeb8d03c1514fb4c79b936e83e36ae3ee1d37a30 Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Tue, 1 Mar 2022 19:41:26 +0100 Subject: [PATCH 8/9] Avoid fs.existsSync() when loading config files --- lib/load-config.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/load-config.js b/lib/load-config.js index 89852cdb2..be3fc0fcb 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}); } }; From 6070409356113d9136f8f5d1247c3bac288000a5 Mon Sep 17 00:00:00 2001 From: Mark Wubben Date: Tue, 1 Mar 2022 19:42:09 +0100 Subject: [PATCH 9/9] Return unsupported files, check while searching the file system, avoid fs.existsSync --- lib/cli.js | 19 ++++++++---------- lib/eslint-plugin-helper-worker.js | 2 +- lib/load-config.js | 31 ++++++++++++++++++------------ test/config/loader.js | 8 +++++--- test/config/next-gen.js | 24 +++++++++++------------ 5 files changed, 45 insertions(+), 39 deletions(-) diff --git a/lib/cli.js b/lib/cli.js index c1f2816b2..60fd0d824 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -99,22 +99,19 @@ const FLAGS = { }, }; -function handleUnsupportedConfigs(unsupportedConfigs) { - if (unsupportedConfigs.length === 0) { - return; - } - - console.log(chalk.magenta( - ` ${figures.warning} AVA does not support JSON config, ignoring:\n\n ${unsupportedConfigs.join('\n ')}`, - )); -} - export default async function loadCli() { // eslint-disable-line complexity let conf; let confError; try { const {argv: {config: configFile}} = yargs(hideBin(process.argv)).help(false).version(false); - conf = await loadConfig({configFile, handleUnsupportedConfigs}); + 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 be3fc0fcb..e3c70fd70 100644 --- a/lib/load-config.js +++ b/lib/load-config.js @@ -64,17 +64,21 @@ async function findRepoRoot(fromDir) { return root; } -function findUnsupportedConfigs(searchDir) { - const unsupportedConfig = path.join(searchDir, 'ava.config.json'); +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; + } - if (fs.existsSync(unsupportedConfig)) { - return [unsupportedConfig]; + throw error; } - - return []; } -export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}, handleUnsupportedConfigs = () => {}} = {}) { +export async function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) { let packageConf = await packageConfig('ava', {cwd: resolveFrom}); const filepath = packageJsonPath(packageConf); const projectDir = filepath === undefined ? resolveFrom : path.dirname(filepath); @@ -85,10 +89,10 @@ 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 = []; - const unsupportedConfigs = []; if (configFile) { const loaded = await loadConfigFile({projectDir, configFile}); if (loaded !== null) { @@ -97,14 +101,18 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau } else { let searchDir = projectDir; const stopAt = path.dirname(repoRoot); - unsupportedConfigs.push(...findUnsupportedConfigs(searchDir)); 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); @@ -152,6 +160,5 @@ export async function loadConfig({configFile, resolveFrom = process.cwd(), defau } } - handleUnsupportedConfigs(unsupportedConfigs); - return config; + return {config, unsupportedFiles}; } 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 fcbe0ca52..2bcf4b872 100644 --- a/test/config/next-gen.js +++ b/test/config/next-gen.js @@ -10,31 +10,31 @@ const FIXTURE_ROOT = fileURLToPath(new URL('fixtures', import.meta.url)); const resolve = relpath => path.resolve(FIXTURE_ROOT, relpath); -const loadFromSetup = (setup, t) => { +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, - handleUnsupportedConfigs = t => unsupportedConfigs => { - t.is(unsupportedConfigs.length, 0); - }, } = setup; - return loadConfig({configFile, defaults, resolveFrom, handleUnsupportedConfigs: handleUnsupportedConfigs(t)}); + 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, t); + const conf = loadFromSetup(setup, t, assertUnsupportedFiles); await t.notThrowsAsync(conf); const result = await t.try(assert, await conf, setup); result.commit(); @@ -78,14 +78,14 @@ test.serial('loads .js config as ESM', ok('js-as-esm'), (t, conf) => { test.serial('finds unsupported configs', ok({ fixture: 'unsupported-configs', - handleUnsupportedConfigs: t => unsupportedConfigs => { - t.is(unsupportedConfigs.length, 1); - t.regex(unsupportedConfigs[0], /ava\.config\.json/); - }, }), (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({