Skip to content

Commit 895996f

Browse files
committed
fix: add a11y tests for missing components and fix failing type tests
1 parent 52f8ea0 commit 895996f

6 files changed

Lines changed: 132 additions & 6 deletions

File tree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// This type declaration file is required to break a circular type resolution in vue-tsc.
2+
// And is based off Package.d.vue.ts
3+
4+
import type { DefineComponent } from 'vue'
5+
6+
declare const _default: DefineComponent<{
7+
title: string
8+
authors?: { name: string; blueskyHandle?: string }[]
9+
date?: string
10+
primaryColor?: string
11+
}>
12+
13+
export default _default

app/pages/blog/index.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
<script setup lang="ts">
2-
const router = useRouter()
3-
42
import type { BlogPostFrontmatter } from '#shared/schemas/blog'
53
64
const blogModules = import.meta.glob<BlogPostFrontmatter>('./*.md', { eager: true })

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@
132132
"@types/sanitize-html": "2.16.0",
133133
"@types/semver": "7.7.1",
134134
"@types/validate-npm-package-name": "4.0.2",
135-
"@valibot/to-json-schema": "^1.5.0",
136135
"@vitest/browser-playwright": "4.0.18",
137136
"@vitest/coverage-v8": "4.0.18",
138137
"@vue/test-utils": "2.4.6",

pnpm-lock.yaml

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/nuxt/a11y.spec.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ import {
121121
AppLogo,
122122
AboutLogoImg,
123123
AboutLogoList,
124+
AuthorAvatar,
125+
AuthorList,
126+
BlogPostListCard,
127+
BlogPostWrapper,
128+
BlueskyComment,
129+
BlueskyComments,
124130
BaseCard,
125131
BlueskyPostEmbed,
126132
BuildEnvironment,
@@ -2159,6 +2165,117 @@ describe('component accessibility audits', () => {
21592165
})
21602166
})
21612167

2168+
describe('AuthorAvatar', () => {
2169+
it('should have no accessibility violations with fallback text', async () => {
2170+
const component = await mountSuspended(AuthorAvatar, {
2171+
props: {
2172+
author: {
2173+
name: 'Daniel Roe',
2174+
blueskyHandle: 'danielroe.dev',
2175+
avatar: null,
2176+
profileUrl: 'https://bsky.app/profile/danielroe.dev',
2177+
},
2178+
},
2179+
})
2180+
const results = await runAxe(component)
2181+
expect(results.violations).toEqual([])
2182+
})
2183+
})
2184+
2185+
describe('AuthorList', () => {
2186+
it('should have no accessibility violations', async () => {
2187+
const component = await mountSuspended(AuthorList, {
2188+
props: {
2189+
authors: [
2190+
{ name: 'Daniel Roe', blueskyHandle: 'danielroe.dev' },
2191+
{ name: 'Salma Alam-Naylor' },
2192+
],
2193+
},
2194+
})
2195+
const results = await runAxe(component)
2196+
expect(results.violations).toEqual([])
2197+
})
2198+
})
2199+
2200+
describe('BlogPostWrapper', () => {
2201+
it('should have no accessibility violations', async () => {
2202+
const component = await mountSuspended(BlogPostWrapper, {
2203+
props: {
2204+
frontmatter: {
2205+
authors: [{ name: 'Daniel Roe', blueskyHandle: 'danielroe.dev' }],
2206+
title: 'Building Accessible Vue Components',
2207+
date: '2024-06-15',
2208+
description: 'A guide to building accessible components in Vue.js applications.',
2209+
path: '/blog/building-accessible-vue-components',
2210+
slug: 'building-accessible-vue-components',
2211+
},
2212+
},
2213+
slots: { default: '<p>Blog post content here.</p>' },
2214+
})
2215+
const results = await runAxe(component)
2216+
expect(results.violations).toEqual([])
2217+
})
2218+
})
2219+
2220+
describe('BlueskyComment', () => {
2221+
it('should have no accessibility violations', async () => {
2222+
const component = await mountSuspended(BlueskyComment, {
2223+
props: {
2224+
comment: {
2225+
uri: 'at://did:plc:2gkh62xvzokhlf6li4ol3b3d/app.bsky.feed.post/3mcg7k75fdc2k',
2226+
cid: 'bafyreigincphooxt7zox3blbocf6hnczzv36fkuj2zi5iuzpjgq6gk6pju',
2227+
author: {
2228+
did: 'did:plc:2gkh62xvzokhlf6li4ol3b3d',
2229+
handle: 'patak.dev',
2230+
displayName: 'patak',
2231+
avatar:
2232+
'https://cdn.bsky.app/img/avatar/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreifgzl4e5jqlakd77ajvnilsb5tufsv24h2sxfwmitkzxrh3sk6mhq@jpeg',
2233+
},
2234+
text: 'our kids will need these new stories, thanks for writing this Daniel',
2235+
createdAt: '2026-01-14T23:22:05.257Z',
2236+
likeCount: 13,
2237+
replyCount: 0,
2238+
repostCount: 0,
2239+
replies: [],
2240+
},
2241+
depth: 0,
2242+
},
2243+
})
2244+
const results = await runAxe(component)
2245+
expect(results.violations).toEqual([])
2246+
})
2247+
})
2248+
2249+
describe('BlueskyComments', () => {
2250+
it('should have no accessibility violations', async () => {
2251+
const component = await mountSuspended(BlueskyComments, {
2252+
props: {
2253+
postUri: 'at://did:plc:jbeaa5kdaladzwq3r7f5xgwe/app.bsky.feed.post/3mcg6svsgsm2k',
2254+
},
2255+
})
2256+
const results = await runAxe(component)
2257+
expect(results.violations).toEqual([])
2258+
})
2259+
})
2260+
2261+
describe('BlogPostListCard', () => {
2262+
it('should have no accessibility violations', async () => {
2263+
const component = await mountSuspended(BlogPostListCard, {
2264+
props: {
2265+
authors: [{ name: 'Daniel Roe', blueskyHandle: 'danielroe.dev' }],
2266+
title: 'Building Accessible Vue Components',
2267+
topics: ['accessibility', 'vue'],
2268+
excerpt: 'A guide to building accessible components in Vue.js applications.',
2269+
published: '2024-06-15',
2270+
path: 'building-accessible-vue-components',
2271+
index: 0,
2272+
},
2273+
})
2274+
const results = await runAxe(component)
2275+
expect(results.violations).toEqual([])
2276+
})
2277+
})
2278+
21622279
describe('PackageReplacement', () => {
21632280
it('should have no accessibility violations for native replacement', async () => {
21642281
const component = await mountSuspended(PackageReplacement, {

test/unit/a11y-component-coverage.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const SKIPPED_COMPONENTS: Record<string, string> = {
2525
// OgImage components are server-side rendered images, not interactive UI
2626
'OgImage/Default.vue': 'OG Image component - server-rendered image, not interactive UI',
2727
'OgImage/Package.vue': 'OG Image component - server-rendered image, not interactive UI',
28+
'OgImage/BlogPost.vue': 'OG Image component - server-rendered image, not interactive UI',
2829

2930
// Client-only components with complex dependencies
3031
'Header/AuthModal.client.vue': 'Complex auth modal with navigation - requires full app context',

0 commit comments

Comments
 (0)