qunitx-cli 0.1.2 → 0.5.0
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/.claude/settings.local.json +7 -0
- package/.env +1 -0
- package/Makefile +35 -0
- package/README.md +120 -49
- package/cli.js +1 -1
- package/cliff.toml +23 -0
- package/demo/demo.gif +0 -0
- package/demo/demo.tape +59 -0
- package/demo/example-test.js +53 -0
- package/demo/failing-test.js +22 -0
- package/flake.lock +4 -4
- package/flake.nix +33 -4
- package/lib/boilerplates/default-project-config-values.js +2 -2
- package/lib/boilerplates/test.js +5 -4
- package/lib/commands/generate.js +6 -8
- package/lib/commands/help.js +8 -8
- package/lib/commands/init.js +35 -25
- package/lib/commands/run/tests-in-browser.js +97 -67
- package/lib/commands/run.js +165 -55
- package/lib/servers/http.js +53 -42
- package/lib/setup/bind-server-to-port.js +3 -12
- package/lib/setup/browser.js +26 -18
- package/lib/setup/config.js +8 -10
- package/lib/setup/file-watcher.js +23 -6
- package/lib/setup/fs-tree.js +29 -27
- package/lib/setup/keyboard-events.js +7 -4
- package/lib/setup/test-file-paths.js +25 -23
- package/lib/setup/web-server.js +87 -61
- package/lib/setup/write-output-static-files.js +4 -1
- package/lib/tap/display-final-result.js +2 -2
- package/lib/tap/display-test-result.js +32 -14
- package/lib/utils/find-chrome.js +16 -0
- package/lib/utils/find-internal-assets-from-html.js +7 -5
- package/lib/utils/find-project-root.js +1 -2
- package/lib/utils/indent-string.js +6 -6
- package/lib/utils/listen-to-keyboard-key.js +6 -2
- package/lib/utils/parse-cli-flags.js +34 -31
- package/lib/utils/resolve-port-number-for.js +3 -3
- package/lib/utils/run-user-module.js +5 -3
- package/lib/utils/search-in-parent-directories.js +4 -1
- package/lib/utils/time-counter.js +2 -2
- package/package.json +21 -35
- package/vendor/qunit.css +7 -7
- package/vendor/qunit.js +3772 -3324
package/.env
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export CHROME_BIN=$(which google-chrome-stable)
|
package/Makefile
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.PHONY: check test lint build demo release
|
|
2
|
+
|
|
3
|
+
check: lint test
|
|
4
|
+
|
|
5
|
+
lint:
|
|
6
|
+
npm run lint
|
|
7
|
+
|
|
8
|
+
test:
|
|
9
|
+
npm test
|
|
10
|
+
|
|
11
|
+
build:
|
|
12
|
+
npm run build
|
|
13
|
+
|
|
14
|
+
# Regenerate demo/demo.gif using VHS.
|
|
15
|
+
# Requires: vhs (brew install vhs | nix profile install nixpkgs#vhs)
|
|
16
|
+
# Chrome (google-chrome-stable or chromium)
|
|
17
|
+
demo:
|
|
18
|
+
@which vhs > /dev/null 2>&1 || (echo "vhs not found — install: brew install vhs or nix profile install nixpkgs#vhs" && exit 1)
|
|
19
|
+
@CHROME=$$(which google-chrome-stable 2>/dev/null || which google-chrome 2>/dev/null || which chromium 2>/dev/null); \
|
|
20
|
+
test -n "$$CHROME" || (echo "Chrome not found — install google-chrome-stable or chromium" && exit 1); \
|
|
21
|
+
CHROME_BIN=$$CHROME vhs demo/demo.tape
|
|
22
|
+
|
|
23
|
+
# Lint, bump version, update changelog, commit, tag, push, publish to npm.
|
|
24
|
+
# CI then pushes the versioned Docker image and creates the GitHub release.
|
|
25
|
+
# Usage: make release LEVEL=patch|minor|major
|
|
26
|
+
release:
|
|
27
|
+
@test -n "$(LEVEL)" || (echo "Usage: make release LEVEL=patch|minor|major" && exit 1)
|
|
28
|
+
npm run lint
|
|
29
|
+
npm version $(LEVEL) --no-git-tag-version
|
|
30
|
+
npm run changelog:update
|
|
31
|
+
git add package.json package-lock.json CHANGELOG.md
|
|
32
|
+
git commit -m "Release $$(node -p 'require("./package.json").version')"
|
|
33
|
+
git tag "v$$(node -p 'require("./package.json").version')"
|
|
34
|
+
git push && git push --tags
|
|
35
|
+
npm publish --access public
|
package/README.md
CHANGED
|
@@ -1,92 +1,163 @@
|
|
|
1
|
-
#
|
|
1
|
+
# qunitx-cli
|
|
2
2
|
|
|
3
|
-
CI
|
|
3
|
+
[](https://github.com/izelnakri/qunitx-cli/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/qunitx-cli)
|
|
5
|
+
[](https://www.npmjs.com/package/qunitx-cli)
|
|
6
|
+
[](LICENSE)
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
Browser-based test runner for [QUnitX](https://github.com/izelnakri/qunitx) — bundles your JS/TS tests
|
|
9
|
+
with esbuild, runs them in headless Chrome, and streams TAP output to the terminal.
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
output in anyway you like. Example:
|
|
11
|
+

|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- Runs `.js` and `.ts` test files in headless Chrome (Puppeteer + esbuild)
|
|
16
|
+
- TypeScript works with zero configuration — esbuild handles transpilation
|
|
17
|
+
- Inline source maps for accurate stack traces pointing to original source files
|
|
18
|
+
- Streams TAP-formatted output to the terminal in real time
|
|
19
|
+
- Concurrent mode (default) splits test files across all CPU cores for fast parallel runs
|
|
20
|
+
- `--watch` mode re-runs affected tests on file change
|
|
21
|
+
- `--failFast` stops the run after the first failing test
|
|
22
|
+
- `--debug` prints the local server URL and pipes browser console to stdout
|
|
23
|
+
- `--before` / `--after` hook scripts for server setup and teardown
|
|
24
|
+
- `--timeout` controls the maximum ms to wait for the full suite to finish
|
|
25
|
+
- Docker image for zero-install CI usage
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
Requires Node.js >= 24.
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
npm install --save-dev qunitx-cli
|
|
13
33
|
```
|
|
14
34
|
|
|
15
|
-
|
|
35
|
+
Or run without installing:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
npx qunitx test/**/*.js
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
With Docker — no install needed:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
docker run --rm -v "$(pwd):/code" -w /code ghcr.io/izelnakri/qunitx-cli:latest npx qunitx test/**/*.js
|
|
45
|
+
```
|
|
16
46
|
|
|
17
|
-
|
|
18
|
-
npm install -g qunitx-cli
|
|
47
|
+
With Nix:
|
|
19
48
|
|
|
20
|
-
|
|
49
|
+
```sh
|
|
50
|
+
nix profile install github:izelnakri/qunitx-cli
|
|
21
51
|
```
|
|
22
52
|
|
|
23
|
-
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
# Single file
|
|
57
|
+
qunitx test/my-test.js
|
|
58
|
+
|
|
59
|
+
# Multiple files / globs
|
|
60
|
+
qunitx test/**/*.js test/**/*.ts
|
|
61
|
+
|
|
62
|
+
# TypeScript — no tsconfig required
|
|
63
|
+
qunitx test/my-test.ts
|
|
64
|
+
|
|
65
|
+
# Watch mode: re-run on file changes
|
|
66
|
+
qunitx test/**/*.js --watch
|
|
67
|
+
|
|
68
|
+
# Stop on the first failure
|
|
69
|
+
qunitx test/**/*.js --failFast
|
|
70
|
+
|
|
71
|
+
# Print the server URL and pipe Chrome console to stdout
|
|
72
|
+
qunitx test/**/*.js --debug
|
|
73
|
+
|
|
74
|
+
# Custom timeout (ms)
|
|
75
|
+
qunitx test/**/*.js --timeout=30000
|
|
76
|
+
|
|
77
|
+
# Run a setup script before tests (can be async — awaited automatically)
|
|
78
|
+
qunitx test/**/*.js --before=scripts/start-server.js
|
|
79
|
+
|
|
80
|
+
# Run a teardown script after tests (can be async)
|
|
81
|
+
qunitx test/**/*.js --after=scripts/stop-server.js
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Writing Tests
|
|
85
|
+
|
|
86
|
+
qunitx-cli runs [QUnitX](https://github.com/izelnakri/qunitx) tests — a superset of QUnit with async
|
|
87
|
+
hooks, concurrency control, and test metadata.
|
|
88
|
+
|
|
89
|
+
Migrating from QUnit? Change a single import:
|
|
24
90
|
|
|
25
91
|
```js
|
|
92
|
+
// before
|
|
26
93
|
import { module, test } from 'qunit';
|
|
27
|
-
|
|
28
|
-
// to:
|
|
94
|
+
// after
|
|
29
95
|
import { module, test } from 'qunitx';
|
|
30
96
|
```
|
|
31
97
|
|
|
32
|
-
Example:
|
|
98
|
+
Example test file — ES modules, npm imports, and nested modules all work out of the box:
|
|
33
99
|
|
|
34
100
|
```js
|
|
35
|
-
//
|
|
101
|
+
// some-test.js (TypeScript is also supported)
|
|
36
102
|
import { module, test } from 'qunitx';
|
|
37
103
|
import $ from 'jquery';
|
|
38
104
|
|
|
39
|
-
module('Basic sanity check',
|
|
40
|
-
test('it works',
|
|
105
|
+
module('Basic sanity check', (hooks) => {
|
|
106
|
+
test('it works', (assert) => {
|
|
41
107
|
assert.equal(true, true);
|
|
42
108
|
});
|
|
43
109
|
|
|
44
|
-
module('More advanced cases',
|
|
45
|
-
test('deepEqual works',
|
|
110
|
+
module('More advanced cases', (hooks) => {
|
|
111
|
+
test('deepEqual works', (assert) => {
|
|
46
112
|
assert.deepEqual({ username: 'izelnakri' }, { username: 'izelnakri' });
|
|
47
113
|
});
|
|
48
|
-
|
|
114
|
+
|
|
115
|
+
test('can import ES & npm modules', (assert) => {
|
|
49
116
|
assert.ok(Object.keys($));
|
|
50
117
|
});
|
|
51
118
|
});
|
|
52
119
|
});
|
|
53
120
|
```
|
|
54
121
|
|
|
55
|
-
|
|
56
|
-
# you can run the test in node with ES modules package.json{ "type": "module" }
|
|
57
|
-
$ node --test some-test.js
|
|
122
|
+
Run it:
|
|
58
123
|
|
|
59
|
-
|
|
124
|
+
```sh
|
|
125
|
+
# Headless Chrome (recommended for CI)
|
|
126
|
+
qunitx some-test.js
|
|
60
127
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
# with browser output enabled:
|
|
64
|
-
|
|
65
|
-
$ qunitx some-test.js --debug
|
|
66
|
-
|
|
67
|
-
# TypeScript also works, make sure on node.js mode, tsconfig.json exists with compilerOptions.module & compilerOptions.moduleResolution set to "NodeNext":
|
|
68
|
-
|
|
69
|
-
$ node --loader=ts-node/esm/transpile-only --test some-test.ts
|
|
70
|
-
|
|
71
|
-
$ qunitx some-test.ts --debug
|
|
128
|
+
# With browser console output
|
|
129
|
+
qunitx some-test.js --debug
|
|
72
130
|
|
|
131
|
+
# TypeScript — no config needed
|
|
132
|
+
qunitx some-test.ts
|
|
73
133
|
```
|
|
74
134
|
|
|
75
|
-
|
|
135
|
+
## CLI Reference
|
|
76
136
|
|
|
77
|
-
Since QUnitX proxies to default node.js test runner in when executed with node, you can use any code coverage tool you like. When running the tests in `qunit`(the browser mode) code coverage support is limited.
|
|
78
137
|
```
|
|
79
|
-
|
|
138
|
+
Usage: qunitx [files/folders...] [options]
|
|
139
|
+
|
|
140
|
+
Options:
|
|
141
|
+
--watch Re-run tests on file changes
|
|
142
|
+
--failFast Stop after the first failure
|
|
143
|
+
--debug Print the server URL; pipe browser console to stdout
|
|
144
|
+
--timeout=<ms> Max ms to wait for the suite to finish [default: 20000]
|
|
145
|
+
--output=<dir> Directory for compiled test assets [default: ./tmp]
|
|
146
|
+
--before=<file> Script to run (and optionally await) before tests start
|
|
147
|
+
--after=<file> Script to run (and optionally await) after tests finish
|
|
148
|
+
--port=<n> HTTP server port (auto-selects a free port if taken)
|
|
80
149
|
```
|
|
81
150
|
|
|
82
|
-
|
|
151
|
+
## Development
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
npm install
|
|
155
|
+
make check # lint + test (run before every commit)
|
|
156
|
+
make test # run tests only
|
|
157
|
+
make demo # regenerate demo output
|
|
158
|
+
make release LEVEL=patch # bump version, update changelog, tag, push
|
|
159
|
+
```
|
|
83
160
|
|
|
84
|
-
|
|
85
|
-
create a JS bundles for testing in the browser, this could be instrumented with `puppeteer-to-istanbul` however
|
|
86
|
-
instrumentation includes transpiled npm imports of `qunitx` and other potential npm imports developer
|
|
87
|
-
includes in the code, this cannot be filtered since potential filtering can only occur after the `esbuild` bundling.
|
|
88
|
-
When chrome browser and puppeteer fully supports ES asset maps we can remove esbuild from the browser mode, run
|
|
89
|
-
everything in deno and make instrumentation for code coverage possible with the default v8 instrumentation.
|
|
161
|
+
## License
|
|
90
162
|
|
|
91
|
-
|
|
92
|
-
with esbuild in the future, which could allow code coverage for --browser mode.
|
|
163
|
+
MIT
|
package/cli.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
import process from 'node:process';
|
|
3
3
|
import displayHelpOutput from './lib/commands/help.js';
|
|
4
4
|
import initializeProject from './lib/commands/init.js';
|
package/cliff.toml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[changelog]
|
|
2
|
+
header = """# Changelog
|
|
3
|
+
|
|
4
|
+
All notable changes to this project will be documented in this file.
|
|
5
|
+
"""
|
|
6
|
+
body = """
|
|
7
|
+
{% if version %}\
|
|
8
|
+
## {{ version | trim_start_matches(pat="v") }} — {{ timestamp | date(format="%Y-%m-%d") }}
|
|
9
|
+
{% else %}\
|
|
10
|
+
## Unreleased
|
|
11
|
+
{% endif %}\
|
|
12
|
+
{% for commit in commits %}\
|
|
13
|
+
- {{ commit.message | split(pat="\n") | first | trim | upper_first }}
|
|
14
|
+
{% endfor %}
|
|
15
|
+
"""
|
|
16
|
+
footer = ""
|
|
17
|
+
trim = true
|
|
18
|
+
|
|
19
|
+
[git]
|
|
20
|
+
conventional_commits = false
|
|
21
|
+
filter_unconventional = false
|
|
22
|
+
tag_pattern = "v[0-9].*"
|
|
23
|
+
sort_commits = "newest"
|
package/demo/demo.gif
ADDED
|
Binary file
|
package/demo/demo.tape
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# qunitx-cli demo — generates demo/demo.gif
|
|
2
|
+
# Run via: make demo (handles Chrome discovery automatically)
|
|
3
|
+
|
|
4
|
+
Output demo/demo.gif
|
|
5
|
+
|
|
6
|
+
Set Shell bash
|
|
7
|
+
Set FontSize 15
|
|
8
|
+
Set Width 800
|
|
9
|
+
Set Height 750
|
|
10
|
+
Set Theme "Dracula"
|
|
11
|
+
Set Padding 20
|
|
12
|
+
Set Framerate 24
|
|
13
|
+
Set TypingSpeed 45ms
|
|
14
|
+
|
|
15
|
+
Env PUPPETEER_SKIP_DOWNLOAD "true"
|
|
16
|
+
Env FORCE_COLOR "1"
|
|
17
|
+
Env PS1 "$ "
|
|
18
|
+
|
|
19
|
+
# ── 1. Show the test file ─────────────────────────────────────────────────────
|
|
20
|
+
Type "# 1/5 Inspect the test file"
|
|
21
|
+
Enter
|
|
22
|
+
Sleep 400ms
|
|
23
|
+
Type "cat demo/example-test.js"
|
|
24
|
+
Enter
|
|
25
|
+
Sleep 3000ms
|
|
26
|
+
|
|
27
|
+
# ── 2. Run all tests — concurrent by default, all green ──────────────────────
|
|
28
|
+
Type "# 2/5 Run tests — concurrent by default"
|
|
29
|
+
Enter
|
|
30
|
+
Sleep 400ms
|
|
31
|
+
Type "qunitx demo/example-test.js"
|
|
32
|
+
Enter
|
|
33
|
+
Sleep 7000ms
|
|
34
|
+
|
|
35
|
+
# ── 3. --debug: pipe Chrome's console.log to your terminal ───────────────────
|
|
36
|
+
Type "# 3/5 --debug: pipe Chrome console to your terminal"
|
|
37
|
+
Enter
|
|
38
|
+
Sleep 400ms
|
|
39
|
+
Type "qunitx demo/example-test.js --debug"
|
|
40
|
+
Enter
|
|
41
|
+
Sleep 7000ms
|
|
42
|
+
|
|
43
|
+
# ── 4. --failFast: stop immediately on the first failure ─────────────────────
|
|
44
|
+
Type "# 4/5 --failFast: stop on the first failure"
|
|
45
|
+
Enter
|
|
46
|
+
Sleep 400ms
|
|
47
|
+
Type "qunitx demo/failing-test.js --failFast"
|
|
48
|
+
Enter
|
|
49
|
+
Sleep 7000ms
|
|
50
|
+
|
|
51
|
+
# ── 5. --watch: stay alive and re-run on every file save ─────────────────────
|
|
52
|
+
Type "# 5/5 --watch: re-run on every file save"
|
|
53
|
+
Enter
|
|
54
|
+
Sleep 400ms
|
|
55
|
+
Type "qunitx demo/example-test.js --watch"
|
|
56
|
+
Enter
|
|
57
|
+
Sleep 6000ms
|
|
58
|
+
Ctrl+C
|
|
59
|
+
Sleep 1200ms
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { module, test } from 'qunitx';
|
|
2
|
+
|
|
3
|
+
// Tests run in real headless Chrome — not jsdom, not Node.js.
|
|
4
|
+
|
|
5
|
+
module('Browser', () => {
|
|
6
|
+
test('has window, document & navigator', (assert) => {
|
|
7
|
+
assert.ok(typeof window !== 'undefined', 'window exists');
|
|
8
|
+
assert.ok(document.body !== null, 'document.body exists');
|
|
9
|
+
assert.ok(navigator.userAgent.includes('Chrome'), 'running in Chrome');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('can build and query a DOM tree', (assert) => {
|
|
13
|
+
const ul = document.createElement('ul');
|
|
14
|
+
['Alice', 'Bob', 'Carol'].forEach((name) => {
|
|
15
|
+
const li = document.createElement('li');
|
|
16
|
+
li.textContent = name;
|
|
17
|
+
ul.appendChild(li);
|
|
18
|
+
});
|
|
19
|
+
assert.equal(ul.querySelectorAll('li').length, 3);
|
|
20
|
+
assert.equal(ul.querySelector('li').textContent, 'Alice');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('crypto.randomUUID() works', (assert) => {
|
|
24
|
+
const id = crypto.randomUUID();
|
|
25
|
+
console.log('[debug] uuid:', id);
|
|
26
|
+
assert.ok(/^[0-9a-f-]{36}$/.test(id), 'valid UUID format');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
module('Async', () => {
|
|
31
|
+
test('resolves a promise', async (assert) => {
|
|
32
|
+
const value = await Promise.resolve('hello from Chrome');
|
|
33
|
+
assert.equal(value, 'hello from Chrome');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('rejects are caught', async (assert) => {
|
|
37
|
+
await assert.rejects(Promise.reject(new Error('boom')), /boom/);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
module('Assertions', () => {
|
|
42
|
+
test('equal & deepEqual', (assert) => {
|
|
43
|
+
assert.equal(1 + 1, 2);
|
|
44
|
+
assert.deepEqual(
|
|
45
|
+
{ user: 'alice', roles: ['admin', 'viewer'] },
|
|
46
|
+
{ user: 'alice', roles: ['admin', 'viewer'] },
|
|
47
|
+
);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('throws on bad input', (assert) => {
|
|
51
|
+
assert.throws(() => JSON.parse('{bad json}'), SyntaxError);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { module, test } from 'qunitx';
|
|
2
|
+
|
|
3
|
+
module('Cart', () => {
|
|
4
|
+
test('calculates subtotal', (assert) => {
|
|
5
|
+
const items = [{ price: 10 }, { price: 20 }, { price: 5 }];
|
|
6
|
+
const total = items.reduce((sum, item) => sum + item.price, 0);
|
|
7
|
+
assert.equal(total, 35, 'subtotal is correct');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test('applies 10% discount', (assert) => {
|
|
11
|
+
assert.equal(Math.round(100 * 0.9), 90);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('validates stock level', (assert) => {
|
|
15
|
+
const stock = 0;
|
|
16
|
+
assert.ok(stock > 0, 'expected items in stock'); // ← will fail
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('calculates tax', (assert) => {
|
|
20
|
+
assert.equal(100 * 0.2, 20); // ← never reached with --failFast
|
|
21
|
+
});
|
|
22
|
+
});
|
package/flake.lock
CHANGED
|
@@ -38,16 +38,16 @@
|
|
|
38
38
|
},
|
|
39
39
|
"nixpkgs": {
|
|
40
40
|
"locked": {
|
|
41
|
-
"lastModified":
|
|
42
|
-
"narHash": "sha256-
|
|
41
|
+
"lastModified": 1772822230,
|
|
42
|
+
"narHash": "sha256-yf3iYLGbGVlIthlQIk5/4/EQDZNNEmuqKZkQssMljuw=",
|
|
43
43
|
"owner": "NixOS",
|
|
44
44
|
"repo": "nixpkgs",
|
|
45
|
-
"rev": "
|
|
45
|
+
"rev": "71caefce12ba78d84fe618cf61644dce01cf3a96",
|
|
46
46
|
"type": "github"
|
|
47
47
|
},
|
|
48
48
|
"original": {
|
|
49
49
|
"owner": "NixOS",
|
|
50
|
-
"ref": "
|
|
50
|
+
"ref": "nixos-25.11",
|
|
51
51
|
"repo": "nixpkgs",
|
|
52
52
|
"type": "github"
|
|
53
53
|
}
|
package/flake.nix
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
description = "A flake for napalm";
|
|
3
3
|
|
|
4
|
-
inputs.nixpkgs.url = "github:NixOS/nixpkgs/
|
|
4
|
+
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11";
|
|
5
5
|
inputs.napalm.url = "github:nix-community/napalm";
|
|
6
6
|
|
|
7
7
|
# NOTE: This is optional, but is how to configure napalm's env
|
|
@@ -13,14 +13,43 @@
|
|
|
13
13
|
pkgs = nixpkgs.legacyPackages."${system}";
|
|
14
14
|
in {
|
|
15
15
|
packages."${system}".default = napalm.legacyPackages."${system}".buildPackage ./. {
|
|
16
|
-
nodejs = pkgs.
|
|
16
|
+
nodejs = pkgs.nodejs_24;
|
|
17
17
|
PUPPETEER_SKIP_DOWNLOAD=1;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
devShells."${system}".default = pkgs.mkShell {
|
|
21
|
-
nativeBuildInputs =
|
|
22
|
-
|
|
21
|
+
nativeBuildInputs = [
|
|
22
|
+
pkgs.pkg-config
|
|
23
|
+
pkgs.deno
|
|
24
|
+
pkgs.nodejs_24
|
|
25
|
+
pkgs.git-cliff
|
|
26
|
+
pkgs.vhs
|
|
27
|
+
# self.packages.default.nativeBuildInputs
|
|
28
|
+
# self.packages.default.buildInputs
|
|
23
29
|
];
|
|
30
|
+
|
|
31
|
+
doCheck = false; # Disables automatically running tests for `$ nix develop` and direnv
|
|
32
|
+
|
|
33
|
+
shellHook = ''
|
|
34
|
+
export ZDOTDIR=$(mktemp -d)
|
|
35
|
+
cat > "$ZDOTDIR/.zshrc" << 'EOF'
|
|
36
|
+
source ~/.zshrc # Source the original ~/.zshrc, required.
|
|
37
|
+
function parse_git_branch {
|
|
38
|
+
git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\ ->\ \1/'
|
|
39
|
+
}
|
|
40
|
+
function display_jobs_count_if_needed {
|
|
41
|
+
local job_count=$(jobs -s | wc -l | tr -d " ")
|
|
42
|
+
if [ $job_count -gt 0 ]; then
|
|
43
|
+
echo "%B%F{yellow}%j| ";
|
|
44
|
+
fi
|
|
45
|
+
}
|
|
46
|
+
# NOTE: Custom prompt with a snowflake: signals we are in `$ nix develop` shell
|
|
47
|
+
PROMPT="%F{blue}$(date +%H:%M:%S) $(display_jobs_count_if_needed)%B%F{green}%n %F{blue}%~%F{cyan} ❄%F{yellow}$(parse_git_branch) %f%{$reset_color%}"
|
|
48
|
+
EOF
|
|
49
|
+
if [ -z "$DIRENV_IN_ENVRC" ]; then # This makes `$ nix develop` universally working with direnv without infinite loop
|
|
50
|
+
exec ${pkgs.zsh}/bin/zsh -i
|
|
51
|
+
fi
|
|
52
|
+
'';
|
|
24
53
|
};
|
|
25
54
|
};
|
|
26
55
|
}
|
package/lib/boilerplates/test.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { module, test } from 'qunitx';
|
|
2
2
|
|
|
3
|
-
module('{{moduleName}}', function(hooks) {
|
|
3
|
+
module('{{moduleName}}', function (hooks) {
|
|
4
4
|
test('assert true works', function (assert) {
|
|
5
5
|
assert.expect(3);
|
|
6
6
|
assert.ok(true);
|
|
@@ -11,9 +11,10 @@ module('{{moduleName}}', function(hooks) {
|
|
|
11
11
|
test('async test finishes', async function (assert) {
|
|
12
12
|
assert.expect(3);
|
|
13
13
|
|
|
14
|
-
let wait = () =>
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
let wait = () =>
|
|
15
|
+
new Promise((resolve, reject) => {
|
|
16
|
+
setTimeout(() => resolve(true), 50);
|
|
17
|
+
});
|
|
17
18
|
let result = await wait();
|
|
18
19
|
|
|
19
20
|
assert.ok(true);
|
package/lib/commands/generate.js
CHANGED
|
@@ -7,12 +7,13 @@ import pathExists from '../utils/path-exists.js';
|
|
|
7
7
|
|
|
8
8
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
9
9
|
|
|
10
|
-
export default async function() {
|
|
10
|
+
export default async function () {
|
|
11
11
|
let projectRoot = await findProjectRoot();
|
|
12
12
|
let moduleName = process.argv[3]; // TODO: classify this maybe in future
|
|
13
|
-
let path =
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
let path =
|
|
14
|
+
process.argv[3].endsWith('.js') || process.argv[3].endsWith('.ts')
|
|
15
|
+
? `${projectRoot}/${process.argv[3]}`
|
|
16
|
+
: `${projectRoot}/${process.argv[3]}.js`;
|
|
16
17
|
|
|
17
18
|
if (await pathExists(path)) {
|
|
18
19
|
return console.log(`${path} already exists!`);
|
|
@@ -24,10 +25,7 @@ export default async function() {
|
|
|
24
25
|
targetFolderPaths.pop();
|
|
25
26
|
|
|
26
27
|
await fs.mkdir(targetFolderPaths.join('/'), { recursive: true });
|
|
27
|
-
await fs.writeFile(
|
|
28
|
-
path,
|
|
29
|
-
testJSContent.toString().replace('{{moduleName}}', moduleName)
|
|
30
|
-
);
|
|
28
|
+
await fs.writeFile(path, testJSContent.toString().replace('{{moduleName}}', moduleName));
|
|
31
29
|
|
|
32
30
|
console.log(kleur.green(`${path} written`));
|
|
33
31
|
}
|
package/lib/commands/help.js
CHANGED
|
@@ -7,30 +7,30 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
7
7
|
const highlight = (text) => kleur.magenta().bold(text);
|
|
8
8
|
const color = (text) => kleur.blue(text);
|
|
9
9
|
|
|
10
|
+
export default async function () {
|
|
11
|
+
const config = JSON.parse(await fs.readFile(`${__dirname}/../../package.json`));
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
const config = JSON.parse((await fs.readFile(`${__dirname}/../../package.json`)));
|
|
13
|
+
console.log(`${highlight('[qunitx v' + config.version + '] Usage:')} qunitx ${color('[targets] --$flags')}
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
${highlight("Input options:")}
|
|
15
|
+
${highlight('Input options:')}
|
|
17
16
|
- File: $ ${color('qunitx test/foo.js')}
|
|
18
17
|
- Folder: $ ${color('qunitx test/login')}
|
|
19
18
|
- Globs: $ ${color('qunitx test/**/*-test.js')}
|
|
20
19
|
- Combination: $ ${color('qunitx test/foo.js test/bar.js test/*-test.js test/logout')}
|
|
21
20
|
|
|
22
|
-
${highlight(
|
|
21
|
+
${highlight('Optional flags:')}
|
|
23
22
|
${color('--debug')} : print console output when tests run in browser
|
|
24
23
|
${color('--watch')} : run the target file or folders, watch them for continuous run and expose http server under localhost
|
|
25
24
|
${color('--timeout')} : change default timeout per test case
|
|
26
25
|
${color('--output')} : folder to distribute built qunitx html and js that a webservers can run[default: tmp]
|
|
27
26
|
${color('--failFast')} : run the target file or folders with immediate abort if a single test fails
|
|
27
|
+
${color('--port')} : HTTP server port (auto-selects a free port if the given port is taken)[default: 1234]
|
|
28
28
|
${color('--before')} : run a script before the tests(i.e start a new web server before tests)
|
|
29
29
|
${color('--after')} : run a script after the tests(i.e save test results to a file)
|
|
30
30
|
|
|
31
|
-
${highlight(
|
|
31
|
+
${highlight('Example:')} $ ${color('qunitx test/foo.ts app/e2e --debug --watch --before=scripts/start-new-webserver.js --after=scripts/write-test-results.js')}
|
|
32
32
|
|
|
33
|
-
${highlight(
|
|
33
|
+
${highlight('Commands:')}
|
|
34
34
|
${color('$ qunitx init')} # Bootstraps qunitx base html and add qunitx config to package.json if needed
|
|
35
35
|
${color('$ qunitx new $testFileName')} # Creates a qunitx test file
|
|
36
36
|
`);
|