-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
fix: report results correctly when the browser crashes mid-test #27786
Merged
Merged
Changes from 31 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
ae25def
report correct number of failures if browser crashes in the middle of…
cacieprins 8d67daa
report failure correctly when browser crashes during test
cacieprins 494aa67
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins 5b46d7e
refactor crash handling
cacieprins f3a2bee
correct exit option check, clean up debug
cacieprins 2de2a38
exit on success if exit option !== false
cacieprins ddd5c86
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins 44d71f1
use default stats when reporter stats are unavailable
cacieprins 983bab3
fix error messaging
cacieprins 93f7e8a
move reporter types to an intermediate .ts file, to be combined with …
cacieprins 93e7d46
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins a117dbf
debug tab close test in ci
cacieprins c9c5ebb
move debug env from pkg to ci yml
cacieprins ef74379
set debug env in spec
cacieprins e259a69
fix pckg
cacieprins 0896f7f
adds some logging to cri-client
cacieprins b8be7fd
remove event emit logging from project-base
cacieprins 8ddeb41
revert snapshot for tab close system test
cacieprins 2bb5df4
fixes console output for no exit on success
cacieprins ec7d362
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins f6cf2cd
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins e69f9bd
changelog
cacieprins bc44078
changelog wsp
cacieprins 9dd282e
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins 47f03d4
cleanup
cacieprins c40c982
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins dd4f1f7
clean up tests
cacieprins aace680
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins 0c09b1d
refactor to more straightforward control flow
cacieprins 29b0020
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins 8da0a05
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins f7e145f
rm export for unused type
cacieprins 65cbc13
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins c688ca6
correct tab close snapshot for ci
cacieprins 7a802ec
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins a043e40
new system test for mid-test config crash
cacieprins 8ffb34c
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins 9bf8025
update snapshots
cacieprins edbad0e
Merge branch 'develop' into cacie/fix/report-results-on-crash
cacieprins File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -376,7 +376,6 @@ export class ProjectBase extends EE { | |
}, | ||
|
||
onMocha: async (event, runnable) => { | ||
debug('onMocha', event) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. was this debug too spammy? |
||
// bail if we dont have a | ||
// reporter instance | ||
if (!reporterInstance) { | ||
|
@@ -385,7 +384,12 @@ export class ProjectBase extends EE { | |
|
||
reporterInstance.emit(event, runnable) | ||
|
||
if (event === 'end') { | ||
if (event === 'test:before:run') { | ||
this.emit('test:before:run', { | ||
runnable, | ||
previousResults: reporterInstance?.results() || {}, | ||
}) | ||
} else if (event === 'end') { | ||
const [stats = {}] = await Promise.all([ | ||
(reporterInstance != null ? reporterInstance.end() : undefined), | ||
this.server.end(), | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
interface ReporterTestAttempt { | ||
state: 'skipped' | 'failed' | 'passed' | ||
error: any | ||
timings: any | ||
failedFromHookId: any | ||
wallClockStartedAt: Date | ||
wallClockDuration: number | ||
videoTimestamp: any | ||
} | ||
interface ReporterTest { | ||
testId: string | ||
title: string[] | ||
state: 'skipped' | 'passed' | 'failed' | ||
body: string | ||
displayError: any | ||
attempts: ReporterTestAttempt[] | ||
} | ||
|
||
export interface BaseReporterResults { | ||
error?: string | ||
stats: { | ||
failures: number | ||
tests: number | ||
passes: number | ||
pending: number | ||
suites: number | ||
skipped: number | ||
wallClockDuration: number | ||
wallClockStartedAt: string | ||
wallClockEndedAt: string | ||
} | ||
} | ||
|
||
export interface ReporterResults extends BaseReporterResults { | ||
reporter: string | ||
reporterStats: { | ||
suites: number | ||
tests: number | ||
passes: number | ||
pending: number | ||
failures: number | ||
start: string | ||
end: string | ||
duration: number | ||
} | ||
hooks: any[] | ||
tests: ReporterTest[] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import type { ProjectBase } from '../project-base' | ||
import type { BaseReporterResults, ReporterResults } from '../types/reporter' | ||
import * as errors from '../errors' | ||
import Debug from 'debug' | ||
import pDefer, { DeferredPromise } from 'p-defer' | ||
|
||
const debug = Debug('cypress:util:crash_handling') | ||
|
||
const patchRunResultsAfterCrash = (error: Error, reporterResults: ReporterResults, mostRecentRunnable: any): ReporterResults => { | ||
const endTime: number = reporterResults?.stats?.wallClockEndedAt ? Date.parse(reporterResults?.stats?.wallClockEndedAt) : new Date().getTime() | ||
const wallClockDuration = reporterResults?.stats?.wallClockStartedAt ? | ||
endTime - Date.parse(reporterResults.stats.wallClockStartedAt) : 0 | ||
const endTimeStamp = new Date(endTime).toJSON() | ||
|
||
// in crash situations, the most recent report will not have the triggering test | ||
// so the results are manually patched, which produces the expected exit=1 and | ||
// terminal output indicating the failed test | ||
return { | ||
...reporterResults, | ||
stats: { | ||
...reporterResults?.stats, | ||
wallClockEndedAt: endTimeStamp, | ||
wallClockDuration, | ||
failures: (reporterResults?.stats?.failures ?? 0) + 1, | ||
skipped: (reporterResults?.stats?.skipped ?? 1) - 1, | ||
}, | ||
reporterStats: { | ||
...reporterResults?.reporterStats, | ||
tests: (reporterResults?.reporterStats?.tests ?? 0) + 1, // crashed test does not increment this value | ||
end: reporterResults?.reporterStats?.end || endTimeStamp, | ||
duration: wallClockDuration, | ||
failures: (reporterResults?.reporterStats?.failures ?? 0) + 1, | ||
}, | ||
tests: (reporterResults?.tests || []).map((test) => { | ||
if (test.testId === mostRecentRunnable.id) { | ||
return { | ||
...test, | ||
state: 'failed', | ||
attempts: [ | ||
...test.attempts.slice(0, -1), | ||
{ | ||
...test.attempts[test.attempts.length - 1], | ||
state: 'failed', | ||
}, | ||
], | ||
} | ||
} | ||
|
||
return test | ||
}), | ||
error: errors.stripAnsi(error.message), | ||
} | ||
} | ||
|
||
const defaultStats = (error: Error): BaseReporterResults => { | ||
return { | ||
error: errors.stripAnsi(error.message), | ||
stats: { | ||
failures: 1, | ||
tests: 0, | ||
passes: 0, | ||
pending: 0, | ||
suites: 0, | ||
skipped: 0, | ||
wallClockDuration: 0, | ||
wallClockStartedAt: new Date().toJSON(), | ||
wallClockEndedAt: new Date().toJSON(), | ||
}, | ||
} | ||
} | ||
|
||
export class EarlyExitTerminator { | ||
private terminator: DeferredPromise<BaseReporterResults> | ||
|
||
private pendingRunnable: any | ||
private intermediateStats: ReporterResults | undefined | ||
|
||
constructor () { | ||
this.terminator = pDefer<BaseReporterResults>() | ||
} | ||
|
||
waitForEarlyExit (project: ProjectBase, exit?: boolean) { | ||
debug('waiting for early exit') | ||
|
||
project.on('test:before:run', ({ | ||
runnable, | ||
previousResults, | ||
}) => { | ||
debug('preparing to run test, previous stats reported as %O', previousResults) | ||
|
||
this.intermediateStats = previousResults | ||
this.pendingRunnable = runnable | ||
}) | ||
|
||
return this.terminator.promise | ||
} | ||
|
||
exitEarly (error) { | ||
if (error.isFatalApiErr) { | ||
this.terminator.reject(error) | ||
|
||
return | ||
} | ||
|
||
// eslint-disable-next-line no-console | ||
console.log('') | ||
errors.log(error) | ||
|
||
const runResults: BaseReporterResults = (this.intermediateStats && this.pendingRunnable) ? | ||
patchRunResultsAfterCrash(error, this.intermediateStats, this.pendingRunnable) : | ||
defaultStats(error) | ||
|
||
this.terminator.resolve(runResults) | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.