testem 3.19.1 → 3.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,50 +1,50 @@
1
1
  {
2
2
  "name": "testem",
3
- "description": "Test'em 'scripts! Javascript Unit testing made easy.",
3
+ "description": "Test'em 'scripts! JavaScript unit testing made easy.",
4
4
  "keywords": [
5
5
  "javascript",
6
6
  "testing",
7
7
  "unittest",
8
8
  "browser"
9
9
  ],
10
- "version": "3.19.1",
10
+ "version": "3.20.1",
11
11
  "author": "Toby Ho <airportyh@gmail.com>",
12
12
  "repository": {
13
13
  "type": "git",
14
- "url": "git://github.com/testem/testem.git"
14
+ "url": "https://github.com/testem/testem.git"
15
15
  },
16
16
  "bugs": {
17
- "url": "http://github.com/testem/testem/issues"
17
+ "url": "https://github.com/testem/testem/issues"
18
18
  },
19
19
  "engines": {
20
- "node": ">= 7.*"
20
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
21
21
  },
22
22
  "license": "MIT",
23
23
  "dependencies": {
24
- "@xmldom/xmldom": "^0.8.0",
25
- "backbone": "^1.1.2",
26
- "charm": "^1.0.0",
27
- "commander": "^2.6.0",
28
- "compression": "^1.7.4",
24
+ "@xmldom/xmldom": "^0.9.9",
25
+ "backbone": "^1.6.1",
26
+ "charm": "^1.0.2",
27
+ "chokidar": "^5.0.0",
28
+ "commander": "^14.0.3",
29
+ "compression": "^1.8.1",
29
30
  "consolidate": "^1.0.4",
30
31
  "execa": "^9.6.1",
31
- "express": "^4.10.7",
32
- "fireworm": "^0.7.2",
32
+ "express": "^5.2.1",
33
33
  "glob": "^13.0.6",
34
- "http-proxy": "^1.13.1",
35
- "js-yaml": "^3.2.5",
36
- "lodash": "^4.17.21",
34
+ "http-proxy": "^1.18.1",
35
+ "js-yaml": "^4.1.1",
36
+ "lodash": "^4.18.1",
37
+ "minimatch": "^10.2.5",
37
38
  "mkdirp": "^3.0.1",
38
39
  "mustache": "^4.2.0",
39
- "node-notifier": "^10.0.0",
40
+ "toasted-notifier": "^10.1.0",
40
41
  "printf": "^0.6.1",
41
- "proc-log": "^5.0.0",
42
+ "proc-log": "^6.1.0",
42
43
  "rimraf": "^6.1.3",
43
- "socket.io": "^4.5.4",
44
+ "socket.io": "^4.8.3",
44
45
  "spawn-args": "^0.2.0",
45
46
  "styled_string": "0.0.1",
46
- "tap-parser": "^7.0.0",
47
- "tmp": "^0.2.5"
47
+ "tap-parser": "^18.3.0"
48
48
  },
49
49
  "files": [
50
50
  "lib",
@@ -56,32 +56,41 @@
56
56
  "views"
57
57
  ],
58
58
  "scripts": {
59
- "install:all": "npm install && npm install phantomjs-prebuilt",
60
59
  "test": "mocha tests/*_tests.js tests/**/*_tests.js",
61
60
  "test:verbose": "TESTEM_VERBOSE=1 mocha tests/*_tests.js tests/**/*_tests.js",
62
61
  "cover": "cover run ./node_modules/.bin/_mocha tests/*_tests.js tests/**/*_tests.js; cover report html; open cover_html/index.html",
63
62
  "integration": "node ./bin/run-integration.js",
63
+ "ci:safari-smoke": "node ./scripts/safari-ci-smoke.js",
64
64
  "browser-tests": "cd examples/saucelabs/ && ../../testem.js ci -d",
65
65
  "lint": "eslint ."
66
66
  },
67
67
  "devDependencies": {
68
- "@cypress/request": "^3.0.10",
69
- "@esbuild-plugins/node-modules-polyfill": "^0.2.2",
68
+ "@eslint/eslintrc": "^3.3.5",
69
+ "@eslint/js": "^10.0.1",
70
70
  "chai": "^6.2.2",
71
- "chai-files": "^1.2.0",
72
- "chai-shallow-deep-equal": "^1.4.4",
73
- "cheerio": "1.0.0-rc.12",
71
+ "chai-files": "^1.4.0",
72
+ "chai-shallow-deep-equal": "^1.4.6",
73
+ "cheerio": "^1.2.0",
74
74
  "dirty-chai": "^3.0.0",
75
- "esbuild": "^0.25.1",
76
- "eslint": "^9.39.4",
77
- "eslint-plugin-chai-expect": "^3.1.0",
75
+ "esbuild": "^0.27.4",
76
+ "esbuild-plugins-node-modules-polyfill": "^1.8.1",
77
+ "eslint": "^10.2.0",
78
+ "eslint-config-prettier": "^10.1.8",
79
+ "eslint-plugin-chai-expect": "^4.0.0",
78
80
  "eslint-plugin-mocha": "^11.2.0",
79
- "fresh-tape": "^5.5.3",
81
+ "fresh-tape": "^5.9.1",
80
82
  "mocha": "^11.7.5",
81
83
  "saucie": "^4.0.1",
82
84
  "sinon": "^21.0.3",
83
85
  "sinon-chai": "^4.0.1",
84
- "socket.io-client": "^4.1.2"
86
+ "socket.io-client": "^4.8.3"
87
+ },
88
+ "overrides": {
89
+ "mocha": {
90
+ "diff": "^8.0.3",
91
+ "minimatch": "^9.0.7",
92
+ "serialize-javascript": "^7.0.5"
93
+ }
85
94
  },
86
95
  "bin": {
87
96
  "testem": "./testem.js"
package/testem.js CHANGED
@@ -1,76 +1,183 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ const { tryDelegateToLocalTestem } = require('./lib/cli-local-delegation');
4
+ if (require.main === module) {
5
+ tryDelegateToLocalTestem(__filename, process.argv, process.cwd(), process.env);
6
+ }
3
7
 
4
- const program = require('commander');
5
- let progOptions = program;
8
+ const { Command } = require('commander');
6
9
  const Config = require('./lib/config');
7
10
  const Api = require('./lib/api');
8
- let appMode = 'dev';
9
-
10
- program
11
- .version(require(__dirname + '/package').version)
12
- .usage('[options]')
13
- .option('-f, --file [file]', 'config file - defaults to testem.json or testem.yml')
14
- .option('-p, --port [num]', 'server port - defaults to 7357', Number)
15
- .option('--host [hostname]', 'host name - defaults to localhost', String)
16
- .option('-l, --launch [list]', 'list of launchers to launch(comma separated)')
17
- .option('-s, --skip [list]', 'list of launchers to skip(comma separated)')
18
- .option('-d, --debug [file]', 'output debug to debug log - defaults to testem.log')
19
- .option('-t, --test_page [page]', 'the html page to drive the tests')
20
- .option('-g, --growl', 'turn on growl / native notifications');
21
-
22
- program
23
- .command('launchers')
24
- .description('Print the list of available launchers (browsers & process launchers)')
25
- .action(act(env => {
26
- env.__proto__ = program;
27
- progOptions = env;
28
- appMode = 'launchers';
29
- }));
30
-
31
- program
32
- .command('ci')
33
- .description('Continuous integration mode')
34
- .option('-T, --timeout [sec]', 'timeout a browser after [sec] seconds', null)
35
- .option('-P, --parallel [num]', 'number of browsers to run in parallel, defaults to 1', Number)
36
- .option('-b, --bail_on_uncaught_error', 'Bail on any uncaught errors')
37
- .option('-R, --reporter [reporter]', 'Test reporter to use [tap|dot|xunit|teamcity]')
38
- .option('--cwd [path]', 'directory to use as root')
39
- .option('--config_dir [path]', 'directory to use as root for resolving configs, if different than cwd')
40
- .action(act(env => {
41
- env.__proto__ = program;
42
- progOptions = env;
43
- appMode = 'ci';
44
- }));
45
-
46
- program
47
- .command('server')
48
- .description('Run just the server')
49
- .action(act(env => {
50
- env.__proto__ = program;
51
- progOptions = env;
52
- appMode = 'server';
53
- }));
54
-
55
- program.on('--help', () => {
56
- console.log(' Keyboard Controls (in dev mode):\n');
57
- console.log(' ENTER run the tests');
58
- console.log(' q quit');
59
- console.log(' LEFT ARROW move to the next browser tab on the left');
60
- console.log(' RIGHT ARROW move to the next browser tab on the right');
61
- console.log(' TAB switch between top and bottom panel (split mode only)');
62
- console.log(' UP ARROW scroll up in the target text panel');
63
- console.log(' DOWN ARROW scroll down in the target text panel');
64
- console.log(' SPACE page down in the target text panel');
65
- console.log(' b page up in the target text panel');
66
- console.log(' d half a page down in the target text panel');
67
- console.log(' u half a page up in the target text panel');
68
- console.log();
69
- });
70
-
71
- main();
11
+
12
+ // this is to workaround the weird behavior in commander where
13
+ // if you provide additional command line arguments that aren't
14
+ // options, it goes in as a string as the 1st argument of the
15
+ // "action" callback, we don't want this
16
+ function act(fun) {
17
+ return function() {
18
+ let options = arguments[arguments.length - 1];
19
+ fun(options);
20
+ };
21
+ }
22
+
23
+ /**
24
+ * Build and parse a fresh Commander program from the given argv array.
25
+ * Returns { progOptions, appMode } where progOptions is a plain object
26
+ * containing all resolved option values (from program.opts() /
27
+ * optsWithGlobals()), so option values are directly accessible as
28
+ * properties rather than requiring access via a Command instance.
29
+ * A _commander reference is attached for internal option enumeration.
30
+ *
31
+ * @param {string[]} argv - process.argv-style array
32
+ * @param {{ exitOverride?: boolean }} [opts]
33
+ * exitOverride: when true, commander throws instead of calling process.exit
34
+ * (useful in tests to prevent the process from terminating)
35
+ */
36
+ function parseArgs(argv, { exitOverride = false } = {}) {
37
+ let progOptions = null;
38
+ let appMode = 'dev';
39
+
40
+ const program = new Command();
41
+
42
+ if (exitOverride) {
43
+ program.exitOverride();
44
+ }
45
+
46
+ program
47
+ .version(require(__dirname + '/package').version)
48
+ .usage('[options]')
49
+ .option(
50
+ '-f, --file [file]',
51
+ 'config file path (JSON, YAML, or JS: testem.js / testem.cjs / testem.mjs); when omitted, picks the first match among defaults (see docs)',
52
+ )
53
+ .option('-p, --port [num]', 'server port - defaults to 7357', Number)
54
+ .option('--host [hostname]', 'host name - defaults to localhost', String)
55
+ .option(
56
+ '-l, --launch [list]',
57
+ 'list of launchers to launch(comma separated)',
58
+ )
59
+ .option('-s, --skip [list]', 'list of launchers to skip(comma separated)')
60
+ .option(
61
+ '-d, --debug [file]',
62
+ 'output debug to debug log - defaults to testem.log',
63
+ )
64
+ .option('-t, --test_page [page]', 'the html page to drive the tests')
65
+ .option('-g, --growl', 'turn on growl / native notifications')
66
+ // A root action is required in commander v7+ to prevent the program from
67
+ // automatically displaying help and exiting when no subcommand is given.
68
+ // Without it, running `testem` (dev mode) would show help instead of
69
+ // starting the dev server.
70
+ .action(() => {});
71
+
72
+ program
73
+ .command('launchers')
74
+ .description(
75
+ 'Print the list of available launchers (browsers & process launchers)',
76
+ )
77
+ .action(
78
+ act((env) => {
79
+ progOptions = env.optsWithGlobals();
80
+ progOptions._commander = env;
81
+ appMode = 'launchers';
82
+ }),
83
+ );
84
+
85
+ program
86
+ .command('ci')
87
+ .description('Continuous integration mode')
88
+ .option(
89
+ '-T, --timeout [sec]',
90
+ 'timeout a browser after [sec] seconds',
91
+ null,
92
+ )
93
+ .option(
94
+ '-P, --parallel [num]',
95
+ 'number of browsers to run in parallel, defaults to 1',
96
+ Number,
97
+ )
98
+ .option('-b, --bail_on_uncaught_error', 'Bail on any uncaught errors')
99
+ .option(
100
+ '-R, --reporter [reporter]',
101
+ 'Test reporter to use [tap|dot|xunit|teamcity]',
102
+ )
103
+ .option('--cwd [path]', 'directory to use as root')
104
+ .option(
105
+ '--config_dir [path]',
106
+ 'directory to use as root for resolving configs, if different than cwd',
107
+ )
108
+ .action(
109
+ act((env) => {
110
+ progOptions = env.optsWithGlobals();
111
+ progOptions._commander = env;
112
+ appMode = 'ci';
113
+ }),
114
+ );
115
+
116
+ program
117
+ .command('server')
118
+ .description('Run just the server')
119
+ .action(
120
+ act((env) => {
121
+ progOptions = env.optsWithGlobals();
122
+ progOptions._commander = env;
123
+ appMode = 'server';
124
+ }),
125
+ );
126
+
127
+ program.on('--help', () => {
128
+ console.log(' Keyboard Controls (in dev mode):\n');
129
+ console.log(' ENTER run the tests');
130
+ console.log(' q quit');
131
+ console.log(
132
+ ' LEFT ARROW move to the next browser tab on the left',
133
+ );
134
+ console.log(
135
+ ' RIGHT ARROW move to the next browser tab on the right',
136
+ );
137
+ console.log(
138
+ ' TAB switch between top and bottom panel (split mode only)',
139
+ );
140
+ console.log(
141
+ ' UP ARROW scroll up in the target text panel',
142
+ );
143
+ console.log(
144
+ ' DOWN ARROW scroll down in the target text panel',
145
+ );
146
+ console.log(
147
+ ' SPACE page down in the target text panel',
148
+ );
149
+ console.log(' b page up in the target text panel');
150
+ console.log(
151
+ ' d half a page down in the target text panel',
152
+ );
153
+ console.log(
154
+ ' u half a page up in the target text panel',
155
+ );
156
+ console.log();
157
+ });
158
+
159
+ program.parse(argv);
160
+
161
+ if (progOptions === null) {
162
+ // dev mode: no subcommand was invoked; use opts() so option values are
163
+ // plain properties rather than requiring access via the Command object
164
+ // (commander v14 no longer exposes options as direct Command properties)
165
+ const devOpts = program.opts();
166
+ devOpts._commander = program;
167
+ progOptions = devOpts;
168
+ }
169
+
170
+ return { progOptions, appMode };
171
+ }
172
+
173
+ module.exports = { parseArgs };
174
+
175
+ if (require.main === module) {
176
+ main();
177
+ }
178
+
72
179
  function main() {
73
- program.parse(process.argv);
180
+ const { progOptions, appMode } = parseArgs(process.argv);
74
181
 
75
182
  let config = new Config(appMode, progOptions);
76
183
  if (appMode === 'launchers') {
@@ -86,14 +193,3 @@ function main() {
86
193
  }
87
194
  }
88
195
  }
89
-
90
- // this is to workaround the weird behavior in command where
91
- // if you provide additional command line arguments that aren't
92
- // options, it goes in as a string as the 1st arguments of the
93
- // "action" callback, we don't want this
94
- function act(fun) {
95
- return function() {
96
- let options = arguments[arguments.length - 1];
97
- fun(options);
98
- };
99
- }