(/** @type {TestFile} */ test)
| 694 | }) |
| 695 | |
| 696 | const runTest = async (/** @type {TestFile} */ test) => { |
| 697 | let passed = false |
| 698 | |
| 699 | for (let i = 0; i < numRetries + 1; i++) { |
| 700 | try { |
| 701 | console.log(`Starting ${test.file} retry ${i}/${numRetries}`) |
| 702 | const time = await runTestOnce(test, i === numRetries, i > 0) |
| 703 | timings.push({ |
| 704 | file: test.file, |
| 705 | time, |
| 706 | }) |
| 707 | passed = true |
| 708 | console.log( |
| 709 | `${test.file} finished on retry ${i}/${numRetries} in ${time / 1000}s` |
| 710 | ) |
| 711 | break |
| 712 | } catch (err) { |
| 713 | if (i < numRetries) { |
| 714 | try { |
| 715 | let testDir = path.dirname(path.join(__dirname, test.file)) |
| 716 | |
| 717 | // if test is nested in a test folder traverse up a dir to ensure |
| 718 | // we clean up relevant test files |
| 719 | if (testDir.endsWith('/test') || testDir.endsWith('\\test')) { |
| 720 | testDir = path.join(testDir, '..') |
| 721 | } |
| 722 | console.log('Cleaning test files at', testDir) |
| 723 | await exec(`git clean -fdx "${testDir}"`) |
| 724 | await exec(`git checkout "${testDir}"`) |
| 725 | } catch (err) {} |
| 726 | } else { |
| 727 | console.error(`${test.file} failed due to ${err}`) |
| 728 | } |
| 729 | } |
| 730 | } |
| 731 | |
| 732 | if (!passed) { |
| 733 | hadFailures = true |
| 734 | // "failed to pass within" is a keyword parsed by next-pr-webhook |
| 735 | console.error(`${test.file} failed to pass within ${numRetries} retries`) |
| 736 | } |
| 737 | |
| 738 | // Emit test output, parsed by the commenter webhook to notify about failing tests. |
| 739 | // Also emit for all tests when NEXT_TEST_EMIT_ALL_OUTPUT is set (for manifest generation). |
| 740 | if ((!passed || process.env.NEXT_TEST_EMIT_ALL_OUTPUT) && isTestJob) { |
| 741 | try { |
| 742 | const testsOutput = await fsp.readFile( |
| 743 | `${test.file}${RESULTS_EXT}`, |
| 744 | 'utf8' |
| 745 | ) |
| 746 | const obj = JSON.parse(testsOutput) |
| 747 | |
| 748 | // Extract failed test case names from Jest JSON output |
| 749 | if (!passed && process.env.CI) { |
| 750 | const failedCases = [] |
| 751 | for (const testResult of obj.testResults || []) { |
| 752 | for (const assertion of testResult.assertionResults || []) { |
| 753 | if (assertion.status === 'failed') { |
no test coverage detected