Skip to content

Commit

Permalink
chore: Build Flaky Badge and tooltip content (#22873)
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-plummer authored Jul 26, 2022
1 parent 41a0271 commit b62c949
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 7 deletions.
14 changes: 14 additions & 0 deletions packages/app/src/specs/SpecNameDisplay.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import SpecNameDisplay from './SpecNameDisplay.vue'

describe('<SpecNameDisplay />', () => {
it('should display spec name information', () => {
cy.mount(<SpecNameDisplay specFileName="myFileName" specFileExtension=".cy.tsx" />)

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()
})
})
18 changes: 18 additions & 0 deletions packages/app/src/specs/SpecNameDisplay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<div
class="max-w-60 truncate overflow-hidden"
data-cy="spec-filename"
:title="specFileName + specFileExtension"
>
<span class="font-semibold text-gray-800">{{ specFileName }}</span><span class="text-gray-600">{{ specFileExtension }}</span>
</div>
</template>

<script lang="ts" setup>
defineProps<{
specFileName: string
specFileExtension: string
}>()
</script>
2 changes: 1 addition & 1 deletion packages/app/src/specs/SpecRunSummary.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
11 changes: 5 additions & 6 deletions packages/app/src/specs/SpecRunSummary.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
:class="highlightColor"
data-cy="spec-run-summary"
>
<div
class="max-w-60 truncate overflow-hidden"
data-cy="spec-run-filename"
>
<span class="font-semibold text-gray-800">{{ props.specFileNoExtension }}</span><span class="text-gray-600">{{ props.specFileExtension }}</span>
</div>
<SpecNameDisplay
:spec-file-name="props.specFileNoExtension"
:spec-file-extension="props.specFileExtension"
/>
<div class="flex flex-row text-gray-700 text-size-14px gap-2 items-center">
<div
v-if="statusText"
Expand Down Expand Up @@ -68,6 +66,7 @@ import { computed } from 'vue'
import type { CloudSpecRun, SpecDataAggregate } from '../../../graphql/src/gen/cloud-source-types.gen'
import ResultCounts, { ResultCountsProps } from '@packages/frontend-shared/src/components/ResultCounts.vue'
import { getTimeAgo, getDurationString } from '@packages/frontend-shared/src/utils/time'
import SpecNameDisplay from './SpecNameDisplay.vue'
const props = defineProps<{
run: CloudSpecRun
Expand Down
16 changes: 16 additions & 0 deletions packages/app/src/specs/flaky-badge/FlakyBadge.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import FlakyBadge from './FlakyBadge.vue'
import { defaultMessages } from '@cy/i18n'

const flakyBadgeTestId = 'flaky-badge'

describe('<FlakyBadge />', () => {
it('should render expected content', () => {
cy.mount(<FlakyBadge />)

cy.findByTestId(flakyBadgeTestId)
.should('have.text', defaultMessages.specPage.flaky.badgeLabel)
.and('be.visible')

cy.percySnapshot()
})
})
16 changes: 16 additions & 0 deletions packages/app/src/specs/flaky-badge/FlakyBadge.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<template>
<Badge
:label="t('specPage.flaky.badgeLabel')"
status="warning"
class="font-bold uppercase"
data-cy="flaky-badge"
/>
</template>

<script setup lang="ts">
import Badge from '@packages/frontend-shared/src/components/Badge.vue'
import { useI18n } from '@cy/i18n'
const { t } = useI18n()
</script>
155 changes: 155 additions & 0 deletions packages/app/src/specs/flaky-badge/FlakySpecSummary.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import FlakySpecSummary from './FlakySpecSummary.vue'

describe('<FlakySpecSummary />', () => {
it('low severity', () => {
cy.mount(
<FlakySpecSummary
specName="test"
specExtension=".cy.tsx"
severity="low"
totalFlakyRuns={4}
totalRuns={50}
runsSinceLastFlake={15}
dashboardUrl="#"
/>,
)

cy.percySnapshot()
})

it('medium severity', () => {
cy.mount(
<FlakySpecSummary
specName="test"
specExtension=".cy.tsx"
severity="medium"
totalFlakyRuns={14}
totalRuns={50}
runsSinceLastFlake={5}
dashboardUrl="#"
/>,
)

cy.percySnapshot()
})

it('high severity', () => {
cy.mount(
<FlakySpecSummary
specName="test"
specExtension=".cy.tsx"
severity="high"
totalFlakyRuns={24}
totalRuns={50}
runsSinceLastFlake={2}
dashboardUrl="#"
/>,
)

cy.percySnapshot()
})

it('fallback state', () => {
// Ensure component handles malformed/incomplete data without blowing up
cy.mount(
<FlakySpecSummary
specName="test"
specExtension=".cy.tsx"
severity={'unknown_value' as any}
totalFlakyRuns={null as any}
totalRuns={null as any}
runsSinceLastFlake={null as any}
dashboardUrl={null as any}
/>,
)

cy.percySnapshot()
})

describe('flaky rate percentages', () => {
it('should round up to next integer if less than 99%', () => {
cy.mount(
<FlakySpecSummary
specName="test"
specExtension=".cy.tsx"
severity="high"
totalFlakyRuns={888}
totalRuns={1000}
runsSinceLastFlake={2}
dashboardUrl="#"
/>,
)

cy.findByTestId('flaky-rate').should('have.text', '89% flaky rate')
})

it('should round down if between 99 and 100%', () => {
cy.mount(
<FlakySpecSummary
specName="test"
specExtension=".cy.tsx"
severity="high"
totalFlakyRuns={999}
totalRuns={1000}
runsSinceLastFlake={2}
dashboardUrl="#"
/>,
)

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(
<FlakySpecSummary
specName="test"
specExtension=".cy.tsx"
severity="high"
totalFlakyRuns={0}
totalRuns={1000}
runsSinceLastFlake={0}
dashboardUrl="#"
/>,
)

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(
<FlakySpecSummary
specName="test"
specExtension=".cy.tsx"
severity="high"
totalFlakyRuns={1}
totalRuns={1000}
runsSinceLastFlake={1}
dashboardUrl="#"
/>,
)

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(
<FlakySpecSummary
specName="test"
specExtension=".cy.tsx"
severity="high"
totalFlakyRuns={2}
totalRuns={1000}
runsSinceLastFlake={2}
dashboardUrl="#"
/>,
)

cy.findByTestId('flaky-runs').should('have.text', '2 flaky runs / 1000 total')
cy.findByTestId('last-flaky').should('have.text', 'Last flaky 2 runs ago')
})
})
})
95 changes: 95 additions & 0 deletions packages/app/src/specs/flaky-badge/FlakySpecSummary.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<template>
<div
class="border-t-4px min-w-200px w-full max-w-400px grid p-4 gap-4 grid-cols-1 justify-items-center"
:class="severity.accentClass"
data-cy="flaky-spec-summary"
>
<SpecNameDisplay
:spec-file-name="specName"
:spec-file-extension="specExtension"
/>
<div class="flex flex-row w-full text-size-14px justify-center items-center">
<component :is="severity.icon" />
<span
class="font-medium ml-2"
:class="severity.textClass"
>{{ severity?.label }}</span>
<span
class="ml-4"
data-cy="flaky-rate"
>{{ t('specPage.flaky.flakyRate', [flakyRate]) }}</span>
</div>

<div class="w-full grid text-gray-700 text-size-14px gap-2 grid-cols-2 justify-items-center">
<span data-cy="flaky-runs">{{ t('specPage.flaky.flakyRuns', { count: totalFlakyRuns, flakyRuns: totalFlakyRuns, totalRuns }) }}</span>
<span data-cy="last-flaky">{{ t('specPage.flaky.lastFlaky', { count: runsSinceLastFlake, runsSinceLastFlake }) }}</span>
</div>
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from '@cy/i18n'
import SpecNameDisplay from '../SpecNameDisplay.vue'
import LowRateIcon from '~icons/cy/rate-low_x16'
import MediumRateIcon from '~icons/cy/rate-medium_x16'
import HighRateIcon from '~icons/cy/rate-high_x16'
const { t } = useI18n()
const SEVERITIES = {
'default': {
accentClass: 'border-t-orange-400',
textClass: null,
label: null,
icon: null,
},
'low': {
accentClass: 'border-t-orange-400',
textClass: 'text-orange-400',
label: t('specPage.flaky.severityLow'),
icon: LowRateIcon,
},
'medium': {
accentClass: 'border-t-orange-500',
textClass: 'text-orange-500',
label: t('specPage.flaky.severityMedium'),
icon: MediumRateIcon,
},
'high': {
accentClass: 'border-t-orange-600',
textClass: 'text-orange-600',
label: t('specPage.flaky.severityHigh'),
icon: HighRateIcon,
},
}
const props = defineProps<{
specName: string
specExtension: string
severity: 'low' | 'medium' | 'high'
totalFlakyRuns: number
totalRuns: number
runsSinceLastFlake: number
dashboardUrl: string
}>()
const flakyRate = computed(() => {
if (props.totalFlakyRuns <= 0 || props.totalRuns <= 0) {
return 0
}
const rawRate = (props.totalFlakyRuns / props.totalRuns) * 100
// Only display 100 if rawRate is actually 100 (do not round to 100)
if (rawRate > 99 && rawRate < 100) {
return 99
}
return Math.ceil(rawRate)
})
const severity = computed(() => SEVERITIES[props.severity] || SEVERITIES.default)
</script>
3 changes: 3 additions & 0 deletions packages/frontend-shared/src/assets/icons/rate-high_x16.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions packages/frontend-shared/src/assets/icons/rate-low_x16.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions packages/frontend-shared/src/assets/icons/rate-medium_x16.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions packages/frontend-shared/src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

5 comments on commit b62c949

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on b62c949 Jul 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/linux-x64/develop-b62c9491b1635e735846a2073b6a2586606a2f1e/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on b62c949 Jul 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/linux-arm64/develop-b62c9491b1635e735846a2073b6a2586606a2f1e/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on b62c949 Jul 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/darwin-arm64/develop-b62c9491b1635e735846a2073b6a2586606a2f1e/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on b62c949 Jul 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/darwin-x64/develop-b62c9491b1635e735846a2073b6a2586606a2f1e/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on b62c949 Jul 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release platform-specific build at https://on.cypress.io/installing-cypress#Install-pre-release-version.

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/10.4.0/win32-x64/develop-b62c9491b1635e735846a2073b6a2586606a2f1e/cypress.tgz

Please sign in to comment.