fix: improve keyboard behavior of the inline specs list "run all" buttons (#24932)

This commit is contained in:
Mark Noonan
2022-12-05 12:08:38 -05:00
committed by GitHub
parent db41507d56
commit 2552bdda9c
5 changed files with 76 additions and 15 deletions
@@ -1,12 +1,14 @@
import InlineRunAllSpecs from './InlineRunAllSpecs.vue'
describe('<InlineRunAllSpecs/>', () => {
describe('<InlineRunAllSpecs/>', { viewportHeight: 50, viewportWidth: 150 }, () => {
context('Correctly rendered for Inline Specs list', () => {
beforeEach(() => {
const runAllStub = cy.stub().as('runAllStub')
cy.mount(() => {
return (
<div class="flex justify-center">
<InlineRunAllSpecs specNumber={40} directory='cypress/e2e' />
<InlineRunAllSpecs specNumber={40} directory='cypress/e2e' onRunAllSpecs={runAllStub}/>
</div>
)
})
@@ -23,6 +25,12 @@ describe('<InlineRunAllSpecs/>', () => {
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', () => {
@@ -48,4 +48,5 @@ defineProps<{
const emits = defineEmits<{
(event: 'runAllSpecs'): void
}>()
</script>
+28 -1
View File
@@ -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')
})
})
})
@@ -19,11 +19,36 @@ describe('InlineSpecListTree', () => {
</div>
))
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}')
// 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', 4)
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', () => {
</div>
))
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(() => {
@@ -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)"
>
<RouterLink
<component
:is="row.data.isLeaf ? RouterLink : 'button'"
:ref="el => setItemRef(el, row.index)"
:key="row.data.data?.absolute"
:tabindex="isTabbable(row, row.index) ? '0' : '-1'"
:style="{ paddingLeft: `${(row.data.depth - 2) * 10 + 16}px` }"
class="border-transparent outline-none border-1 w-full group focus-visible:bg-gray-900 before:(border-r-4 border-transparent h-28px rounded-r-4px absolute left-[-4px] w-8px) "
:class="{
@@ -31,9 +31,9 @@
'before:focus:border-r-indigo-300 before:focus-visible:border-r-transparent before:hover:border-r-indigo-300': !isCurrentSpec(row.data)
}"
:to="{ path: '/specs/runner', query: { file: row.data.data?.relative?.replace(/\\/g, '/') } }"
:aria-expanded="row.data.isLeaf ? null : row.data.expanded"
@focus="resetFocusIfNecessary(row, row.index)"
@click.capture.prevent="submit(row.data, row.index)"
@keydown.enter.space.prevent.stop="submit(row.data, row.index)"
@click.prevent="submitOrToggle(row.data, row.index)"
@keydown.left.right.prevent.stop="toggle(row.data, row.index)"
>
<SpecFileItem
@@ -63,7 +63,7 @@
/>
</template>
</DirectoryItem>
</RouterLink>
</component>
</li>
</ul>
</div>
@@ -124,7 +124,7 @@ const toggle = (row: UseCollapsibleTreeNode<SpecTreeNode<FuzzyFoundSpec>>, idx:
row.toggle()
}
const submit = (row: UseCollapsibleTreeNode<SpecTreeNode<FuzzyFoundSpec>>, idx: number) => {
const submitOrToggle = (row: UseCollapsibleTreeNode<SpecTreeNode<FuzzyFoundSpec>>, idx: number) => {
// If the user selects a new spec while in studio mode, turn studio mode off
const studioStore = useStudioStore()