Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,45 @@ To add or modify tests:

Do not modify `cts.json` directly!


### Tags

When adding a new test, please tag it with the appropriate tags. The full list of tags
is printed (to stderr) when running the build script. Please use the
existing tags where possible, and add new tags as needed.

You can build a subset of the test suite by specifying the tags you want to include.

_Example 1._ Build only the tests tagged with `index` OR `whitespace` (or both):

``` shell
node build.js -t index -t whitespace
```

_Example 2._ Build only the tests tagged with `index` AND `whitespace`:

``` shell
node build.js -t index -t whitespace -a
```

Example 3. Build only tests NOT tagged with `index`:

``` shell
node build.js -t index -e
```

Example 4. Exclude tests tagged with BOTH `index` AND `whitespace`:

``` shell
node build.js -t index -t whitespace -t error -e -a
```

### Checking for potential duplicates

As the test suite grows, it is becoming harder to check for potential duplicates. One way to help with this is to see
which tests are tagged with the same tags.


### Staying In Sync With Upstream

When your branch gets out of sync with the jsonpath-standard/jsonpath-compliance-test-suite/main branch, use the following to update:
Expand Down
83 changes: 73 additions & 10 deletions build.js
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#!/usr/bin/env node
// @ts-check

const fs = require('fs');
const path = require('path');
const {parseArgs} = require('node:util');

/**
* The file extension of test files.
* @type {string}
Expand All @@ -24,25 +27,85 @@ const testNameSeparator = ', ';
*/
const description = 'JSONPath Compliance Test Suite. This file is autogenerated, do not edit.';

build();

/**
* Build a combined test suite from a directory of test files.
* The output is written to stdout.
* The options for the command line. See https://nodejs.org/api/util.html#utilparseargsconfig.
* IMPORTANT: Update usage if you change these options.
*/
function build() {
if (process.argv.length < 3) {
console.error('Usage: node build.js <test-folder-path>');
const options = {
'tag': {
type: 'string',
short: 't',
multiple: true,
default: [],
},
'require-all': {
type: 'boolean',
short: 'a',
default: false,
},
'exclude': {
type: 'boolean',
short: 'e',
default: false,
}
}

const usage = [
'Build a combined test suite from a directory of test files.',
'',
'Usage: node build.js <test-folder-path> [OPTION]...',
'Options:',
' -t, --tag <tag> Filter tests by tag. Can be used multiple times.',
' Any test with at least one matching tag (by default) or all matching tags (if -a is used)',
' will be included (by default) or excluded (if -e is used) in the output.',
' -a, --require-all Flag to require all tags to be present in a test.',
' -e, --exclude Flag to exclude the specified tags instead of including them.',
]

main()

function main() {
const {values, positionals} = parseArgs({options, allowPositionals: true});
if (positionals.length !== 1) {
usage.forEach(line => console.error(line));
process.exit(1);
}
const [testsFolder] = positionals;
buildTestSuite(testsFolder, values['tag'], values['require-all'], values['exclude']);
}

const testsFolder = process.argv[2];
const tests = readTestsFromDir(testsFolder);
/**
* Build a combined test suite from a directory of test files.
* The output is written to stdout.
* @param testsFolder {string} - The directory containing the test files.
* @param tags {string[]} - The tags to filter tests by.
* @param all {boolean} - True if all tags must match.
* @param exclude {boolean} - True if the tags should be excluded instead of included.
*/
function buildTestSuite(testsFolder, tags, all, exclude) {
console.error(`Building test suite from ${testsFolder}`);
console.error(`Filtering by tags (${tags.length}): ${tags.join(', ')}`);
console.error(`Require all tags: ${all}`);
console.error(`Exclude tags: ${exclude}`);
const tagFilter = all
? list => tags.every(t => list.includes(t))
: list => tags.some(t => list.includes(t))
const tests = readTestsFromDir(testsFolder)
.filter(test => tags.length === 0 || (tagFilter(getTags(test)) !== exclude));
tests.forEach(test => {
if ('tags' in test) test.tags.sort();
});
const cts = {'description': description, 'tests': tests};
console.log(JSON.stringify(cts, null, jsonIndent));
const allTags = Array.from(new Set(tests.flatMap(getTags)));
allTags.sort();
console.error(`Wrote ${tests.length} tests to stdout.`);
}
console.error(`Tags (${allTags.length}): ${allTags.join(', ')}`);

function getTags(test) {
return 'tags' in test ? test.tags : [];
}
}

/**
* Read all test files from a directory and its subdirectories.
Expand Down
Loading