diff --git a/packages/app/src/specs/InlineRunAllSpecs.cy.tsx b/packages/app/src/specs/InlineRunAllSpecs.cy.tsx index 4a19f94acb5e..451398532959 100644 --- a/packages/app/src/specs/InlineRunAllSpecs.cy.tsx +++ b/packages/app/src/specs/InlineRunAllSpecs.cy.tsx @@ -1,12 +1,14 @@ import InlineRunAllSpecs from './InlineRunAllSpecs.vue' -describe('', () => { +describe('', { viewportHeight: 50, viewportWidth: 150 }, () => { context('Correctly rendered for Inline Specs list', () => { beforeEach(() => { + const runAllStub = cy.stub().as('runAllStub') + cy.mount(() => { return (
- +
) }) @@ -23,6 +25,12 @@ describe('', () => { cy.findByTestId('tooltip-content').should('contain.text', 'Run 40 specs') }) }) + + it('emits expected event', () => { + cy.get('button').click() + + cy.get('@runAllStub').should('have.been.calledOnce') + }) }) it('disables button when no specs are available', () => { diff --git a/packages/app/src/specs/InlineRunAllSpecs.vue b/packages/app/src/specs/InlineRunAllSpecs.vue index 798e89cd71ee..a6c313e024f9 100644 --- a/packages/app/src/specs/InlineRunAllSpecs.vue +++ b/packages/app/src/specs/InlineRunAllSpecs.vue @@ -48,4 +48,5 @@ defineProps<{ const emits = defineEmits<{ (event: 'runAllSpecs'): void }>() + diff --git a/packages/app/src/specs/InlineSpecList.cy.tsx b/packages/app/src/specs/InlineSpecList.cy.tsx index a4abb3131c97..b87071603260 100644 --- a/packages/app/src/specs/InlineSpecList.cy.tsx +++ b/packages/app/src/specs/InlineSpecList.cy.tsx @@ -1,4 +1,4 @@ -import { Specs_InlineSpecListFragment, Specs_InlineSpecListFragmentDoc, SpecFilter_SetPreferencesDocument } from '../generated/graphql-test' +import { Specs_InlineSpecListFragment, Specs_InlineSpecListFragmentDoc, SpecFilter_SetPreferencesDocument, RunAllSpecsDocument } from '../generated/graphql-test' import InlineSpecList from './InlineSpecList.vue' import { defaultMessages } from '@cy/i18n' @@ -222,5 +222,32 @@ describe('InlineSpecList', () => { mountInlineSpecList({ experimentalRunAllSpecs: true, specFilter: 'B' }) hoverRunAllSpecs('src/components', 1) }) + + it('allows keyboard interactions to run spec groups without toggling sections', () => { + // this test is specifically to catch regressions of a bug caused by nesting controls: https://github.com/cypress-io/cypress/issues/24762 + // TODO: #24966 remove this test when the structure of controls in this area has been flattened out + mountInlineSpecList({ experimentalRunAllSpecs: true }) + + const mutationStub = cy.stub().as('mutationStub') + + cy.stubMutationResolver(RunAllSpecsDocument, () => { + mutationStub() + }) + + cy.findAllByTestId('spec-file-item').should('have.length', 4) + cy.findAllByTestId('run-all-specs-button').eq(0) + .click() + .type(' ') + + // make sure typing didn't change displayed items + cy.findAllByTestId('spec-file-item').should('have.length', 4) + cy.findAllByTestId('run-all-specs-button').eq(1) + .focus() + .type('{enter}') + + // make sure typing didn't change displayed items + cy.findAllByTestId('spec-file-item').should('have.length', 4) + cy.get('@mutationStub').should('have.been.calledThrice') + }) }) }) diff --git a/packages/app/src/specs/InlineSpecListTree.cy.tsx b/packages/app/src/specs/InlineSpecListTree.cy.tsx index cd9dca57d29c..3901a1f28948 100644 --- a/packages/app/src/specs/InlineSpecListTree.cy.tsx +++ b/packages/app/src/specs/InlineSpecListTree.cy.tsx @@ -19,11 +19,36 @@ describe('InlineSpecListTree', () => { )) - cy.findAllByTestId('spec-row-item').should('have.length', 7).first().click().type('{enter}') - cy.findAllByTestId('spec-row-item').should('have.length', 1).focused().type('{rightarrow}') - .focused().type('{downarrow}').focused().type('{enter}') - - cy.findAllByTestId('spec-row-item').should('have.length', 4) + // should have 4 actual spec links + cy.get('[data-cy=spec-row-item] a').should('have.length', 4) + // should have 3 toggle buttons to hide and show directories + cy.get('[data-cy=spec-row-item] button').should('have.length', 3) + .and('have.attr', 'aria-expanded', 'true') // all should be open at the start + + cy.findAllByTestId('spec-row-item').should('have.length', 7) + .first() + .find('button') + .focus() // avoid Cypress triggering a 'click' before typing (which causes 2 separate toggles, meaning no state change) + .type('{enter}') + + cy.findAllByTestId('spec-row-item') + .should('have.length', 1) + .first() + .find('button') + .should('have.attr', 'aria-expanded', 'false') + .type('{rightarrow}') // expand this folder + .type('{downarrow}') // move to next row + .focused() // focused element should be next row + .type('{enter}') // should close next row + + // now only one link should be shown + cy.get('[data-cy=spec-row-item] a').should('have.length', 1) + .and('contain.text', 'Spec-D.spec.tsx') + + // some specific assertions about button label text and aria state + cy.contains('button', 'src').should('have.attr', 'aria-expanded', 'true') + cy.contains('button', 'components').should('have.attr', 'aria-expanded', 'false') + cy.contains('button', 'utils').should('have.attr', 'aria-expanded', 'true') }) it('collapses and rebuilds tree on specs change', () => { @@ -35,7 +60,7 @@ describe('InlineSpecListTree', () => { )) - cy.findByTestId('directory-item').should('contain', 'src/components') + cy.contains('button [data-cy=directory-item]', 'src/components') cy.findAllByTestId('spec-file-item').should('have.length', specProp.value.length) cy.then(() => { diff --git a/packages/app/src/specs/InlineSpecListTree.vue b/packages/app/src/specs/InlineSpecListTree.vue index 96ab6f717969..8e46288d5615 100644 --- a/packages/app/src/specs/InlineSpecListTree.vue +++ b/packages/app/src/specs/InlineSpecListTree.vue @@ -18,12 +18,12 @@ relative" data-cy="spec-row-item" :data-selected-spec="isCurrentSpec(row.data)" - @click.self="submit(row.data, row.index)" + @click.self="submitOrToggle(row.data, row.index)" > - - + @@ -124,7 +124,7 @@ const toggle = (row: UseCollapsibleTreeNode>, idx: row.toggle() } -const submit = (row: UseCollapsibleTreeNode>, idx: number) => { +const submitOrToggle = (row: UseCollapsibleTreeNode>, idx: number) => { // If the user selects a new spec while in studio mode, turn studio mode off const studioStore = useStudioStore()