1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222 |
- import { beVisible, beHidden, haveAttribute, haveClasses, notHaveClasses, haveText, contain, notContain, html, notBeVisible, notHaveAttribute, notExist, haveFocus, test, haveValue, haveLength} from '../../../utils'
- test('it works with x-model',
- [html`
- <div
- x-data="{
- query: '',
- selected: null,
- people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ],
- get filteredPeople() {
- return this.query === ''
- ? this.people
- : this.people.filter((person) => {
- return person.name.toLowerCase().includes(this.query.toLowerCase())
- })
- },
- }"
- >
- <div x-combobox x-model="selected">
- <label x-combobox:label>Select person</label>
- <div>
- <div>
- <input
- x-combobox:input
- :display-value="person => person.name"
- @change="query = $event.target.value"
- placeholder="Search..."
- />
- <button x-combobox:button>Toggle</button>
- </div>
- <div x-combobox:options>
- <ul>
- <template
- x-for="person in filteredPeople"
- :key="person.id"
- hidden
- >
- <li
- x-combobox:option
- :option="person.id"
- :value="person"
- :disabled="person.disabled"
- x-text="person.name"
- >
- </li>
- </template>
- </ul>
- <p x-show="filteredPeople.length == 0">No people match your query.</p>
- </div>
- </div>
- <article x-text="selected?.name"></article>
- </div>
- </div>
- `],
- ({ get }) => {
- get('ul').should(notBeVisible())
- get('button').click()
- get('ul').should(beVisible())
- get('button').click()
- get('ul').should(notBeVisible())
- get('button').click()
- get('[option="2"]').click()
- get('ul').should(notBeVisible())
- get('input').should(haveValue('Arlene Mccoy'))
- get('article').should(haveText('Arlene Mccoy'))
- get('button').click()
- get('ul').should(contain('Wade Cooper'))
- .should(contain('Arlene Mccoy'))
- .should(contain('Devon Webb'))
- get('[option="3"]').click()
- get('ul').should(notBeVisible())
- get('input').should(haveValue('Devon Webb'))
- get('article').should(haveText('Devon Webb'))
- get('button').click()
- get('ul').should(contain('Wade Cooper'))
- .should(contain('Arlene Mccoy'))
- .should(contain('Devon Webb'))
- get('[option="1"]').click()
- get('ul').should(notBeVisible())
- get('input').should(haveValue('Wade Cooper'))
- get('article').should(haveText('Wade Cooper'))
- },
- )
- test('it works with internal state',
- [html`
- <div
- x-data="{ people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]}"
- x-combobox
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button x-combobox:button x-text="$combobox.value ? $combobox.value.name : 'Select Person'"></button>
- <ul x-combobox:options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person"
- :disabled="person.disabled"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('ul').should(notBeVisible())
- get('button')
- .should(haveText('Select Person'))
- .click()
- get('ul').should(beVisible())
- get('button').click()
- get('ul').should(notBeVisible())
- get('button').click()
- get('[option="2"]').click()
- get('ul').should(notBeVisible())
- get('button').should(haveText('Arlene Mccoy'))
- get('input').should(haveValue('Arlene Mccoy'))
- },
- )
- test('$combobox/$comboboxOption',
- [html`
- <div
- x-data="{ people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]}"
- x-combobox
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button x-combobox:button x-text="$combobox.value ? $combobox.value.name : 'Select Person'"></button>
- <p x-text="$combobox.activeIndex"></p>
- <article x-text="$combobox.activeOption?.name"></article>
- <ul x-combobox:options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person"
- :disabled="person.disabled"
- :class="{
- 'selected': $comboboxOption.isSelected,
- 'active': $comboboxOption.isActive,
- 'disabled': $comboboxOption.isDisabled,
- }"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('article').should(haveText(''))
- get('[option="5"]').should(haveClasses(['disabled']))
- get('button')
- .should(haveText('Select Person'))
- .click()
- get('[option="1"]').should(haveClasses(['active']))
- get('input').type('{downarrow}')
- get('article').should(haveText('Arlene Mccoy'))
- get('p').should(haveText('1'))
- get('[option="2"]').should(haveClasses(['active']))
- get('button').should(haveText('Select Person'))
- get('[option="2"]').click()
- get('button').should(haveText('Arlene Mccoy'))
- get('[option="2"]').should(haveClasses(['selected']))
- },
- )
- test('"name" prop',
- [html`
- <div
- x-data="{ people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]}"
- x-combobox
- name="person"
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button x-combobox:button x-text="$combobox.value ? $combobox.value : 'Select Person'"></button>
- <ul x-combobox:options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person.id"
- :disabled="person.disabled"
- :class="{
- 'selected': $comboboxOption.isSelected,
- 'active': $comboboxOption.isActive,
- }"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('input').should(haveAttribute('value', 'null'))
- get('button').click()
- get('input').should(haveAttribute('value', 'null'))
- get('[option="2"]').click()
- get('input').should(beHidden())
- .should(haveAttribute('name', 'person'))
- .should(haveAttribute('value', '2'))
- .should(haveAttribute('type', 'hidden'))
- get('button').click()
- get('[option="4"]').click()
- get('input').should(beHidden())
- .should(haveAttribute('name', 'person'))
- .should(haveAttribute('value', '4'))
- .should(haveAttribute('type', 'hidden'))
- },
- );
- test('Preserves currenty active selection while options change from searching even if there\'s a selected option in the filtered results',
- [html`
- <div
- x-data="{
- query: '',
- selected: null,
- people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ],
- get filteredPeople() {
- return this.query === ''
- ? this.people
- : this.people.filter((person) => {
- return person.name.toLowerCase().includes(this.query.toLowerCase())
- })
- },
- }"
- >
- <div x-combobox x-model="selected">
- <label x-combobox:label>Select person</label>
- <div>
- <div>
- <input
- x-combobox:input
- :display-value="person => person.name"
- @change="query = $event.target.value"
- placeholder="Search..."
- />
- <button x-combobox:button>Toggle</button>
- </div>
- <div x-combobox:options>
- <ul>
- <template
- x-for="person in filteredPeople"
- :key="person.id"
- hidden
- >
- <li
- x-combobox:option
- :option="person.id"
- :value="person"
- :disabled="person.disabled"
- >
- <span x-text="person.name"></span>
- <span x-show="$comboboxOption.isActive">*</span>
- <span x-show="$comboboxOption.isSelected">x</span>
- </li>
- </template>
- </ul>
- <p x-show="filteredPeople.length == 0">No people match your query.</p>
- </div>
- </div>
- </div>
- <article>lorem ipsum</article>
- </div>
- `],
- ({ get }) => {
- get('input').should(haveText(''))
- get('button').click()
- get('[option="3"]').click()
- cy.wait(100)
- get('input').type('{selectAll}{backspace}')
- cy.wait(100)
- get('input').type('{downArrow}')
- cy.wait(100)
- get('[option="3"]').should(contain('*'))
- get('input').type('{upArrow}{upArrow}')
- cy.wait(100)
- get('[option="1"]').should(contain('*'))
- cy.wait(100)
- get('input').type('d')
- get('input').trigger('change')
- cy.wait(100)
- get('[option="1"]').should(contain('*'))
- },
- );
- test('"name" prop with object value',
- [html`
- <div
- x-data="{ people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]}"
- x-combobox
- name="person"
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button x-combobox:button x-text="$combobox.value ? $combobox.value.name : 'Select Person'"></button>
- <ul x-combobox:options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person"
- :disabled="person.disabled"
- :class="{
- 'selected': $comboboxOption.isSelected,
- 'active': $comboboxOption.isActive,
- }"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('input[name="person"]').should(haveAttribute('value', 'null'))
- get('button').click()
- get('[name="person[id]"]').should(notExist())
- get('[option="2"]').click()
- get('input[name="person"]').should(notExist())
- get('[name="person[id]"]').should(beHidden())
- .should(haveAttribute('value', '2'))
- .should(haveAttribute('type', 'hidden'))
- get('[name="person[name]"]').should(beHidden())
- .should(haveAttribute('value', 'Arlene Mccoy'))
- .should(haveAttribute('type', 'hidden'))
- get('button').click()
- get('[option="4"]').click()
- get('[name="person[id]"]').should(beHidden())
- .should(haveAttribute('value', '4'))
- .should(haveAttribute('type', 'hidden'))
- get('[name="person[name]"]').should(beHidden())
- .should(haveAttribute('value', 'Tom Cook'))
- .should(haveAttribute('type', 'hidden'))
- },
- );
- test('"default-value" prop',
- [html`
- <div
- x-data="{ people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]}"
- x-combobox
- name="person"
- default-value="2"
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button x-combobox:button x-text="$combobox.value ? $combobox.value : 'Select Person'"></button>
- <ul x-combobox:options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person.id"
- :disabled="person.disabled"
- :class="{
- 'selected': $comboboxOption.isSelected,
- 'active': $comboboxOption.isActive,
- }"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('input[name="person"]').should(beHidden())
- .should(haveAttribute('value', '2'))
- .should(haveAttribute('type', 'hidden'))
- },
- );
- test('"multiple" prop',
- [html`
- <div
- x-data="{
- people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]
- }"
- x-combobox
- multiple
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button x-combobox:button x-text="$combobox.value ? $combobox.value.join(',') : 'Select People'"></button>
- <ul x-combobox:options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person.id"
- :disabled="person.disabled"
- :class="{
- 'selected': $comboboxOption.isSelected,
- 'active': $comboboxOption.isActive,
- }"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('button').click()
- get('[option="2"]').click()
- get('ul').should(beVisible())
- get('button').should(haveText('2'))
- get('[option="4"]').click()
- get('button').should(haveText('2,4'))
- get('ul').should(beVisible())
- get('[option="4"]').click()
- get('button').should(haveText('2'))
- get('ul').should(beVisible())
- get('input').type('Tom')
- get('input').type('{enter}')
- get('button').should(haveText('2,4'))
- // input field doesn't reset when a new option is selected
- get('input').should(haveValue('Tom'))
- },
- );
- test('"multiple" and "name" props together',
- [html`
- <div
- x-data="{
- people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]
- }"
- x-combobox
- multiple
- name="people"
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button x-combobox:button x-text="$combobox.value ? $combobox.value.map(p => p.id).join(',') : 'Select People'"></button>
- <ul x-combobox:options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person"
- :disabled="person.disabled"
- :class="{
- 'selected': $comboboxOption.isSelected,
- 'active': $comboboxOption.isActive,
- }"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- // get('input[name="people"]').should(haveAttribute('value', 'null'))
- get('button').click()
- get('[name="people[0][id]"]').should(notExist())
- get('[option="2"]').click()
- get('ul').should(beVisible())
- get('button').should(haveText('2'))
- get('input[name="people"]').should(notExist())
- get('[name="people[0][id]"]').should(beHidden())
- .should(haveAttribute('value', '2'))
- .should(haveAttribute('type', 'hidden'))
- get('[name="people[0][name]"]').should(beHidden())
- .should(haveAttribute('value', 'Arlene Mccoy'))
- .should(haveAttribute('type', 'hidden'))
- get('[option="4"]').click()
- get('[name="people[0][id]"]').should(beHidden())
- .should(haveAttribute('value', '2'))
- .should(haveAttribute('type', 'hidden'))
- get('[name="people[0][name]"]').should(beHidden())
- .should(haveAttribute('value', 'Arlene Mccoy'))
- .should(haveAttribute('type', 'hidden'))
- get('[name="people[1][id]"]').should(beHidden())
- .should(haveAttribute('value', '4'))
- .should(haveAttribute('type', 'hidden'))
- get('[name="people[1][name]"]').should(beHidden())
- .should(haveAttribute('value', 'Tom Cook'))
- .should(haveAttribute('type', 'hidden'))
- get('button').should(haveText('2,4'))
- get('ul').should(beVisible())
- get('[option="4"]').click()
- get('[name="people[0][id]"]').should(beHidden())
- .should(haveAttribute('value', '2'))
- .should(haveAttribute('type', 'hidden'))
- get('[name="people[0][name]"]').should(beHidden())
- .should(haveAttribute('value', 'Arlene Mccoy'))
- .should(haveAttribute('type', 'hidden'))
- get('[name="people[1][id]"]').should(notExist())
- get('[name="people[1][name]"]').should(notExist())
- get('button').should(haveText('2'))
- get('ul').should(beVisible())
- },
- );
- test('keyboard controls',
- [html`
- <div
- x-data="{ active: null, people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb', disabled: true },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]}"
- x-combobox
- x-model="active"
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button x-combobox:button x-text="active ? active.name : 'Select Person'"></button>
- <ul x-combobox:options options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person"
- :disabled="person.disabled"
- :class="{
- 'selected': $comboboxOption.isSelected,
- 'active': $comboboxOption.isActive,
- }"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('.active').should(notExist())
- get('button').click()
- get('[options]')
- .should(beVisible())
- get('input').should(haveFocus())
- get('[option="1"]')
- .should(haveClasses(['active']))
- get('input')
- .type('{downarrow}')
- get('[option="2"]')
- .should(haveClasses(['active']))
- get('input')
- .type('{downarrow}')
- get('[option="4"]')
- .should(haveClasses(['active']))
- get('input')
- .type('{uparrow}')
- get('[option="2"]')
- .should(haveClasses(['active']))
- get('input')
- .type('{home}')
- get('[option="1"]')
- .should(haveClasses(['active']))
- get('input')
- .type('{end}')
- get('[option="10"]')
- .should(haveClasses(['active']))
- get('input')
- .type('{pageUp}')
- get('[option="1"]')
- .should(haveClasses(['active']))
- get('input')
- .type('{pageDown}')
- get('[option="10"]')
- .should(haveClasses(['active']))
- get('input')
- .tab()
- .should(haveFocus())
- get('[options]')
- .should(beVisible())
- get('input')
- .type('{esc}')
- get('[options]')
- .should(notBeVisible())
- },
- )
- test('changing value manually changes internal state',
- [html`
- <div
- x-data="{ active: null, people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb', disabled: true },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]}"
- x-combobox
- x-model="active"
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button toggle x-combobox:button x-text="$combobox.value ? $combobox.value : 'Select Person'"></button>
- <button select-tim @click="active = 4">Select Tim</button>
- <ul x-combobox:options options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person.id"
- :disabled="person.disabled"
- :class="{
- 'selected': $comboboxOption.isSelected,
- 'active': $comboboxOption.isActive,
- }"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('[select-tim]').click()
- get('[option="4"]').should(haveClasses(['selected']))
- get('[option="1"]').should(notHaveClasses(['selected']))
- get('[toggle]').should(haveText('4'))
- },
- )
- test('has accessibility attributes',
- [html`
- <div
- x-data="{ active: null, people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb', disabled: true },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]}"
- x-combobox
- x-model="active"
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button x-combobox:button x-text="active ? active.name : 'Select Person'"></button>
- <ul x-combobox:options options>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person"
- :disabled="person.disabled"
- :class="{
- 'selected': $comboboxOption.isSelected,
- 'active': $comboboxOption.isActive,
- }"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('input')
- .should(haveAttribute('aria-expanded', 'false'))
- get('button')
- .should(haveAttribute('aria-haspopup', 'true'))
- .should(haveAttribute('aria-labelledby', 'alpine-combobox-label-1 alpine-combobox-button-1'))
- .should(haveAttribute('aria-expanded', 'false'))
- .should(notHaveAttribute('aria-controls'))
- .should(haveAttribute('id', 'alpine-combobox-button-1'))
- .should(haveAttribute('tabindex', '-1'))
- .click()
- .should(haveAttribute('aria-expanded', 'true'))
- .should(haveAttribute('aria-controls', 'alpine-combobox-options-1'))
- get('[options]')
- .should(haveAttribute('role', 'combobox'))
- .should(haveAttribute('id', 'alpine-combobox-options-1'))
- .should(haveAttribute('aria-labelledby', 'alpine-combobox-label-1'))
- get('[option="1"]')
- .should(haveAttribute('role', 'option'))
- .should(haveAttribute('id', 'alpine-combobox-option-1'))
- .should(haveAttribute('tabindex', '-1'))
- .should(haveAttribute('aria-selected', 'true'))
- get('[option="2"]')
- .should(haveAttribute('role', 'option'))
- .should(haveAttribute('id', 'alpine-combobox-option-2'))
- .should(haveAttribute('tabindex', '-1'))
- .should(haveAttribute('aria-selected', 'false'))
- get('input')
- .should(haveAttribute('role', 'combobox'))
- .should(haveAttribute('aria-autocomplete', 'list'))
- .should(haveAttribute('tabindex', '0'))
- .should(haveAttribute('aria-expanded', 'true'))
- .should(haveAttribute('aria-labelledby', 'alpine-combobox-label-1'))
- .should(haveAttribute('aria-controls', 'alpine-combobox-options-1'))
- .should(haveAttribute('aria-activedescendant', 'alpine-combobox-option-1'))
- .type('{downarrow}')
- .should(haveAttribute('aria-activedescendant', 'alpine-combobox-option-2'))
- get('[option="2"]')
- .should(haveAttribute('aria-selected', 'true'))
- },
- )
- test('"static" prop',
- [html`
- <div
- x-data="{ active: null, show: false, people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ]}"
- x-combobox
- x-model="active"
- >
- <label x-combobox:label>Assigned to</label>
- <input x-combobox:input :display-value="(person) => person.name" type="text">
- <button normal-toggle x-combobox:button x-text="active ? active.name : 'Select Person'"></button>
- <button real-toggle @click="show = ! show">Toggle</button>
- <ul x-combobox:options x-show="show" static>
- <template x-for="person in people" :key="person.id">
- <li
- :option="person.id"
- x-combobox:option
- :value="person"
- :disabled="person.disabled"
- >
- <span x-text="person.name"></span>
- </li>
- </template>
- </ul>
- </div>
- `],
- ({ get }) => {
- get('ul').should(notBeVisible())
- get('[normal-toggle]')
- .should(haveText('Select Person'))
- .click()
- get('ul').should(notBeVisible())
- get('[real-toggle]').click()
- get('ul').should(beVisible())
- get('[option="2"]').click()
- get('ul').should(beVisible())
- get('[normal-toggle]').should(haveText('Arlene Mccoy'))
- },
- )
- test('input reset',
- [html`
- <div
- x-data="{
- query: '',
- selected: null,
- people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ],
- get filteredPeople() {
- return this.query === ''
- ? this.people
- : this.people.filter((person) => {
- return person.name.toLowerCase().includes(this.query.toLowerCase())
- })
- },
- }"
- >
- <div x-combobox x-model="selected">
- <label x-combobox:label>Select person</label>
- <div>
- <div>
- <input
- x-combobox:input
- :display-value="person => person.name"
- @change="query = $event.target.value"
- placeholder="Search..."
- />
- <button x-combobox:button>Toggle</button>
- </div>
- <div x-combobox:options>
- <ul>
- <template
- x-for="person in filteredPeople"
- :key="person.id"
- hidden
- >
- <li
- x-combobox:option
- :option="person.id"
- :value="person"
- :disabled="person.disabled"
- x-text="person.name"
- >
- </li>
- </template>
- </ul>
- <p x-show="filteredPeople.length == 0">No people match your query.</p>
- </div>
- </div>
- </div>
- <article>lorem ipsum</article>
- </div>
- `],
- ({ get }) => {
- // Test after closing with button
- get('button').click()
- get('input').type('w')
- get('button').click()
- get('input').should(haveValue(''))
- // Test correct state after closing with ESC
- get('button').click()
- get('input').type('w')
- get('input').type('{esc}')
- get('input').should(haveValue(''))
- // Test correct state after closing with TAB
- get('button').click()
- get('input').type('w')
- get('input').tab()
- get('input').should(haveValue(''))
- // Test correct state after closing with external click
- get('button').click()
- get('input').type('w')
- get('article').click()
- get('input').should(haveValue(''))
- // Select something
- get('button').click()
- get('ul').should(beVisible())
- get('[option="2"]').click()
- get('input').should(haveValue('Arlene Mccoy'))
- // Test after closing with button
- get('button').click()
- get('input').type('w')
- get('button').click()
- get('input').should(haveValue('Arlene Mccoy'))
- // Test correct state after closing with ESC and reopening
- get('button').click()
- get('input').type('w')
- get('input').type('{esc}')
- get('input').should(haveValue('Arlene Mccoy'))
- // Test correct state after closing with TAB and reopening
- get('button').click()
- get('input').type('w')
- get('input').tab()
- get('input').should(haveValue('Arlene Mccoy'))
- // Test correct state after closing with external click and reopening
- get('button').click()
- get('input').type('w')
- get('article').click()
- get('input').should(haveValue('Arlene Mccoy'))
- },
- )
- test('combobox shows all options when opening',
- [html`
- <div
- x-data="{
- query: '',
- selected: null,
- people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ],
- get filteredPeople() {
- return this.query === ''
- ? this.people
- : this.people.filter((person) => {
- return person.name.toLowerCase().includes(this.query.toLowerCase())
- })
- },
- }"
- >
- <div x-combobox x-model="selected">
- <label x-combobox:label>Select person</label>
- <div>
- <div>
- <input
- x-combobox:input
- :display-value="person => person.name"
- @change="query = $event.target.value"
- placeholder="Search..."
- />
- <button x-combobox:button>Toggle</button>
- </div>
- <div x-combobox:options>
- <ul>
- <template
- x-for="person in filteredPeople"
- :key="person.id"
- hidden
- >
- <li
- x-combobox:option
- :option="person.id"
- :value="person"
- :disabled="person.disabled"
- x-text="person.name"
- >
- </li>
- </template>
- </ul>
- <p x-show="filteredPeople.length == 0">No people match your query.</p>
- </div>
- </div>
- </div>
- <article>lorem ipsum</article>
- </div>
- `],
- ({ get }) => {
- get('button').click()
- get('li').should(haveLength('10'))
- // Test after closing with button and reopening
- get('input').type('w').trigger('input')
- get('li').should(haveLength('2'))
- get('button').click()
- get('button').click()
- get('li').should(haveLength('10'))
- // Test correct state after closing with ESC and reopening
- get('input').type('w').trigger('input')
- get('li').should(haveLength('2'))
- get('input').type('{esc}')
- get('button').click()
- get('li').should(haveLength('10'))
- // Test correct state after closing with TAB and reopening
- get('input').type('w').trigger('input')
- get('li').should(haveLength('2'))
- get('input').tab()
- get('button').click()
- get('li').should(haveLength('10'))
- // Test correct state after closing with external click and reopening
- get('input').type('w').trigger('input')
- get('li').should(haveLength('2'))
- get('article').click()
- get('button').click()
- get('li').should(haveLength('10'))
- },
- )
- test('active element logic when opening a combobox',
- [html`
- <div
- x-data="{
- query: '',
- selected: null,
- people: [
- { id: 1, name: 'Wade Cooper' },
- { id: 2, name: 'Arlene Mccoy' },
- { id: 3, name: 'Devon Webb' },
- { id: 4, name: 'Tom Cook' },
- { id: 5, name: 'Tanya Fox', disabled: true },
- { id: 6, name: 'Hellen Schmidt' },
- { id: 7, name: 'Caroline Schultz' },
- { id: 8, name: 'Mason Heaney' },
- { id: 9, name: 'Claudie Smitham' },
- { id: 10, name: 'Emil Schaefer' },
- ],
- get filteredPeople() {
- return this.query === ''
- ? this.people
- : this.people.filter((person) => {
- return person.name.toLowerCase().includes(this.query.toLowerCase())
- })
- },
- }"
- >
- <div x-combobox x-model="selected">
- <label x-combobox:label>Select person</label>
- <div>
- <div>
- <input
- x-combobox:input
- :display-value="person => person.name"
- @change="query = $event.target.value"
- placeholder="Search..."
- />
- <button x-combobox:button>Toggle</button>
- </div>
- <div x-combobox:options>
- <ul>
- <template
- x-for="person in filteredPeople"
- :key="person.id"
- hidden
- >
- <li
- x-combobox:option
- :option="person.id"
- :value="person"
- :disabled="person.disabled"
- x-text="person.name"
- >
- </li>
- </template>
- </ul>
- <p x-show="filteredPeople.length == 0">No people match your query.</p>
- </div>
- </div>
- </div>
- </div>
- `],
- ({ get }) => {
- get('button').click()
- // First option is selected on opening if no preselection
- get('ul').should(beVisible())
- get('[option="1"]').should(haveAttribute('aria-selected', 'true'))
- // First match is selected while typing
- get('[option="4"]').should(haveAttribute('aria-selected', 'false'))
- get('input').type('T')
- get('input').trigger('change')
- get('[option="4"]').should(haveAttribute('aria-selected', 'true'))
- // Reset state and select option 3
- get('button').click()
- get('button').click()
- get('[option="3"]').click()
- // Previous selection is selected
- get('button').click()
- get('[option="4"]').should(haveAttribute('aria-selected', 'false'))
- get('[option="3"]').should(haveAttribute('aria-selected', 'true'))
- }
- )
|