diff --git a/packages/app/src/specs/SpecNameDisplay.cy.tsx b/packages/app/src/specs/SpecNameDisplay.cy.tsx new file mode 100644 index 000000000000..7df965a22752 --- /dev/null +++ b/packages/app/src/specs/SpecNameDisplay.cy.tsx @@ -0,0 +1,14 @@ +import SpecNameDisplay from './SpecNameDisplay.vue' + +describe('', () => { + it('should display spec name information', () => { + cy.mount() + + cy.findByText('myFileName').should('be.visible') + cy.findByText('.cy.tsx').should('be.visible') + + cy.findByTestId('spec-filename').should('have.attr', 'title', 'myFileName.cy.tsx') + + cy.percySnapshot() + }) +}) diff --git a/packages/app/src/specs/SpecNameDisplay.vue b/packages/app/src/specs/SpecNameDisplay.vue new file mode 100644 index 000000000000..200d9f29dee5 --- /dev/null +++ b/packages/app/src/specs/SpecNameDisplay.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/app/src/specs/SpecRunSummary.cy.tsx b/packages/app/src/specs/SpecRunSummary.cy.tsx index e711be4dd4a6..a198d425d3e9 100644 --- a/packages/app/src/specs/SpecRunSummary.cy.tsx +++ b/packages/app/src/specs/SpecRunSummary.cy.tsx @@ -8,7 +8,7 @@ function validateTopBorder (color: string): void { } function validateFilename (expected: string): void { - cy.findByTestId('spec-run-filename').should('have.text', expected) + cy.findByTestId('spec-filename').should('have.text', expected) } function validateTimeAgo (expected: string): void { diff --git a/packages/app/src/specs/SpecRunSummary.vue b/packages/app/src/specs/SpecRunSummary.vue index 66186a71a843..0f1f6573560f 100644 --- a/packages/app/src/specs/SpecRunSummary.vue +++ b/packages/app/src/specs/SpecRunSummary.vue @@ -5,12 +5,10 @@ :class="highlightColor" data-cy="spec-run-summary" > -
- {{ props.specFileNoExtension }}{{ props.specFileExtension }} -
+
', () => { + it('should render expected content', () => { + cy.mount() + + cy.findByTestId(flakyBadgeTestId) + .should('have.text', defaultMessages.specPage.flaky.badgeLabel) + .and('be.visible') + + cy.percySnapshot() + }) +}) diff --git a/packages/app/src/specs/flaky-badge/FlakyBadge.vue b/packages/app/src/specs/flaky-badge/FlakyBadge.vue new file mode 100644 index 000000000000..cc8447999a66 --- /dev/null +++ b/packages/app/src/specs/flaky-badge/FlakyBadge.vue @@ -0,0 +1,16 @@ + + + diff --git a/packages/app/src/specs/flaky-badge/FlakySpecSummary.cy.tsx b/packages/app/src/specs/flaky-badge/FlakySpecSummary.cy.tsx new file mode 100644 index 000000000000..e8cc56ae77e2 --- /dev/null +++ b/packages/app/src/specs/flaky-badge/FlakySpecSummary.cy.tsx @@ -0,0 +1,155 @@ +import FlakySpecSummary from './FlakySpecSummary.vue' + +describe('', () => { + it('low severity', () => { + cy.mount( + , + ) + + cy.percySnapshot() + }) + + it('medium severity', () => { + cy.mount( + , + ) + + cy.percySnapshot() + }) + + it('high severity', () => { + cy.mount( + , + ) + + cy.percySnapshot() + }) + + it('fallback state', () => { + // Ensure component handles malformed/incomplete data without blowing up + cy.mount( + , + ) + + cy.percySnapshot() + }) + + describe('flaky rate percentages', () => { + it('should round up to next integer if less than 99%', () => { + cy.mount( + , + ) + + cy.findByTestId('flaky-rate').should('have.text', '89% flaky rate') + }) + + it('should round down if between 99 and 100%', () => { + cy.mount( + , + ) + + cy.findByTestId('flaky-rate').should('have.text', '99% flaky rate') + }) + }) + + describe('pluralization', () => { + it('should handle zero flaky runs and zero runs since last flake', () => { + cy.mount( + , + ) + + cy.findByTestId('flaky-runs').should('have.text', '0 flaky runs / 1000 total') + cy.findByTestId('last-flaky').should('have.text', 'Last flaky 0 runs ago') + }) + + it('should handle 1 flaky run and 1 run since last flake', () => { + cy.mount( + , + ) + + cy.findByTestId('flaky-runs').should('have.text', '1 flaky run / 1000 total') + cy.findByTestId('last-flaky').should('have.text', 'Last flaky 1 run ago') + }) + + it('should handle multiple flaky runs and multiple runs since last flake', () => { + cy.mount( + , + ) + + cy.findByTestId('flaky-runs').should('have.text', '2 flaky runs / 1000 total') + cy.findByTestId('last-flaky').should('have.text', 'Last flaky 2 runs ago') + }) + }) +}) diff --git a/packages/app/src/specs/flaky-badge/FlakySpecSummary.vue b/packages/app/src/specs/flaky-badge/FlakySpecSummary.vue new file mode 100644 index 000000000000..f11c020de491 --- /dev/null +++ b/packages/app/src/specs/flaky-badge/FlakySpecSummary.vue @@ -0,0 +1,95 @@ + + + diff --git a/packages/frontend-shared/src/assets/icons/rate-high_x16.svg b/packages/frontend-shared/src/assets/icons/rate-high_x16.svg new file mode 100644 index 000000000000..5475db1490ed --- /dev/null +++ b/packages/frontend-shared/src/assets/icons/rate-high_x16.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/frontend-shared/src/assets/icons/rate-low_x16.svg b/packages/frontend-shared/src/assets/icons/rate-low_x16.svg new file mode 100644 index 000000000000..a287db1e093e --- /dev/null +++ b/packages/frontend-shared/src/assets/icons/rate-low_x16.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/frontend-shared/src/assets/icons/rate-medium_x16.svg b/packages/frontend-shared/src/assets/icons/rate-medium_x16.svg new file mode 100644 index 000000000000..8ecd3a89e60d --- /dev/null +++ b/packages/frontend-shared/src/assets/icons/rate-medium_x16.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/packages/frontend-shared/src/locales/en-US.json b/packages/frontend-shared/src/locales/en-US.json index faab7392adf1..d20fa95a337c 100644 --- a/packages/frontend-shared/src/locales/en-US.json +++ b/packages/frontend-shared/src/locales/en-US.json @@ -151,6 +151,15 @@ "linkText": "average spec durations" } }, + "flaky": { + "badgeLabel": "Flaky", + "severityLow": "Low", + "severityMedium": "Medium", + "severityHigh": "High", + "flakyRate": "{0}% flaky rate", + "flakyRuns": "{flakyRuns} flaky runs / {totalRuns} total | {flakyRuns} flaky run / {totalRuns} total | {flakyRuns} flaky runs / {totalRuns} total", + "lastFlaky": "Last flaky {runsSinceLastFlake} runs ago | Last flaky {runsSinceLastFlake} run ago | Last flaky {runsSinceLastFlake} runs ago" + }, "connectProjectButton": "Connect your project", "dashboardLoginButton": "Log in to the Dashboard", "reconnectProjectButton": "Reconnect your project",