You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
qtap: Improve bailout, refactor browser launch, fix Safari multi file
Major:
* qtap,server: Streamline error handling and signal handling to handle
various kinds of errors that previously went unhandled, bypassing
teardown, or caused us to get stuck waiting for nothing.
In particular, "Could not open <file>" is now propagated to a
top-level error (e.g. run throws/rejects) rather than a test-level
"bail". This means we emit "error" instead of "finish" and
"clientresult", and other tests are cancelled.
With this in place, other uncaught errors we can handle other errors
better as well, such as errors from reporters.
* qtap: Handle uncaught errors from reporters, which otherwise
cause emit() to throw. Provide a dedicated EventEmitter proxy for
each reporter, to attribute the reporter in the error message.
This also protects our EventEmitter object from a reporter tampering
with "emit" or "on". The proxy only implements "on" because there
is no use case for reporters calling "emit", and it is simpler this
way.
* tap-finished: Add "bailout" as finish signal, and fix stuckness
when calling end().
* server: Separate browser launch from TAP consumption.
Starting the tapParser right away inside the launch attempt meant
we threw an exception for browser connect timeout, we have no way
to produce a finalResult / clientresult event. This is why bailout
was separate, but this is messy to deal with in reporters and also
makes partial results hard to transfer.
Instead, handle our bailout the same way as TAP bailout: As part
of the clientresult event, not as a separate event. Upstream tap-parser
emits finalResult#bailout, we can do the same in clientresult.
For this to work we need to make tap-finished trigger on bailout,
which it didn't until now.
The benefit of this is also that there is no longer any risk of
multiple browser attempts communicating over the same TAP stream
and producing duplicate or conflicting results because we do not
attach the TAP stream until after the browser has connected.
For additional disambiguation we also mint the clientId during the
attempt, instead of sharing it across retries.
* browsers: Fix safari() bug when running multiple test files.
* reporter: Flesh out more of the default reporter,
and refine the events we emit to ease the work of reporters.
* Remove separate "bail" event to simplify reporter code.
Make this part of "finish" and "clientresult" events instead.
* Emit all "assert" events, not just the first.
Minor:
* browsers: Rename Headless Firefox => Firefox Headless.
* client: Set `window.qunit_config_reporters_html = false`.
* client: Add basic visual `<pre>` output in debug mode.
* server: Change clientId format from "client_1" to "client_S1_C1"
to make verbose logs more useful. This makes it obvious which
clients are for the same testFile, and thus ControlServer.
* qtap: De-duplicate browsers and test files.
Copy file name to clipboardExpand all lines: API.md
+51-44Lines changed: 51 additions & 44 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -155,70 +155,77 @@ async function mybrowser (url, signals) {
155
155
}
156
156
```
157
157
158
-
## QTap basic events
158
+
## QTap summary events
159
159
160
-
### Event: `'error'`
160
+
These are emitted at most once for the run overall.
161
161
162
-
*`error <Error|string>`
162
+
### Event: `'clients'`
163
163
164
-
### Event: `'finish'`
164
+
The `clients` event conveys which browsers are being started, and which tests will be run. It is emitted as soon as QTap has validated the parameters. Each client is a browser process that runs one test suite. For example, if you run 2 test suites in 3 different browsers, there will be 6 clients.
165
+
166
+
*`event.clients {Object<string,Object>}` Keyed by clientId
167
+
*`clientId {string}` An identifier unique within the current qtap process (e.g. `client_123`).
168
+
*`testFile {string}` Relative file path or URL (e.g. `test/index.html` or `http://localhost/test/`).
169
+
*`browserName {string}` Browser name, as specified in config or CLI (e.g. `firefox`).
170
+
*`displayName {string}` Browser pretty name (e.g. "Headless Firefox").
165
171
166
-
Summary event that is ideal for when you run one test suite in one browser, or if you otherwise don't need a break down of results by client.
172
+
### Event: `'error'`
173
+
174
+
*`error {Error|string}`
167
175
168
-
*`event.ok <boolean>` Aggregate status of each client's results. If any failed, this is false.
169
-
*`event.exitCode <number>` Suggested exit code, 0 for success, 1 for failed.
170
-
*`event.total <number>` Aggregated from `result` events.
171
-
*`event.passed <number>` Aggregated from `result` events.
172
-
*`event.failed <number>` Aggregated from `result` events.
173
-
*`event.skips <array>` Carried from the first client that failed, or empty.
174
-
*`event.todos <array>` Carried from the first client that failed, or empty.
175
-
*`event.failures <array>` Carried from the first client that failed, or empty.
176
-
*`event.bailout <false|string>` Carried from the first client that failed, or false.
176
+
### Event: `'finish'`
177
177
178
-
## QTap reporter events
178
+
Summary event based on the `clientresult`events. This is mutually exclusive with `error`.
179
179
180
-
A client will emit each of these events only once, except `consoleerror` which may be emitted any number of times.
180
+
*`event.ok {boolean}` Aggregate status of each client's results. If any failed or bailed, this is false.
181
+
*`event.exitCode {number}` Suggested exit code, 0 for success, 1 for failed or bailed.
182
+
*`event.total {number}` Aggregated from `clientresult` events.
183
+
*`event.passed {number}` Aggregated from `clientresult` events.
184
+
*`event.failed {number}` Aggregated from `clientresult` events.
181
185
182
-
### Event: `'client'`
186
+
##QTap client events
183
187
184
-
The `client` event is emitted when a client is created. A client is a dedicated browser instance that runs one test suite. For example, if you run 2 test suites in 3 different browsers, there will be 6 clients.
188
+
These are emitted once per client, except `clientconsole` and `clientassert` which may be emitted many times by a client during a test run.
185
189
186
-
*`event.clientId <string>` An identifier unique within the current qtap process (e.g. `client_123`).
187
-
*`event.testFile <string>` Relative file path or URL (e.g. `test/index.html` or `http://localhost/test/`).
188
-
*`event.browserName <string>` Browser name, as specified in config or CLI (e.g. `firefox`).
The `clientonline` event is emitted when a browser has successfully started and opened the test file. If a browser fails to start or connect, then the `error` event is emitted instead.
192
193
193
-
The `online` event is emitted when a browser has successfully started and opened the test file. If a browser fails to connect, a `bail` event is emitted instead.
194
+
*`event.clientId {string}`
195
+
*`event.testFile {string}`
196
+
*`event.browserName {string}`
197
+
*`event.displayName {string}`
194
198
195
-
*`event.clientId <string>`
199
+
### Event: `'clientresult'`
196
200
197
-
### Event: `'result'`
201
+
The `clientresult` event is emitted when a browser has completed a test run. This includes if it bailed mid-run, such as when a test run times out.
198
202
199
-
The `result` event is emitted when a browser has completed a test run. This is mutually exclusive with the `bail` event.
203
+
*`event.clientId {string}`
204
+
*`event.ok {boolean}`
205
+
*`event.total {number}`
206
+
*`event.passed {number}`
207
+
*`event.failed {number}`
208
+
*`event.skips {array}` Details about skipped tests (count as passed).
209
+
*`event.todos {array}` Details about todo tests (count as passed).
210
+
*`event.failures {array}` Details about failed tests.
211
+
*`event.bailout {false|string}`
200
212
201
-
*`event.clientId <string>`
202
-
*`event.ok <boolean>`
203
-
*`event.total <number>`
204
-
*`event.passed <number>`
205
-
*`event.failed <number>`
206
-
*`event.skips <array>` Details about skipped tests (count as passed).
207
-
*`event.todos <array>` Details about todo tests (count as passed).
208
-
*`event.failures <array>` Details about failed tests.
213
+
### Event: `'clientconsole'`
209
214
210
-
### Event: `'bail'`
215
+
The `clientconsole` event relays any warnings and uncaught errors from the browser console. These are for debug purposes only, and do not cause a test run to fail per-se. A complete and successful test run, may nonetheless print warnings or errors to the console.
211
216
212
-
The `bail` event is emitted when a browser was unable to start or complete a test run.
217
+
Note that test frameworks such as QUnit may catch global errors during a test
213
218
214
-
*`event.clientId <string>`
215
-
*`event.reason <string>`
219
+
It is recommended that reporters only display console errors if a test run failed (i.e. there was a failed test result, or an uncaught error).
216
220
217
-
### Event: `'consoleerror'`
221
+
*`event.clientId {string}`
222
+
*`event.message {string}`
218
223
219
-
The `consoleerror` event relays any warning or error messages from the browser console. These are for debug purposes only, and do not indicate that a test has failed. A complete and successful test run, may nonetheless print warnings or errors to the console.
224
+
### Event: `'assert'`
220
225
221
-
It is recommended that reporters only display console errors if a test run failed (i.e. there was a failed test result, or the cilent bailed).
226
+
The `assert` event describes a single test result (whether passing or failing). This can be used by reporters to indicate activity, display the name of a test in real-time, or to convey failures early.
Copy file name to clipboardExpand all lines: ARCHITECTURE.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -436,7 +436,7 @@ Safari has long resisted the temptation to offer a reasonable command-line inter
436
436
{"value":null}
437
437
```
438
438
439
-
This addresses all previous concerns, and seems to be the best as of2025. The only downside is that it requires a bit more code to setup (find available port, and perform various HTTP requests).
439
+
This addresses all previous concerns, and seems to work best as of2025. The only downside is that it requires more code to set up (find available port, and perform various HTTP requests).
0 commit comments