import path from 'node:path';import {fileURLToPath} from 'node:url';import test from '@ava/test';import sinon from 'sinon';import {loadConfig} from '../../lib/load-config.js';const FIXTURE_ROOT = fileURLToPath(new URL('../../test-tap/fixture/load-config', import.meta.url));const resolve = relpath => path.resolve(FIXTURE_ROOT, relpath);const loadFromSetup = async setup => {if (typeof setup === 'string') {const loaded = await loadConfig();return loaded.config;}const {configFile, defaults, resolveFrom} = setup;const loaded = await loadConfig({configFile, defaults, resolveFrom});return loaded.config;};const ok = setup => async (t, assert = tt => tt.pass()) => {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);await t.notThrowsAsync(conf);const result = await t.try(assert, await conf, setup);result.commit();};const notOk = setup => async (t, assert = (tt, error) => tt.snapshot(error.message, 'error message')) => {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 error = await t.throwsAsync(conf);const result = await t.try(assert, error, setup);result.commit();};test.serial('finds config in package.json', ok('package-only'), (t, conf) => {t.true(conf.failFast);});test.serial('loads config from a particular directory', ok({fixture: 'throws',resolveFrom: resolve('package-only'),}), (t, conf) => {t.true(conf.failFast);});test.serial('throws an error if both configs are present', notOk('package-yes-file-yes'));test.serial('explicit configFile option overrides package.json config', ok({fixture: 'package-yes-explicit-yes',configFile: 'explicit.js',}), (t, conf) => {t.is(conf.files, 'package-yes-explicit-yes-test-value');});test.serial('configFile does not need to be in the same directory as the package.json file', ok({fixture: 'package-yes-explicit-yes',configFile: 'nested/explicit.js',}), (t, config) => {t.is(path.relative(config.projectDir, config.configFile), path.normalize('nested/explicit.js'));});test.serial('throws if configFile option has an unsupported extension', notOk({fixture: 'explicit-bad-extension',configFile: 'explicit.txt',}));test.serial('merges in defaults passed with initial call', ok({fixture: 'package-only',defaults: {files: ['123', '!456'],},}), (t, conf, {defaults}) => {t.true(conf.failFast, 'preserves original props');t.is(conf.files, defaults.files, 'merges in extra props');});test.serial('loads config from file with `export default` syntax', ok('package-no-file-yes'), (t, conf) => {t.is(conf.files, 'config-file-esm-test-value');});test.serial('loads config from factory function', ok('package-no-file-yes-factory'), (t, conf) => {t.assert(conf.files.startsWith(FIXTURE_ROOT));});test.serial('does not support require() inside config.js files', notOk('require'), (t, error) => {t.true(error.message.startsWith('Error loading ava.config.js: require is not defined'));});test.serial('throws an error if a config factory does not return a plain object', notOk('factory-no-plain-return'));test.serial('throws an error if a config does not export a plain object', notOk('no-plain-config'));test.serial('receives a `projectDir` property', (...args) => ok('package-only')(...args), (t, conf) => {t.assert(conf.projectDir.startsWith(FIXTURE_ROOT));});test.serial('rethrows wrapped module errors', notOk('throws'), (t, error) => {t.is(error.cause.message, 'foo');});test.serial('throws an error if a .js config file has no default export', notOk('no-default-export'));test.serial('throws an error if a config file contains `ava` property', notOk('contains-ava-property'));test.serial('throws an error if a config file contains a non-function `filterNodeArgumentsForWorkerThreads` property', notOk('non-function'));test.serial('throws an error if a config file contains a non-object `nonSemVerExperiments` property', notOk('non-object-experiments'));test.serial('throws an error if a config file enables an unsupported experiment', notOk('unsupported-experiments'));test.serial('loads .cjs config', ok('cjs'), (t, conf) => {t.assert(conf.files.startsWith(FIXTURE_ROOT));});test.serial('throws an error if both .js and .cjs configs are present', notOk('file-yes-cjs-yes'));