-
Notifications
You must be signed in to change notification settings - Fork 783
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(html-reporter): add "Rerun all failed tests" #1626
Conversation
Closes qunitjs#1474. Appends a "Rerun all failed tests" link to the progress report in the `qunit-testresult-display` header, that uses `setUrl({ ... })` to generate a URL that includes the IDs of all failed tests as a list of `testId` query parameters. To achieve this, the `stats.failedTests` property was changed from a `number` to a `string[]` array that keeps track of all failed test IDs. Considered alternatives: - Keep `stats.failedTests` a `number` and add an extra `failedTestIds: string[]` array. I disliked this because of the double book-keeping, which could lead to `stats.failedTests` and `failedTestIds` getting out of sync. - Lazily query the IDs of all failed tests from the DOM on demand. Based on the snippet I included in my original issue qunitjs#1474, I could have also generated the "Rerun all failed tests" link on demand, like so: ```js const failedTestIds = [ ...document.querySelectorAll('.fail[id^="qunit-test-output"]') ].map(n => n.id.slice('qunit-test-output-'.length)); const href = setUrl({ testId: failedTestIds }); ``` However, that seemed quite hacky and would require more complex code to intercept interactions with the `<a>` tag to set the `href` attribute in time, where the current `stats.failedTests` solution is very straightforward. Furthermore the registered hooks for `QUnit.done(...)` and `QUnit.testStart(...)` were refactored to use common utility functions: - `getProgressHtml(runtime: number, stats: Stats, total: number): string` - When called from `Qunit.testStart(...)`, the count of completed tests is lower than `total` and the return value looks like this: `209 / 978 tests completed in 398101 milliseconds, with 2 failed, 6 skipped, and 0 todo.` - When called from `Qunit.done(...)`, the count of completed tests is equal to `total` and the return value looks like this: `978 tests completed in 703624 milliseconds, with 2 failed, 6 skipped, and 0 todo.` - `getAssertionsSummaryHtml(total: number, passed: number, failed: number): string` Called from `Qunit.done(...)` to print the summary of assertions. Example: ```html <span class="passed">116</span> assertions of <span class="total">116</span> passed, <span class="failed">0</span> failed. ``` - `getRerunFailedHtml(failedTests: string[]): string` Called from both `Qunit.done(...)` and `Qunit.testStart(...)` to generate a link to rerun all (so far) failed tests. Example: ```html <a href="http://localhost:1337/tests?testId=883cd3ae&testId=b2f8d939"> Rerun all 2 failed tests </a> ``` Returns an empty string (`""`), if `failedTests` is empty (`[]`). I also refactored how `<br>` tags are inserted between these fragments. Instead of including the `<br>` in the return value of e.g. `getProgressHtml(...)` and in the fragment arrays, they are inserted by `.filter(Boolean).join("<br">)`, when the fargments are concatenated into the final HTML string, which has the added advantage of conveniently filtering out optional fragments first. I would have also liked to change the inner workings to construct real DOM directly instead of using `element.innerHTML = "..."`, but I did not want to change more than necessary, as the above already are quite significant refactors.
I wasn't really sure where to add tests for this. I think |
@buschtoens Thanks, this looks great. I agree with your decision tree and overall approach. I think a test would be useful here, but perhaps better as a standalone HTML file to make it less subject to change. The test suite would e.g. have 2 fake failing tests with a known test ID, and a third test asserting that the link is generated as expected. It then needs the "usual" trickery with In the hopefully not-too-distant future this'll be easier to test when the HTML Reporter is more separated (#1118), at which point you'd instantiate it within a test, give it a new element to add its UI to, feed it some fixed events, and see what it does to the element (without affecting the "main" runner etc.). |
Merged in f5333b2. |
Closes #1474.
New Feature: "Rerun all failed tests" Link
Appends a "Rerun all failed tests" link to the progress report in the
qunit-testresult-display
header, that usessetUrl({ ... })
to generate a URL that includes the IDs of all failed tests as a list oftestId
query parameters.Screenshots
During test execution![Screenshot 2021-09-05 at 17 43 40](https://user-images.githubusercontent.com/156867/132134672-cef2c727-53ed-416f-84d2-78a9633ecf46.png)
After completionHow?
To achieve this, the
stats.failedTests
property was changed from anumber
to astring[]
array that keeps track of all failed test IDs.Considered Alternatives
stats.failedTests
anumber
and add an extrafailedTestIds: string[]
array.I disliked this because of the double book-keeping, which could lead to
stats.failedTests
andfailedTestIds
getting out of sync.Based on the snippet I included in my original issue [Feature] Rerun all failed tests #1474, I could have also generated the "Rerun all failed tests" link on demand, like so:
<a>
tag to set thehref
attribute in time, where the currentstats.failedTests
solution is very straightforward.Further Refactors
Common Utility Functions
Furthermore the registered hooks for
QUnit.done(...)
andQUnit.testStart(...)
were refactored to use common utility functions:getProgressHtml(runtime: number, stats: Stats, total: number): string
Qunit.testStart(...)
, the count of completed tests is lower thantotal
and the return value looks like this:Qunit.done(...)
, the count of completed tests is equal tototal
and the return value looks like this:getAssertionsSummaryHtml(total: number, passed: number, failed: number): string
Called from
Qunit.done(...)
to print the summary of assertions. Example:getRerunFailedHtml(failedTests: string[]): string
Called from both
Qunit.done(...)
andQunit.testStart(...)
to generate a link to rerun all (so far) failed tests. Example:Returns an empty string (
""
), iffailedTests
is empty ([]
).<br>
InsertionI also refactored how
<br>
tags are inserted between these fragments. Instead of including the<br>
in the return value of e.g.getProgressHtml(...)
and in the fragment arrays, they are inserted by.filter(Boolean).join("<br">)
, when the fargments are concatenated into the final HTML string, which has the added advantage of conveniently filtering out optional fragments first.Recommended Refactors
Avoid
innerHTML
I would have also liked to change the inner workings to construct real DOM directly instead of using
element.innerHTML = "..."
, but I did not want to change more than necessary, as the above already are quite significant refactors.