1
+ #!/usr/bin/env node
1
2
// @ts -check
2
3
3
4
const fs = require ( 'fs' ) ;
4
5
const path = require ( 'path' ) ;
6
+ const { parseArgs} = require ( 'node:util' ) ;
7
+
5
8
/**
6
9
* The file extension of test files.
7
10
* @type {string }
@@ -24,26 +27,82 @@ const testNameSeparator = ', ';
24
27
*/
25
28
const description = 'JSONPath Compliance Test Suite. This file is autogenerated, do not edit.' ;
26
29
27
- build ( ) ;
28
-
29
30
/**
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 .
32
33
*/
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 ) ) ;
36
71
process . exit ( 1 ) ;
37
72
}
73
+ const [ testsFolder ] = positionals ;
74
+ buildTestSuite ( testsFolder , values [ 'tag' ] , values [ 'require-all' ] , values [ 'exclude' ] ) ;
75
+ }
38
76
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
+ } ) ;
41
98
const cts = { 'description' : description , 'tests' : tests } ;
42
99
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 ( ) ;
43
102
console . error ( `Wrote ${ tests . length } tests to stdout.` ) ;
103
+ console . error ( `Tags (${ allTags . length } ): ${ allTags . join ( ', ' ) } ` ) ;
44
104
}
45
105
46
-
47
106
/**
48
107
* Read all test files from a directory and its subdirectories.
49
108
* The directory name is prepended to the test name.
0 commit comments