Skip to content

Commit 1e50280

Browse files
committed
Tags
1 parent 082d8a0 commit 1e50280

19 files changed

+2863
-697
lines changed

CONTRIBUTING.md

+39
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,45 @@ To add or modify tests:
3333

3434
Do not modify `cts.json` directly!
3535

36+
37+
### Tags
38+
39+
When adding a new test, please tag it with the appropriate tags. The full list of tags
40+
is printed (to stderr) when running the build script. Please use the
41+
existing tags where possible, and add new tags as needed.
42+
43+
You can build a subset of the test suite by specifying the tags you want to include.
44+
45+
_Example 1._ Build only the tests tagged with `index` OR `whitespace` (or both):
46+
47+
``` shell
48+
node build.js -t index -t whitespace
49+
```
50+
51+
_Example 2._ Build only the tests tagged with `index` AND `whitespace`:
52+
53+
``` shell
54+
node build.js -t index -t whitespace -a
55+
```
56+
57+
Example 3. Build only tests NOT tagged with `index`:
58+
59+
``` shell
60+
node build.js -t index -e
61+
```
62+
63+
Example 4. Exclude tests tagged with BOTH `index` AND `whitespace`:
64+
65+
``` shell
66+
node build.js -t index -t whitespace -t error -e -a
67+
```
68+
69+
### Checking for potential duplicates
70+
71+
As the test suite grows, it is becoming harder to check for potential duplicates. One way to help with this is to see
72+
which tests are tagged with the same tags.
73+
74+
3675
### Staying In Sync With Upstream
3776

3877
When your branch gets out of sync with the jsonpath-standard/jsonpath-compliance-test-suite/main branch, use the following to update:

build.js

100644100755
+69-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
#!/usr/bin/env node
12
// @ts-check
23

34
const fs = require('fs');
45
const path = require('path');
6+
const {parseArgs} = require('node:util');
7+
58
/**
69
* The file extension of test files.
710
* @type {string}
@@ -24,26 +27,82 @@ const testNameSeparator = ', ';
2427
*/
2528
const description = 'JSONPath Compliance Test Suite. This file is autogenerated, do not edit.';
2629

27-
build();
28-
2930
/**
30-
* Build a combined test suite from a directory of test files.
31-
* The output is written to stdout.
31+
* The options for the command line. See https://nodejs.org/api/util.html#utilparseargsconfig.
32+
* IMPORTANT: Update usage if you change these options.
3233
*/
33-
function build() {
34-
if (process.argv.length < 3) {
35-
console.error('Usage: node build.js <test-folder-path>');
34+
const options = {
35+
'tag': {
36+
type: 'string',
37+
short: 't',
38+
multiple: true,
39+
default: [],
40+
},
41+
'require-all': {
42+
type: 'boolean',
43+
short: 'a',
44+
default: false,
45+
},
46+
'exclude': {
47+
type: 'boolean',
48+
short: 'e',
49+
default: false,
50+
}
51+
}
52+
53+
const usage = [
54+
'Build a combined test suite from a directory of test files.',
55+
'',
56+
'Usage: node build.js <test-folder-path> [OPTION]...',
57+
'Options:',
58+
' -t, --tag <tag> Filter tests by tag. Can be used multiple times.',
59+
' Any test with at least one matching tag (by default) or all matching tags (if -a is used)',
60+
' will be included (by default) or excluded (if -e is used) in the output.',
61+
' -a, --require-all Flag to require all tags to be present in a test.',
62+
' -e, --exclude Flag to exclude the specified tags instead of including them.',
63+
]
64+
65+
main()
66+
67+
function main() {
68+
const {values, positionals} = parseArgs({options, allowPositionals: true});
69+
if (positionals.length !== 1) {
70+
usage.forEach(line => console.error(line));
3671
process.exit(1);
3772
}
73+
const [testsFolder] = positionals;
74+
buildTestSuite(testsFolder, values['tag'], values['require-all'], values['exclude']);
75+
}
3876

39-
const testsFolder = process.argv[2];
40-
const tests = readTestsFromDir(testsFolder);
77+
/**
78+
* Build a combined test suite from a directory of test files.
79+
* The output is written to stdout.
80+
* @param testsFolder {string} - The directory containing the test files.
81+
* @param tags {string[]} - The tags to filter tests by.
82+
* @param all {boolean} - True if all tags must match.
83+
* @param exclude {boolean} - True if the tags should be excluded instead of included.
84+
*/
85+
function buildTestSuite(testsFolder, tags, all, exclude) {
86+
console.error(`Building test suite from ${testsFolder}`);
87+
console.error(`Filtering by tags (${tags.length}): ${tags.join(', ')}`);
88+
console.error(`Require all tags: ${all}`);
89+
console.error(`Exclude tags: ${exclude}`);
90+
const tagFilter = all
91+
? list => tags.every(t => list.includes(t))
92+
: list => tags.some(t => list.includes(t))
93+
const tests = readTestsFromDir(testsFolder)
94+
.filter(test => tags.length === 0 || (!tagFilter('tags' in test ? test.tags : []) !== !exclude));
95+
tests.forEach(test => {
96+
if ('tags' in test) test.tags.sort();
97+
});
4198
const cts = {'description': description, 'tests': tests};
4299
console.log(JSON.stringify(cts, null, jsonIndent));
100+
const allTags = Array.from(new Set(tests.flatMap(test => 'tags' in test ? test.tags : [])));
101+
allTags.sort();
43102
console.error(`Wrote ${tests.length} tests to stdout.`);
103+
console.error(`Tags (${allTags.length}): ${allTags.join(', ')}`);
44104
}
45105

46-
47106
/**
48107
* Read all test files from a directory and its subdirectories.
49108
* The directory name is prepended to the test name.

0 commit comments

Comments
 (0)