Skip to content

Commit

Permalink
feat: IATR-M0 Spec and Test Component (#24877)
Browse files Browse the repository at this point in the history
Closes #24443 and #24444
  • Loading branch information
amehta265 authored Dec 2, 2022
1 parent 7141e40 commit 1c80741
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 5 deletions.
38 changes: 38 additions & 0 deletions packages/app/src/debug/DebugFailedTest.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import DebugFailedTest from './DebugFailedTest.vue'

describe('<DebugFailedTest/>', () => {
it('mounts correctly', () => {
const testResult = {
id: '676df87878',
titleParts: ['Login', 'Should redirect unauthenticated user to signin page'],
}

cy.mount(() => (
<DebugFailedTest failedTestResult={testResult} />
))

cy.findByTestId('test-row').children().should('have.length', 2)

testResult.titleParts.forEach((title, index) => {
cy.findByTestId(`titleParts-${index}`).should('have.text', `${title}`)
})
})

it('contains multiple titleParts segments', () => {
const multipleTitleParts = {
id: '676df87878',
titleParts: ['Login', 'Describe', 'it', 'context', 'Should redirect unauthenticated user to signin page'],
}

cy.mount(() => (
<DebugFailedTest failedTestResult={multipleTitleParts} />
))

cy.findByTestId('test-row').children().should('have.length', 5).should('be.visible')
multipleTitleParts.titleParts.forEach((title, index) => {
cy.findByTestId(`titleParts-${index}`).should('have.text', `${title}`)
})

cy.percySnapshot()
})
})
33 changes: 33 additions & 0 deletions packages/app/src/debug/DebugFailedTest.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<div
data-cy="test-row"
class="flex flex-row items-center gap-x-2.5 non-italic text-base text-gray-700 font-normal"
>
<div
v-for="(titlePart, index) in props.failedTestResult.titleParts"
:key="`${titlePart}-${index}`"
class="flex flex-row items-center gap-x-2.5"
:data-cy="`titleParts-${index}`"
>
<IconChevronRightSmall
v-if="index !== 0"
data-cy="right-chevron"
size="8"
stroke-color="gray-200"
fill-color="gray-200"
/>
<span>
{{ titlePart }}
</span>
</div>
</div>
</template>
<script lang="ts" setup>
import { IconChevronRightSmall } from '@cypress-design/vue-icon'
import type { TestResults } from './DebugSpec.vue'
const props = defineProps<{
failedTestResult: TestResults
}>()
</script>
102 changes: 102 additions & 0 deletions packages/app/src/debug/DebugSpec.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import type { Spec, TestResults } from './DebugSpec.vue'
import DebugSpec from './DebugSpec.vue'
import { defaultMessages } from '@cy/i18n'

describe('<DebugSpec/> with multiple test results', () => {
const spec: Spec = {
id: '8879798756s88d',
path: 'cypress/tests',
fileName: 'auth',
fileExtension: '.spec.ts',
}

const testResults: TestResults[] = [
{
id: '676df87878',
titleParts: ['Login', 'Should redirect unauthenticated user to signin page'],
},
{
id: '78hjkdf987d9f',
titleParts: ['Login', 'redirects to stored path after login'],
},
]

it('mounts correctly', () => {
cy.mount(() => (
<DebugSpec spec={spec} testResults={testResults} />
))

cy.findByTestId('debug-spec-item').children().should('have.length', 3)
cy.findByTestId('spec-contents').children().should('have.length', 2)
cy.findByTestId('spec-path').should('have.text', 'cypress/tests/auth.spec.ts')
cy.contains('auth').should('be.visible')
cy.findByTestId('run-failures').should('not.be.disabled')
.contains(defaultMessages.debugPage.runFailures)

cy.findAllByTestId('test-group').should('have.length', 2)

cy.percySnapshot()
})

it('renders correctly with disabled run-failures button', () => {
cy.mount(() => (
<DebugSpec spec={spec} testResults={testResults} isDisabled={true} />
))

cy.findByTestId('run-failures').should('have.attr', 'aria-disabled', 'disabled')
.should('not.have.attr', 'href')

cy.percySnapshot()
})
})

describe('<DebugSpec/> responsive UI', () => {
const testResults: TestResults[] = [
{
id: 'ab78dkb300js',
titleParts: ['Alert Bar with state', 'Alert Bar shows passing message'],
},
{
id: 'ab78dkb590js',
titleParts: ['Alert Bar with state', 'Alert Bar shows failure message'],
},
]

it('renders complete UI on smaller viewports', { viewportHeight: 300, viewportWidth: 450 }, () => {
const spec: Spec = {
id: '5479adf90s7f',
path: 'cypress/tests',
fileName: 'AlertBar',
fileExtension: '.spec.ts',
}

cy.mount(() => (
<DebugSpec spec={spec} testResults={testResults} />
))

cy.findByTestId('spec-contents').children().should('have.length', 2)
cy.findByTestId('spec-path').should('have.text', 'cypress/tests/AlertBar.spec.ts')
cy.contains('AlertBar').should('be.visible')
cy.findByTestId('run-failures').should('be.visible')

cy.percySnapshot()
})

it('shows complete spec component header with long relative filePath', () => {
const spec: Spec = {
id: '547a0dG90s7f',
path: 'src/shared/frontend/cow/packages/foo/cypress/tests/e2e/components',
fileName: 'AlertBar',
fileExtension: '.spec.ts',
}

cy.mount(() => (
<DebugSpec spec={spec} testResults={testResults} />
))

cy.findByTestId('spec-path').should('have.css', 'text-overflow', 'ellipsis')
cy.findByTestId('run-failures').should('be.visible')

cy.percySnapshot()
})
})
111 changes: 111 additions & 0 deletions packages/app/src/debug/DebugSpec.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<template>
<div
data-cy="debug-spec-col"
class="grid flex flex-col px-24px gap-24px self-stretch"
>
<div
data-cy="debug-spec-item"
class="w-full overflow-hidden flex flex-col items-start box-border border-t-1px border-x-1px rounded"
>
<div
data-cy="debug-spec-header"
class="w-full flex flex-row items-center py-12px bg-gray-50 border-b-1px border-b-gray-100 rounded-t"
>
<div
data-cy="spec-contents"
class="w-full flex flex-row px-16px items-center"
>
<div
data-cy="spec-path"
class="flex-grow non-italic text-base truncate"
>
<span
class="font-normal text-gray-600"
>
{{ specData.path }}
</span>
<span
class="inline-flex items-center"
>
<SpecNameDisplay
:spec-file-name="specData.fileName"
:spec-file-extension="specData.fileExtension"
/>
</span>
</div>
<div
class="ml-10px"
>
<Button
data-cy="run-failures"
variant="white"
class="inline-flex gap-x-10px whitespace-nowrap justify-center items-center isolate"
:disabled="isDisabled"
:to="{ path: '/specs/runner', query: { file: (specData.path).replace(/\\/g, '/') } }"
>
<template #prefix>
<IconActionRefresh
data-cy="icon-refresh"
stroke-color="indigo-500"
/>
</template>
<!-- Wrapping this with a default template to avoid an unneeded space -->
<template #default>
{{ t('debugPage.runFailures') }}
</template>
</Button>
</div>
</div>
</div>
<div
v-for="test in specData.failedTests"
:key="`test-${test.id}`"
data-cy="test-group"
class="w-full flex flex-col flex-start h-12 items-start justify-center pl-16px border-b-gray-100 border-b-1px"
>
<DebugFailedTest
:failed-test-result="test"
:data-cy="`test-${test.id}`"
/>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
export interface Spec {
id: string
path: string
fileName: string
fileExtension: string
}
export interface TestResults {
id: string
titleParts: string[]
}
import { computed } from 'vue'
import { IconActionRefresh } from '@cypress-design/vue-icon'
import DebugFailedTest from './DebugFailedTest.vue'
import Button from '@packages/frontend-shared/src/components/Button.vue'
import SpecNameDisplay from '../specs/SpecNameDisplay.vue'
import { useI18n } from '@cy/i18n'
const { t } = useI18n()
const props = defineProps<{
spec: Spec
testResults: TestResults[]
isDisabled?: boolean
}>()
const specData = computed(() => {
return {
path: `${props.spec.path}/`,
fileName: props.spec.fileName,
fileExtension: props.spec.fileExtension,
failedTests: props.testResults,
}
})
</script>
12 changes: 12 additions & 0 deletions packages/frontend-shared/src/components/Button.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ describe('<Button />', { viewportWidth: 300, viewportHeight: 400 }, () => {
<Button variant="text" disabled>Text with text disabled</Button>
<Button variant="secondary">Secondary with text</Button>
<Button variant="secondary" disabled>Secondary with text disabled</Button>
<Button variant="white" size="md">White with text</Button>
<Button variant="white" size="md" disabled>White with text disabled</Button>
</div>
))

Expand Down Expand Up @@ -96,4 +98,14 @@ describe('<Button />', { viewportWidth: 300, viewportHeight: 400 }, () => {

cy.get('[data-cy="coffee-icon"]').should('be.visible')
})

it('renders button as disabled with a disabled and to prop', () => {
cy.mount(() => (
<Button disabled to="cypress.io"> test </Button>
))

cy.contains('a', 'test').should('not.have.attr', 'href')
cy.contains('a', 'test').should('have.attr', 'aria-disabled', 'disabled')
cy.contains('a', 'test').should('have.attr', 'role', 'link')
})
})
15 changes: 10 additions & 5 deletions packages/frontend-shared/src/components/Button.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,11 @@
<template #default>
<slot />
</template>
<template #suffix>
<slot
v-if="suffixIcon || $slots.suffix"
name="suffix"
>
<template
v-if="suffixIcon || $slots.suffix"
#suffix
>
<slot name="suffix">
<component
:is="suffixIcon"
:class="suffixIconClass"
Expand All @@ -88,6 +88,7 @@ const VariantClassesTable = {
linkBold: 'border-transparent text-indigo-500 font-medium',
text: 'border-0',
secondary: 'bg-jade-500 text-white hocus-secondary',
white: 'bg-white text-indigo-500 font-medium hocus-default',
} as const
const SizeClassesTable = {
Expand Down Expand Up @@ -144,6 +145,10 @@ const linkVersion = computed(() => {
return props.internalLink ? BaseLink : ExternalLink
}
if (props.disabled) {
return BaseLink
}
return RouterLink
})
Expand Down
3 changes: 3 additions & 0 deletions packages/frontend-shared/src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -854,5 +854,8 @@
"alpha": "Alpha",
"beta": "Beta",
"new": "New"
},
"debugPage": {
"runFailures": "Run Failures"
}
}

0 comments on commit 1c80741

Please sign in to comment.