Skip to content

Commit 08c6108

Browse files
committed
chore(ses-ava): Replace dynamic CLI options with static ones
Fixes #2998 Replace --no-config-$name and --only-config-$name with --exclude $name and --only $name (and respective shorthands -x $name and -o $name).
1 parent e914ed8 commit 08c6108

File tree

5 files changed

+42
-40
lines changed

5 files changed

+42
-40
lines changed

packages/ses-ava/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ SES-AVA also provides a command line tool, `ses-ava`, that can run AVA with
3636
multiple configurations in a single command, intercepting flags to filter
3737
for interesting configurations.
3838
The `ses-ava` command consumes the `"ava"` and (new) `"sesAvaConfigs"` properties
39-
in `package.json` to discover and name the supported configurations and infer
40-
flags like `--only-config-configname` and `--no-config-configname` for each,
41-
where the `"ava"` configuration is the `default`, if present.
39+
in `package.json` to discover and name the supported configurations which can be
40+
referenced by `--only` and `--exclude` options (and their respective `-o` and
41+
`-x` shorthands), where the `"ava"` configuration is the `default`, if present.
4242

4343
With appropriate configurations, packages can run many of the same tests
4444
with or without an initialized Endo environment.
@@ -93,8 +93,8 @@ Then, in `package.json`, we can use `ses-ava` instead of `ava`.
9393
}
9494
```
9595

96-
With this configuration, `ses-ava ...args --no-config-lockdown` and `ses-ava
97-
...args --only-config-unsafe` would both just run the `unsafe` configuration.
96+
With this configuration, `ses-ava ...args --exclude lockdown` and `ses-ava
97+
...args --only unsafe` would both just run the `unsafe` configuration.
9898
Using `ses-ava` under `c8` allows all configurations to cover used code.
9999

100100
# Compatibility

packages/ses-ava/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
"lint-fix": "eslint --fix .",
4141
"lint:eslint": "eslint .",
4242
"lint:types": "tsc",
43-
"test": "ava && bin/ses-ava --only-config-env --only-config-raw"
43+
"test": "ava && bin/ses-ava --only env --only raw"
4444
},
4545
"dependencies": {
4646
"@endo/env-options": "workspace:^",

packages/ses-ava/src/command.js

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
* Each of these configurations requires a separate AVA config file like
77
* test/_ava.special.config.js and a name.
88
* The ses-ava command will by default run all tests in every mode but allows
9-
* the user to pass --only-* and --no-* at any argument position for any of
10-
* the named configurations to filter.
9+
* the user to pass --only <name> and --exclude <name> (or shorthands -o <name>
10+
* and -x <name>) at any argument position for any of the named configurations
11+
* to filter.
1112
* Consequently, the "test" script for a package using ses-ava can simply be
1213
* "ses-ava" and preserves the filtering behaviors of the underlying "ava"
1314
* sessions if run like `yarn test -m file`.
@@ -46,8 +47,6 @@ export const main = async () => {
4647
if (ava) sesAvaConfigs.default = undefined;
4748
const keys = Object.keys(sesAvaConfigs);
4849
const allConfigNames = new Set(keys);
49-
const noFlags = new Map(keys.map(key => [`--no-config-${key}`, key]));
50-
const onlyFlags = new Map(keys.map(key => [`--only-config-${key}`, key]));
5150

5251
// Parse arguments.
5352
const passThroughArgs = [];
@@ -56,38 +55,43 @@ export const main = async () => {
5655
let failFast = false;
5756
let firstArg = true;
5857
const argsIterator = process.argv.slice(2)[Symbol.iterator]();
59-
for (const arg of argsIterator) {
60-
if (arg === '--') {
58+
for (const rawArg of argsIterator) {
59+
if (rawArg === '--') {
6160
passThroughArgs.push(...argsIterator);
6261
break;
6362
}
64-
const noKey = noFlags.get(arg);
65-
const onlyKey = onlyFlags.get(arg);
66-
const equalsAt = arg.indexOf('=');
67-
if (passThroughFlags.has(arg)) {
68-
passThroughArgs.push(arg);
69-
} else if (arg.startsWith('--') && equalsAt !== -1) {
70-
const flag = arg.slice(0, equalsAt);
71-
if (!passThroughArgOptions.has(flag)) {
72-
throw new Error(`Unrecognized flag ${flag}`);
63+
const charsBeforeOptArg = rawArg.startsWith('--') ? rawArg.indexOf('=') : 2;
64+
const arg =
65+
charsBeforeOptArg !== -1 ? rawArg.slice(0, charsBeforeOptArg) : rawArg;
66+
const getOptArg = () => {
67+
if (charsBeforeOptArg !== -1) {
68+
if (rawArg.startsWith('--')) return rawArg.slice(charsBeforeOptArg + 1);
69+
if (rawArg.length > 2) return rawArg.slice(2);
7370
}
74-
passThroughArgs.push(arg);
75-
} else if (passThroughArgOptions.has(arg)) {
76-
const { value: nextArg, done } = argsIterator.next();
71+
const { value, done } = argsIterator.next();
7772
if (done) {
7873
throw new Error(`Expected argument after ${arg}`);
7974
}
80-
passThroughArgs.push(arg, nextArg);
81-
} else if (arg === '--fail-fast') {
75+
return value;
76+
};
77+
if (passThroughFlags.has(arg)) {
78+
passThroughArgs.push(rawArg);
79+
} else if (passThroughArgOptions.has(arg)) {
80+
if (arg !== rawArg) {
81+
passThroughArgs.push(rawArg);
82+
} else {
83+
passThroughArgs.push(arg, getOptArg());
84+
}
85+
} else if (rawArg === '--fail-fast') {
8286
// Pass-through too
83-
passThroughArgs.push(arg);
87+
passThroughArgs.push(rawArg);
8488
failFast = true;
8589
} else if (arg === 'reset-cache' && firstArg) {
86-
passThroughArgs.push(arg);
87-
} else if (noKey) {
88-
noConfigNames.add(noKey);
89-
} else if (onlyKey) {
90-
onlyConfigNames.add(onlyKey);
90+
passThroughArgs.push(rawArg);
91+
} else if (arg === '--exclude' || arg === '-x') {
92+
noConfigNames.add(getOptArg());
93+
} else if (arg === '--only' || arg === '-o') {
94+
onlyConfigNames.add(getOptArg());
9195
} else if (arg.startsWith('-')) {
9296
throw new Error(
9397
`Unknown flag ${arg}. If this is an ava flag, pass through after --.`,
@@ -102,11 +106,9 @@ export const main = async () => {
102106
const configs = new Set();
103107
for (const config of noConfigNames) {
104108
if (onlyConfigNames.has(config)) {
105-
// Ask not the advice of wizards, for they will say both --no-config- and
106-
// --only-config-.
107-
throw new Error(
108-
`ses-ava cannot respect both --no-config-${config} and --only-config-${config}`,
109-
);
109+
// Ask not the advice of wizards, for they will say both --include and
110+
// --exclude.
111+
throw new Error(`ses-ava cannot both include and exclude ${config}`);
110112
}
111113
}
112114
for (const config of onlyConfigNames.size > 0

packages/ses-ava/test/ses-ava.env-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
import test from 'ava';
44

55
test('ses-ava env', t => {
6-
// ses-ava --only-config-* flag sees this test and the corresponding config
6+
// ses-ava `--only env` flag sees this test and the corresponding config
77
t.is(process.env.SES_AVA, '1');
88
});
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import test from 'ava';
22

3-
test('ses-ava --no-config-* prevents this test from being discovered', t => {
4-
t.fail('should not be reachable because --no-config-two');
3+
test('ses-ava --exclude prevents this test from being discovered', t => {
4+
t.fail('should not be reachable because --exclude two');
55
});

0 commit comments

Comments
 (0)