Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@
"nuxt": "^4.1.2",
"release-it": "^19.0.5",
"vitest": "^3.2.4",
"vitest-axe": "^0.1.0",
"vitest-environment-nuxt": "^1.0.1",
"vue-tsc": "^3.1.0"
},
Expand Down
61 changes: 59 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/runtime/components/AuthForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,9 @@ function omitFieldProps(field: F) {
/>
<UInput
v-else-if="field.type === 'password'"
v-bind="(omitFieldProps(field) as AuthFormInputField<'password'>)"
v-model="state[field.name]"
:class="ui.password({ class: props.ui?.password })"
v-bind="(omitFieldProps(field) as AuthFormInputField<'password'>)"
:type="passwordVisibility ? 'text' : 'password'"
>
<template #trailing>
Expand Down
10 changes: 10 additions & 0 deletions test/components/Accordion.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { describe, it, expect } from 'vitest'
import Accordion from '../../src/runtime/components/Accordion.vue'
import type { AccordionProps, AccordionSlots } from '../../src/runtime/components/Accordion.vue'
import ComponentRender from '../component-render'
import { axe } from 'vitest-axe'
import { mountSuspended } from '@nuxt/test-utils/runtime'

describe('Accordion', () => {
const items = [{
Expand Down Expand Up @@ -62,4 +64,12 @@ describe('Accordion', () => {
const html = await ComponentRender(nameOrHtml, options, Accordion)
expect(html).toMatchSnapshot()
})

it('passes accessibility tests', async () => {
const wrapper = await mountSuspended(Accordion, {
props: { items, modelValue: '1' }
})

expect(await axe(wrapper.element)).toHaveNoViolations()
})
})
20 changes: 20 additions & 0 deletions test/components/Alert.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import Alert from '../../src/runtime/components/Alert.vue'
import type { AlertProps, AlertSlots } from '../../src/runtime/components/Alert.vue'
import ComponentRender from '../component-render'
import theme from '#build/ui/alert'
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { axe } from 'vitest-axe'

describe('Alert', () => {
const variants = Object.keys(theme.variants.variant) as any
Expand Down Expand Up @@ -34,4 +36,22 @@ describe('Alert', () => {
const html = await ComponentRender(nameOrHtml, options, Alert)
expect(html).toMatchSnapshot()
})

it('passes accessibility tests', async () => {
const wrapper = await mountSuspended(Alert, {
props: {
title: 'Alert',
icon: 'i-lucide-lightbulb',
description: 'This is a description',
actions: [{ label: 'Action' }],
close: true,
avatar: {
src: 'https://github.com/benjamincanac.png',
alt: 'Benjamin Canac'
}
}
})

expect(await axe(wrapper.element)).toHaveNoViolations()
})
})
24 changes: 24 additions & 0 deletions test/components/AuthForm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { describe, it, expect } from 'vitest'
import AuthForm from '../../src/runtime/components/AuthForm.vue'
import type { AuthFormProps, AuthFormSlots } from '../../src/runtime/components/AuthForm.vue'
import ComponentRender from '../component-render'
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { axe } from 'vitest-axe'

describe('AuthForm', () => {
const fields = [{
Expand Down Expand Up @@ -44,4 +46,26 @@ describe('AuthForm', () => {
const html = await ComponentRender(nameOrHtml, options, AuthForm)
expect(html).toMatchSnapshot()
})

it('passes accessibility tests', async () => {
const wrapper = await mountSuspended(AuthForm, {
props: {
fields,
title: 'Title',
description: 'Description',
icon: 'i-lucide-user',
providers: [{ label: 'Google', icon: 'i-simple-icons-google' }],
separator: 'or',
submit: { label: 'Submit' }

}
})

expect(await axe(wrapper.element, {
rules: {
// The passwordVisibility button has an invalid aria-controls value - it need to point to the id of the password input not its name.
'aria-valid-attr-value': { enabled: false }
}
})).toHaveNoViolations()
})
})
13 changes: 13 additions & 0 deletions test/components/Avatar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import Avatar from '../../src/runtime/components/Avatar.vue'
import type { AvatarProps, AvatarSlots } from '../../src/runtime/components/Avatar.vue'
import ComponentRender from '../component-render'
import theme from '#build/ui/avatar'
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { axe } from 'vitest-axe'

describe('Avatar', () => {
const sizes = Object.keys(theme.variants.size) as any
Expand All @@ -26,4 +28,15 @@ describe('Avatar', () => {
const html = await ComponentRender(nameOrHtml, options, Avatar)
expect(html).toMatchSnapshot()
})

it('passes accessibility tests', async () => {
const wrapper = await mountSuspended(Avatar, {
props: {
alt: 'Benjamin Canac',
src: 'https://github.com/benjamincanac.png'
}
})

expect(await axe(wrapper.element)).toHaveNoViolations()
})
})
12 changes: 12 additions & 0 deletions test/components/AvatarGroup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import AvatarGroup from '../../src/runtime/components/AvatarGroup.vue'
import type { AvatarGroupProps, AvatarGroupSlots } from '../../src/runtime/components/AvatarGroup.vue'
import ComponentRender from '../component-render'
import theme from '#build/ui/avatar-group'
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { axe } from 'vitest-axe'

const AvatarGroupWrapper = defineComponent({
components: {
Expand Down Expand Up @@ -34,4 +36,14 @@ describe('AvatarGroup', () => {
const html = await ComponentRender(nameOrHtml, options, AvatarGroupWrapper)
expect(html).toMatchSnapshot()
})

it('passes accessibility tests', async () => {
const wrapper = await mountSuspended(AvatarGroupWrapper, {
props: {
max: 2
}
})

expect(await axe(wrapper.element)).toHaveNoViolations()
})
})
16 changes: 16 additions & 0 deletions test/components/Badge.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import Badge from '../../src/runtime/components/Badge.vue'
import type { BadgeProps, BadgeSlots } from '../../src/runtime/components/Badge.vue'
import ComponentRender from '../component-render'
import theme from '#build/ui/badge'
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { axe } from 'vitest-axe'

describe('Badge', () => {
const sizes = Object.keys(theme.variants.size) as any
Expand Down Expand Up @@ -34,4 +36,18 @@ describe('Badge', () => {
const html = await ComponentRender(nameOrHtml, options, Badge)
expect(html).toMatchSnapshot()
})

it('passes accessibility tests', async () => {
const wrapper = await mountSuspended(Badge, {
props: {
label: 'Badge',
icon: 'i-lucide-rocket',
leadingIcon: 'i-lucide-arrow-left',
trailingIcon: 'i-lucide-arrow-right',
avatar: { src: 'https://github.com/benjamincanac.png' }
}
})

expect(await axe(wrapper.element)).toHaveNoViolations()
})
})
16 changes: 16 additions & 0 deletions test/components/Banner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { describe, it, expect } from 'vitest'
import Banner from '../../src/runtime/components/Banner.vue'
import type { BannerProps, BannerSlots } from '../../src/runtime/components/Banner.vue'
import ComponentRender from '../component-render'
import { mountSuspended } from '@nuxt/test-utils/runtime'
import { axe } from 'vitest-axe'

describe('Banner', () => {
const props = { id: 'banner' }
Expand Down Expand Up @@ -29,4 +31,18 @@ describe('Banner', () => {
const html = await ComponentRender(nameOrHtml, options, Banner)
expect(html).toMatchSnapshot()
})

it('passes accessibility tests', async () => {
const wrapper = await mountSuspended(Banner, {
props: {
id: 'banner',
title: 'Title',
icon: 'i-lucide-rocket',
actions: [{ label: 'Learn more', trailingIcon: 'i-lucide-arrow-right' }],
close: true
}
})

expect(await axe(wrapper.element)).toHaveNoViolations()
})
})
Loading