Skip to content

Commit

Permalink
fix(ui): add role="list" to QList (fix: #17439) (#17441)
Browse files Browse the repository at this point in the history
* fix(a11y): Add role="list" on the list, fixes #17439

* test: add tests for QList component

* docs: add watch mode instruction for a filter

* Review: remove unnecessary defined check

Co-authored-by: Yusuf Kandemir <yusuf.kandemir@outlook.com.tr>

* Review: make it more concise

Co-authored-by: Yusuf Kandemir <yusuf.kandemir@outlook.com.tr>

---------

Co-authored-by: Evert van der Weit <evert@mett.nl>
Co-authored-by: Yusuf Kandemir <yusuf.kandemir@outlook.com.tr>
  • Loading branch information
3 people authored Aug 16, 2024
1 parent 73add64 commit a0b7171
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 1 deletion.
4 changes: 3 additions & 1 deletion ui/src/components/item/QList.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export default createComponent({
+ (props.padding === true ? ' q-list--padding' : '')
)

return () => h(props.tag, { class: classes.value }, hSlot(slots.default))
const role = computed(() => props.tag === 'ul' || props.tag === 'ol' ? undefined : 'list')

return () => h(props.tag, { class: classes.value, role: role.value }, hSlot(slots.default))
}
})
170 changes: 170 additions & 0 deletions ui/src/components/item/QList.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import { mount, flushPromises } from '@vue/test-utils'
import { describe, test, expect } from 'vitest'

import QList from './QList.js'

describe('[QList API]', () => {
describe('[Props]', () => {
describe('[default attributes]', () => {
test('has a role="list" attribute with a div', async () => {
const wrapper = mount(QList)

const target = wrapper.get('.q-list')

expect(target.element.getAttribute('role')).toBe('list')
})

test('does not have a role="list" attribute with a ol', async () => {
const wrapper = mount(QList, { props: { tag: 'ol' } })

const target = wrapper.get('.q-list')

expect(target.element.getAttribute('role')).toBe(null)
})

test('does not have a role="list" attribute with a ul', async () => {
const wrapper = mount(QList, { props: { tag: 'ul' } })

const target = wrapper.get('.q-list')

expect(target.element.getAttribute('role')).toBe(null)
})
})

describe('[(prop)bordered]', () => {
test('type Boolean has effect', async () => {
const wrapper = mount(QList)

const target = wrapper.get('.q-list')

expect(target.classes()).not.toContain('q-list--bordered')

await wrapper.setProps({ bordered: true })
await flushPromises()

expect(target.classes()).toContain('q-list--bordered')
})
})

describe('[(prop)dense]', () => {
test('type Boolean has effect', async () => {
const wrapper = mount(QList)

const target = wrapper.get('.q-list')

expect(target.classes()).not.toContain('q-list--dense')

await wrapper.setProps({ dense: true })
await flushPromises()

expect(target.classes()).toContain('q-list--dense')
})
})

describe('[(prop)separator]', () => {
test('type Boolean has effect', async () => {
const wrapper = mount(QList)

const target = wrapper.get('.q-list')

expect(target.classes()).not.toContain('q-list--separator')

await wrapper.setProps({ separator: true })
await flushPromises()

expect(target.classes()).toContain('q-list--separator')
})
})

describe('[(prop)dark]', () => {
test('type Boolean has effect', async () => {
const wrapper = mount(QList)
await wrapper.setProps({ dark: false })

const target = wrapper.get('.q-list')

expect(target.classes()).not.toContain('q-list--dark')

await wrapper.setProps({ dark: true })
await flushPromises()

expect(target.classes()).toContain('q-list--dark')

await wrapper.setProps({ dark: false })
await wrapper.vm.$q.dark.set(true)
await flushPromises()

expect(target.classes()).not.toContain('q-list--dark')
})

test('type null has effect', async () => {
const wrapper = mount(QList)
await wrapper.vm.$q.dark.set(false)

const target = wrapper.get('.q-list')
expect(target.classes()).not.toContain('q-list--dark')

await wrapper.setProps({ dark: null })
await flushPromises()

expect(target.classes()).not.toContain('q-list--dark')

await wrapper.vm.$q.dark.set(true)

expect(target.classes()).toContain('q-list--dark')
})
})

describe('[(prop)padding]', () => {
test('type Boolean has effect', async () => {
const wrapper = mount(QList)

const target = wrapper.get('.q-list')

expect(target.classes()).not.toContain('q-list--padding')

await wrapper.setProps({ padding: true })
await flushPromises()

expect(target.classes()).toContain('q-list--padding')
})
})

describe('[(prop)tag]', () => {
test('type String has effect', async () => {
const wrapper = mount(QList, { props: { tag: 'ol' } })

const target = wrapper.get('.q-list')

expect(
target.element.tagName.toLowerCase()
).toBe('ol')
})

test('default tag is div', async () => {
const wrapper = mount(QList)

const target = wrapper.get('.q-list')

expect(
target.element.tagName.toLowerCase()
).toBe('div')
})
})
})

describe('[Slots]', () => {
describe('[(slot)default]', () => {
test('renders the content', () => {
const slotContent = 'some-slot-content'
const wrapper = mount(QList, {
slots: {
default: () => slotContent
}
})

expect(wrapper.html()).toContain(slotContent)
})
})
})
})
3 changes: 3 additions & 0 deletions ui/testing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ $ pnpm test:specs --target <target_file>
# withOUT Vitest UI:
$ pnpm test:watch

# to watch only a specific file pattern
$ pnpm test:watch "QList"

# with Vitest UI:
$ pnpm test:watch:ui
```
Expand Down

0 comments on commit a0b7171

Please sign in to comment.