@revoloo/cypress6
Version:
Cypress.io end to end testing tool
260 lines (224 loc) • 8.55 kB
JSX
import React, { useState } from 'react'
import { render } from 'react-dom'
import { Select, SelectItem } from '../../src'
const _ = Cypress._
describe('<Select />', () => {
beforeEach(() => {
cy.visit('dist/index.html')
cy.viewport(400, 600)
})
it('optionally provide a name', () => {
cy.render(render, (
<>
<Select value="v2" name="myName">
<SelectItem value="v1" data-test="v1" />
<SelectItem value="v2" data-test="v2" />
<SelectItem value="v3" data-test="v3" />
</Select>
<br/>
<Select value="v1">
<SelectItem value="v1" data-test="v1" />
<SelectItem value="v2" data-test="v2" />
<SelectItem value="v3" data-test="v3" />
</Select>
</>
))
cy.get('input[name="myName"]').then((el) => expect(el.length).to.eql(3))
cy.get('input').then((els) => {
expect(els.length).to.eql(6)
expect(_.filter(els, (el) => el.name !== 'myName').length).to.eql(3)
})
})
it('can render multiple groups on the same page', () => {
cy.render(render, (
<>
<Select value="v2" name="myName">
<SelectItem value="v1" data-test="v1" />
<SelectItem value="v2" data-test="v2" />
<SelectItem value="v3" data-test="v3" />
</Select>
<br/>
<Select value="v1">
<SelectItem value="v1" data-test="v1" />
<SelectItem value="v2" data-test="v2" />
<SelectItem value="v3" data-test="v3" />
</Select>
<br/>
<Select value="v3">
<SelectItem value="v1" data-test="v1" />
<SelectItem value="v2" data-test="v2" />
<SelectItem value="v3" data-test="v3" />
</Select>
</>
))
cy.get('input[name="myName"]').then((el) => expect(el.length).to.eql(3))
cy.get('input').then((els) => {
expect(els.length).to.eql(9)
expect(_.filter(els, (el) => el.name !== 'myName').length).to.eql(6)
expect(els[1].checked).to.be.true
expect(els[3].checked).to.be.true
expect(els[8].checked).to.be.true
})
})
it('only a single SelectItem is checked at a time', () => {
const onChange = cy.stub()
cy.render(render, (
<Select value="v2" onChange={onChange}>
<SelectItem value="v1" />
<SelectItem value="v2" />
<SelectItem value="v3" />
</Select>
))
cy.get('[data-value="v1"]').click()
.then(() => expect(onChange).to.be.calledWith('v1'))
cy.get('[data-value="v3"]').click()
.then(() => expect(onChange).to.be.calledWith('v3'))
})
it('other components are permitted as children for a <Select />', () => {
cy.render(render, (
<div width="100%">
<Select value="oranges">
<h3>Fruits</h3>
<label><SelectItem value="apples" data-test="apples" /> apples</label>
<label><SelectItem value="oranges" data-test="oranges" /> oranges</label>
<h3>Vegetables</h3>
<label><SelectItem value="apples" data-test="apples" /> carrot</label>
<label><SelectItem value="oranges" data-test="oranges" /> potato</label>
</Select>
</div>
))
cy.get('h3').first().contains('Fruits')
cy.get('h3').last().contains('Vegetables')
})
describe('single value selection', () => {
it('focus-able', () => {
cy.render(render, (
<Select value="v2">
<SelectItem value="v1" />
<SelectItem value="v2" />
<SelectItem value="v3" />
</Select>
))
cy.get('[value="v1"]').as('focused').first().focus()
cy.window().then((win) => {
cy.get('@focused').then((el) => {
expect(win.document.activeElement).to.eql(el[0])
})
})
})
// NOTE: requires native event tab support
// cypress-plugin-tab does not mimic the behavior of tabbing in this context exactly as the browser does
it.skip('tabbing moves focus to the next element with a tabIndex', () => {
cy.render(render, (
<Select>
<SelectItem value="v1" data-test={`v1`} />
<input type="text"/>
<SelectItem value="v2" data-test={`v2`} />
<SelectItem value="v3" data-test={`v3`} />
</Select>
))
cy.get('[data-test="v1"]').focus().tab()
cy.window().then((win) => {
cy.get('input[type="text"]').then((el) => {
expect(win.document.activeElement).to.eql(el[0])
})
})
cy.get('[data-test="v3"]').focus().tab({ shift: true })
cy.window().then((win) => {
cy.get('input[type="text"]').then((el) => {
expect(win.document.activeElement).to.eql(el[0])
})
})
})
describe('arrow keys', () => {
const left = 13
const up = 38
const right = 39
const down = 40
let onChange
beforeEach(() => {
const Wrapper = ({ onChangeSpy }) => {
const [selected, setSelected] = useState()
const onChange = (value) => {
onChangeSpy(value)
setSelected(value)
}
return (
<Select value={selected} onChange={onChange}>
<SelectItem value="v1" />
<input type="text"/>
<SelectItem value="v2" />
<SelectItem value="v3" />
<SelectItem value="v4">
<input data-cy="input" type="text" />
</SelectItem>
<SelectItem value="v5" />
</Select>
)
}
onChange = cy.spy()
cy.render(render, <Wrapper onChangeSpy={onChange} />)
cy.get('li').as('items')
cy.get('[value]').as('values')
})
it('left on first goes to last', () => {
cy.get('@items').first().click().trigger('keydown', { keyCode: left, which: left })
cy.get('@values').last().should('be.checked')
cy.wrap(onChange).should('be.calledWith', 'v5')
})
it('up on first goes to last', () => {
cy.get('@items').first().click().trigger('keydown', { keyCode: up, which: up })
cy.get('@values').last().should('be.checked')
cy.wrap(onChange).should('be.calledWith', 'v5')
})
it('right on last goes to first', () => {
cy.get('@items').last().click().trigger('keydown', { keyCode: right, which: right })
cy.get('@values').first().should('be.checked')
cy.wrap(onChange).should('be.calledWith', 'v1')
})
it('down on last goes to first', () => {
cy.get('@items').last().click().trigger('keydown', { keyCode: down, which: down })
cy.get('@values').first().should('be.checked')
cy.wrap(onChange).should('be.calledWith', 'v1')
})
it('left on last goes to penultimate', () => {
cy.get('@items').last().click().trigger('keydown', { keyCode: left, which: left })
cy.get('@values').eq(3).should('be.checked')
cy.wrap(onChange).should('be.calledWith', 'v4')
})
it('up on last goes to penultimate', () => {
cy.get('@items').last().click().trigger('keydown', { keyCode: up, which: up })
cy.get('@values').eq(3).should('be.checked')
cy.wrap(onChange).should('be.calledWith', 'v4')
})
it('right on first goes to second', () => {
cy.get('@items').first().click().trigger('keydown', { keyCode: right, which: right })
cy.get('@values').eq(1).should('be.checked')
cy.wrap(onChange).should('be.calledWith', 'v2')
})
it('down on first goes to second', () => {
cy.get('@items').first().click().trigger('keydown', { keyCode: down, which: down })
cy.get('@values').eq(1).should('be.checked')
cy.wrap(onChange).should('be.calledWith', 'v2')
})
describe('when keydown comes from inner element', () => {
it('does not move on left', () => {
cy.get('[data-cy="input"]').type('{leftarrow}')
cy.get('@values').eq(3).should('be.checked')
})
it('does not move on right', () => {
cy.get('[data-cy="input"]').type('{rightarrow}')
cy.get('@values').eq(3).should('be.checked')
})
it('does not move on up', () => {
cy.get('[data-cy="input"]').type('{uparrow}')
cy.get('@values').eq(3).should('be.checked')
})
it('does not move on down', () => {
cy.get('[data-cy="input"]').type('{downarrow}')
cy.get('@values').eq(3).should('be.checked')
})
})
})
})
})