Skip to content
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

feat: add spec pattern modal #19801

Merged
merged 16 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 35 additions & 12 deletions packages/app/cypress/e2e/index.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,22 @@ describe('App: Index', () => {
cy.findByTestId('no-specs-message').should('be.visible')
.and('contain', defaultMessages.createSpec.noSpecsMessage)

cy.findByRole('link', { name: defaultMessages.createSpec.viewSpecPatternButton })
cy.findByRole('button', { name: defaultMessages.createSpec.viewSpecPatternButton })
.should('be.visible')
.and('not.be.disabled')
.and('have.attr', 'href', '#/settings?section=project&setting=specPattern')
.click()

cy.findByRole('dialog', {
name: defaultMessages.components.specPatternModal.title,
}).should('be.visible').within(() => {
cy.validateExternalLink({ name: 'Need help', href: 'https://on.cypress.io' })
cy.findByRole('button', { name: 'Close' }).should('be.visible').as('CloseDialogButton')
cy.get('[data-cy="file-match-indicator"]').contains('0 Matches')
cy.get('[data-cy="spec-pattern"]').contains('cypress/e2e/**/*.cy.{js,jsx,ts,tsx}')
})

cy.get('@CloseDialogButton').click()
cy.findByRole('dialog').should('not.exist')
})

context('scaffold examples', () => {
Expand Down Expand Up @@ -85,7 +97,7 @@ describe('App: Index', () => {
cy.findByRole('dialog', {
name: defaultMessages.createSpec.e2e.importFromScaffold.specsAddedHeader,
}).within(() => {
cy.validateExternalLink({ name: 'Need help?', href: 'https://on.cypress.io' })
cy.validateExternalLink({ name: 'Need help', href: 'https://on.cypress.io' })
cy.findByRole('button', { name: 'Close' }).should('be.visible').as('CloseDialogButton')
})

Expand Down Expand Up @@ -334,10 +346,22 @@ describe('App: Index', () => {
.should('be.visible')
.and('contain', defaultMessages.createSpec.noSpecsMessage)

cy.findByRole('link', { name: defaultMessages.createSpec.viewSpecPatternButton })
cy.findByRole('button', { name: defaultMessages.createSpec.viewSpecPatternButton })
.should('be.visible')
.and('not.be.disabled')
.and('have.attr', 'href', '#/settings?section=project&setting=specPattern')
.click()

cy.findByRole('dialog', {
name: defaultMessages.components.specPatternModal.title,
}).should('be.visible').within(() => {
cy.validateExternalLink({ name: 'Need help', href: 'https://on.cypress.io' })
cy.findByRole('button', { name: 'Close' }).should('be.visible').as('CloseDialogButton')
cy.get('[data-cy="file-match-indicator"]').contains('0 Matches')
cy.get('[data-cy="spec-pattern"]').contains('**/*.cy.{js,jsx,ts,tsx}')
})

cy.get('@CloseDialogButton').click()
cy.findByRole('dialog').should('not.exist')
})

context('create from story', () => {
Expand All @@ -349,7 +373,7 @@ describe('App: Index', () => {
}).as('CreateFromStoryDialog')

cy.get('@CreateFromStoryDialog').within(() => {
cy.validateExternalLink({ name: 'Need help?', href: 'https://on.cypress.io' })
cy.validateExternalLink({ name: 'Need help', href: 'https://on.cypress.io' })
})

cy.findByRole('button', { name: 'Close' }).as('DialogCloseButton')
Expand Down Expand Up @@ -418,7 +442,7 @@ describe('App: Index', () => {
cy.findByRole('dialog', {
name: defaultMessages.createSpec.successPage.header,
}).as('SuccessDialog').within(() => {
cy.validateExternalLink({ name: 'Need help?', href: 'https://on.cypress.io' })
cy.validateExternalLink({ name: 'Need help', href: 'https://on.cypress.io' })
cy.findByRole('button', { name: 'Close' }).should('be.visible')
cy.contains('src/stories/Button.stories.cy.jsx').should('be.visible')

Expand Down Expand Up @@ -492,10 +516,9 @@ describe('App: Index', () => {
cy.findByTestId('no-specs-message').should('be.visible')
.and('contain', defaultMessages.createSpec.noSpecsMessage)

cy.findByRole('link', { name: defaultMessages.createSpec.viewSpecPatternButton })
cy.findByRole('button', { name: defaultMessages.createSpec.viewSpecPatternButton })
.should('be.visible')
.and('not.be.disabled')
.and('have.attr', 'href', '#/settings?section=project&setting=specPattern')
})

context('create from component', () => {
Expand All @@ -507,7 +530,7 @@ describe('App: Index', () => {
}).as('CreateFromComponentDialog')

cy.get('@CreateFromComponentDialog').within(() => {
cy.validateExternalLink({ name: 'Need help?', href: 'https://on.cypress.io' })
cy.validateExternalLink({ name: 'Need help', href: 'https://on.cypress.io' })
})

cy.findByRole('button', { name: 'Close' }).as('DialogCloseButton')
Expand Down Expand Up @@ -577,7 +600,7 @@ describe('App: Index', () => {
cy.findByRole('dialog', {
name: defaultMessages.createSpec.successPage.header,
}).as('SuccessDialog').within(() => {
cy.validateExternalLink({ name: 'Need help?', href: 'https://on.cypress.io' })
cy.validateExternalLink({ name: 'Need help', href: 'https://on.cypress.io' })
cy.contains('src/App.cy.jsx').should('be.visible')
cy.findByRole('button', { name: 'Close' }).should('be.visible')

Expand Down Expand Up @@ -789,7 +812,7 @@ describe('App: Index', () => {
cy.findByTestId('create-spec-modal').should('be.visible').within(() => {
cy.contains('Create a new spec').should('be.visible')

cy.validateExternalLink({ name: `${defaultMessages.links.needHelp}?`, href: 'https://on.cypress.io' })
cy.validateExternalLink({ name: `${defaultMessages.links.needHelp}`, href: 'https://on.cypress.io' })
})

cy.contains('Create from component').click()
Expand Down
15 changes: 15 additions & 0 deletions packages/app/cypress/e2e/spec_list.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@ describe('App: Spec List', () => {
cy.visitApp()
})

it('opens spec pattern modal', () => {
cy.contains('button', 'View spec pattern').click()

cy.get('[data-cy="spec-pattern-modal"]').should('be.visible')
cy.get('[data-cy="spec-pattern"]').contains('cypress/component-tests/**/*')

cy.contains('button', 'Update Spec Pattern').click()
cy.get('[data-cy="choose-editor-modal"]').should('be.visible').within(() => {
cy.get('[aria-label="Close"]').click()
})

cy.contains('button', 'Dismiss').click()
cy.get('[data-cy="spec-pattern-modal"]').should('not.exist')
})

it('highlights the currently running spec', () => {
cy.contains('fails').click()

Expand Down
2 changes: 1 addition & 1 deletion packages/app/cypress/e2e/top-nav.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ describe('App Top Nav Workflows', () => {
cy.findByTestId('cypress-update-popover').findByRole('button', { name: 'Update to 10.1.0' }).click()

cy.findByRole('dialog', { name: 'Upgrade to Cypress 10.1.0' }).as('upgradeModal').within(() => {
cy.validateExternalLink({ name: 'Need help?', href: 'https://on.cypress.io' })
cy.validateExternalLink({ name: 'Need help', href: 'https://on.cypress.io' })
cy.contains('You are currently running Version 10.0.0 of Cypress').should('be.visible')
cy.contains('npm install --save-dev cypress@10.1.0').should('be.visible')
cy.findByRole('button', { name: 'Close' }).click()
Expand Down
39 changes: 39 additions & 0 deletions packages/app/src/components/SpecPatternModal.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { SpecPatternModalFragmentDoc } from '../generated/graphql-test'
import SpecPatternModal from './SpecPatternModal.vue'
import { defaultMessages } from '@cy/i18n'

describe('<SpecPatternModal />', () => {
it('should not render if closed', () => {
cy.mountFragment(SpecPatternModalFragmentDoc, {
render (gql) {
return (<SpecPatternModal gql={gql} show={false} />)
},
})

cy.get('[data-cy="spec-pattern-modal"]').should('not.exist')
})

it('should render and close', () => {
const closeSpy = cy.stub().as('closeSpy')

cy.mountFragment(SpecPatternModalFragmentDoc, {
render (gql) {
return (<SpecPatternModal gql={gql} show={true} onClose={closeSpy} />)
},
})

cy.get('[data-cy="spec-pattern-modal"]').should('be.visible')
cy.contains('h2', defaultMessages.components.specPatternModal.title)
cy.get('[data-cy="external"]').should('have.attr', 'href').and('eq', 'https://on.cypress.io')
cy.get('[data-cy="spec-pattern"]').should('be.visible')

cy.percySnapshot()

cy.get('[data-cy="open-config-file"').should('be.visible')
cy.contains('button', defaultMessages.createSpec.updateSpecPattern)

cy.contains('button', defaultMessages.components.modal.dismiss).click()

cy.get('@closeSpy').should('have.been.called')
})
})
68 changes: 68 additions & 0 deletions packages/app/src/components/SpecPatternModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<template>
<StandardModal
class="transition-all transition duration-200"
variant="bare"
:title="t('components.specPatternModal.title')"
:model-value="show"
data-cy="spec-pattern-modal"
help-link="https://on.cypress.io"
@update:model-value="emits('close')"
>
<div
class="w-full p-24px sm:min-w-640px"
>
<SpecPatterns
:gql="props.gql"
class="border-gray-100 rounded border-px"
/>
</div>
<StandardModalFooter
class="flex items-center h-72px gap-16px"
>
<OpenConfigFileInIDE>
<Button size="lg">
<template #prefix>
<i-cy-code-editor_x16 class="icon-dark-white" />
</template>
{{ t('createSpec.updateSpecPattern') }}
</Button>
</OpenConfigFileInIDE>
<Button
variant="outline"
size="lg"
@click="emits('close')"
>
{{ t('components.modal.dismiss') }}
</Button>
</StandardModalFooter>
</StandardModal>
</template>

<script lang="ts" setup>
import StandardModal from '@cy/components/StandardModal.vue'
import SpecPatterns from '../components/SpecPatterns.vue'
import { useI18n } from '@cy/i18n'
import type { SpecPatternModalFragment } from '../generated/graphql'
import { gql } from '@urql/core'
import StandardModalFooter from '@cy/components/StandardModalFooter.vue'
import Button from '../../../frontend-shared/src/components/Button.vue'
import OpenConfigFileInIDE from '../../../frontend-shared/src/gql-components/OpenConfigFileInIDE.vue'

gql`
fragment SpecPatternModal on CurrentProject {
id
...SpecPatterns
}
`

const props = defineProps<{
gql: SpecPatternModalFragment
show: boolean
}>()

const { t } = useI18n()

const emits = defineEmits<{
(eventName: 'close'): void
}>()
</script>
10 changes: 5 additions & 5 deletions packages/app/src/components/SpecPatterns.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="rounded border-gray-100 border-1px w-full">
<div class="flex p-16px justify-between items-center">
<div class="w-full border-gray-100 rounded border-1px">
<div class="flex items-center justify-between p-16px">
<FileMatchIndicator>
<i18n-t
scope="global"
Expand All @@ -10,8 +10,8 @@
</i18n-t>
</FileMatchIndicator>
<OpenConfigFileInIDE>
<span class="flex outline-transparent text-indigo-500 gap-8px items-center group">
<i-cy-document-text_x16 class="icon-light-gray-100 icon-dark-gray-500" />
<span class="flex items-center text-indigo-500 outline-transparent gap-8px group">
<i-cy-document-text_x16 class="icon-light-gray-50 icon-dark-gray-300" />
<span class="group-hocus:underline">cypress.config.js</span>
</span>
</OpenConfigFileInIDE>
Expand All @@ -21,7 +21,7 @@
<code
v-for="pattern in specPatterns"
:key="pattern"
class="flex py-8px text-gray-600 text-size-14px leading-24px block"
class="flex block text-gray-600 py-8px text-size-14px leading-24px"
data-cy="spec-pattern"
>
{{ pattern }}
Expand Down
2 changes: 0 additions & 2 deletions packages/app/src/settings/SettingsCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
:max-height="maxHeight"
lazy
:data-cy="title"
:initially-open="initiallyOpen"
>
<template #target="{ open }">
<ListRowHeader
Expand Down Expand Up @@ -49,7 +48,6 @@ defineProps<{
description: string,
icon: FunctionalComponent<SVGAttributes, {}>
maxHeight: string
initiallyOpen?: boolean
}>()

</script>
Expand Down
37 changes: 0 additions & 37 deletions packages/app/src/settings/SettingsContainer.cy.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { SettingsContainerFragmentDoc } from '../generated/graphql-test'
import { defaultMessages } from '@cy/i18n'
import SettingsContainer from './SettingsContainer.vue'
import { useRoute, useRouter } from 'vue-router'

describe('<SettingsContainer />', { viewportHeight: 800, viewportWidth: 900 }, () => {
const mountSettingsContainer = () => cy.mountFragment(SettingsContainerFragmentDoc, { render: (gql) => <SettingsContainer gql={gql} /> })
Expand Down Expand Up @@ -40,40 +39,4 @@ describe('<SettingsContainer />', { viewportHeight: 800, viewportWidth: 900 }, (

cy.findByText(defaultMessages.settingsPage.projectId.title).should('not.exist')
})

context('scrolls to setting', () => {
const sections = [
{ section: 'device',
name: 'Device Settings',
settings: ['editor', 'proxy', 'testingPreferences'],
},
{ section: 'project',
name: 'Project Settings',
settings: ['projectId', 'recordKey', 'specPattern', 'experiments', 'config'],
},
]

sections.forEach(({ section, name, settings }) => settings.forEach((setting) => {
it(`should scroll to ${setting}`, () => {
cy.mountFragment(SettingsContainerFragmentDoc, {
render: (gql) => {
const router = useRouter()
const route = useRoute()

router.push({ path: '/settings', query: { section, setting } })

route.query.section = section
route.query.setting = setting

return <SettingsContainer gql={gql} />
},
})

cy.get(`[data-cy="${name}"]`).within(() => {
cy.get('[data-cy="collapsible-header"]').should('have.attr', 'aria-expanded', 'true')
cy.contains(defaultMessages.settingsPage[setting].title, { timeout: 10000 }).should('be.visible')
})
})
}))
})
})
Loading