Skip to content

Commit

Permalink
Groundwork to support experimental features
Browse files Browse the repository at this point in the history
From time to time, AVA will implement experimental features. These may
change or be removed at any time, not just when there's a new major
version. You can opt-in to such a feature by enabling it in the
`nonSemVerExperiments` configuration.
  • Loading branch information
novemberborn committed Sep 8, 2019
1 parent 0a5c933 commit 03c1509
Show file tree
Hide file tree
Showing 15 changed files with 67 additions and 1 deletion.
15 changes: 15 additions & 0 deletions docs/06-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,19 @@ test('My test', t => {

AVA has a minimum depth of `3`.

## Experiments

From time to time, AVA will implement experimental features. These may change or be removed at any time, not just when there's a new major version. You can opt-in to such a feature by enabling it in the `nonSemVerExperiments` configuration.

`ava.config.js`:
```js
export default {
nonSemVerExperiments: {
feature: true
}
};
```

There are currently no such features available.

[CLI]: ./05-command-line.md
2 changes: 2 additions & 0 deletions docs/support-statement.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ We try to avoid *accidentally* dropping support for non-latest Node.js releases.
We may explicitly drop support for non-latest Node.js releases. If this occurs we will bump AVA's major version number. This may be due to adoption of backported APIs or the availability of newer V8 releases in later Node.js versions, either in AVA itself or one of our dependencies.

We may drop support for a Node.js version, in a major-version-bumping-pre-release, if that new AVA version is expected to become stable around or after the end-of-life date of the Node.js version in question.

Experimental features opted into through the `nonSemVerExperiments` configuration may be changed or removed at any time.
1 change: 1 addition & 0 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class Api extends Emittery {

await this.emit('run', {
clearLogOnNextRun: runtimeOptions.clearLogOnNextRun === true,
experiments: Object.keys(apiOptions.experiments),
failFastEnabled: failFast,
filePathPrefix: commonPathPrefix(files),
files,
Expand Down
1 change: 1 addition & 0 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ exports.run = async () => { // eslint-disable-line complexity
color: conf.color,
compileEnhancements: conf.compileEnhancements !== false,
concurrency: conf.concurrency ? parseInt(conf.concurrency, 10) : 0,
experiments: conf.nonSemVerExperiments,
extensions,
failFast: conf.failFast,
failWithoutAssertions: conf.failWithoutAssertions !== false,
Expand Down
16 changes: 15 additions & 1 deletion lib/load-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const pkgConf = require('pkg-conf');

const NO_SUCH_FILE = Symbol('no ava.config.js file');
const MISSING_DEFAULT_EXPORT = Symbol('missing default export');
const EXPERIMENTS = new Set([]);

function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {}) { // eslint-disable-line complexity
let packageConf = pkgConf.sync('ava', {cwd: resolveFrom});
Expand Down Expand Up @@ -82,7 +83,20 @@ function loadConfig({configFile, resolveFrom = process.cwd(), defaults = {}} = {
}
}

return {...defaults, ...fileConf, ...packageConf, projectDir};
const config = {...defaults, nonSemVerExperiments: {}, ...fileConf, ...packageConf, projectDir};

const {nonSemVerExperiments: experiments} = config;
if (!isPlainObject(experiments)) {
throw new Error(`nonSemVerExperiments from ${fileForErrorMessage} must be an object`);
}

for (const key of Object.keys(experiments)) {
if (!EXPERIMENTS.has(key)) {
throw new Error(`nonSemVerExperiments.${key} from ${fileForErrorMessage} is not a supported experiment`);
}
}

return config;
}

module.exports = loadConfig;
5 changes: 5 additions & 0 deletions lib/reporters/mini.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ class MiniReporter {

cliCursor.hide(this.reportStream);
this.lineWriter.writeLine();

if (plan.experiments.length > 0) {
this.lineWriter.writeLine(colors.information(`${figures.warning} Experiments are enabled. These are unsupported and may change or be be removed at any time.`));
}

this.spinner.start();
}

Expand Down
3 changes: 3 additions & 0 deletions lib/reporters/verbose.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ class VerboseReporter {
}

this.lineWriter.writeLine();
if (plan.experiments.length > 0) {
this.lineWriter.writeLine(colors.information(`${figures.warning} Experiments are enabled. These are unsupported and may change or be removed at any time.${os.EOL}`));
}
}

consumeStateChange(evt) { // eslint-disable-line complexity
Expand Down
1 change: 1 addition & 0 deletions profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ runStatus.observeWorker({
}, file);

reporter.startRun({
experiments: [],
failFastEnabled: false,
files: [file],
matching: false,
Expand Down
1 change: 1 addition & 0 deletions test/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function apiCreator(options = {}) {
options.babelConfig = babelPipeline.validate(options.babelConfig);
options.concurrency = 2;
options.extensions = options.extensions || {all: ['js'], enhancementsOnly: [], full: ['js']};
options.experiments = {};
options.globs = normalizeGlobs(options.files, options.helpers, options.sources, options.extensions.all);
options.projectDir = options.projectDir || ROOT_DIR;
options.resolveTestsFrom = options.resolveTestsFrom || options.projectDir;
Expand Down
3 changes: 3 additions & 0 deletions test/fixture/load-config/non-object-experiments/ava.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
nonSemVerExperiments: []
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
nonSemVerExperiments: {
unsupported: true
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions test/helper/report.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const run = (type, reporter, match = []) => {
require: [],
cacheEnabled: true,
compileEnhancements: true,
experiments: {},
match,
babelConfig: {testOptions: {}},
resolveTestsFrom: projectDir,
Expand Down
12 changes: 12 additions & 0 deletions test/load-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,15 @@ test('throws an error if a config file contains `ava` property', t => {
t.throws(loadConfig, /Encountered 'ava' property in ava.config.js; avoid wrapping the configuration/);
t.end();
});

test('throws an error if a config file contains a non-object `nonSemVerExperiments` property', t => {
changeDir('non-object-experiments');
t.throws(loadConfig, /nonSemVerExperiments from ava.config.js must be an object/);
t.end();
});

test('throws an error if a config file enables an unsupported experiment', t => {
changeDir('unsupported-experiments');
t.throws(loadConfig, /nonSemVerExperiments.unsupported from ava.config.js is not a supported experiment/);
t.end();
});

0 comments on commit 03c1509

Please sign in to comment.