From 4b34896ff224ece6ff9e76bfad5182da219c6887 Mon Sep 17 00:00:00 2001 From: Jonathan Yeong Date: Thu, 12 Feb 2026 21:06:27 +0900 Subject: [PATCH 1/2] chore: remove unused package --- package.json | 1 - pnpm-lock.yaml | 4 +- test/nuxt/a11y.spec.ts | 130 ++++++++++++++++++++++ test/unit/a11y-component-coverage.spec.ts | 1 + 4 files changed, 132 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 1fe8f1d38..0867dffb2 100644 --- a/package.json +++ b/package.json @@ -122,7 +122,6 @@ "@types/sanitize-html": "2.16.0", "@types/semver": "7.7.1", "@types/validate-npm-package-name": "4.0.2", - "@valibot/to-json-schema": "^1.5.0", "@vitest/browser-playwright": "4.0.18", "@vitest/coverage-v8": "4.0.18", "@vue/test-utils": "2.4.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b0f32c2cc..c1a467d65 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -237,9 +237,6 @@ importers: '@types/validate-npm-package-name': specifier: 4.0.2 version: 4.0.2 - '@valibot/to-json-schema': - specifier: ^1.5.0 - version: 1.5.0(valibot@1.2.0(typescript@5.9.3)) '@vitest/browser-playwright': specifier: 4.0.18 version: 4.0.18(@voidzero-dev/vite-plus-test@0.0.0-833c515fa25cef20905a7f9affb156dfa6f151ab(@types/node@24.10.9)(esbuild@0.27.3)(happy-dom@20.4.0)(jiti@2.6.1)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2))(playwright@1.58.1)(vite@7.3.1(@types/node@24.10.9)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.46.0)(yaml@2.8.2)) @@ -14279,6 +14276,7 @@ snapshots: '@valibot/to-json-schema@1.5.0(valibot@1.2.0(typescript@5.9.3))': dependencies: valibot: 1.2.0(typescript@5.9.3) + optional: true '@vercel/kv@3.0.0': dependencies: diff --git a/test/nuxt/a11y.spec.ts b/test/nuxt/a11y.spec.ts index b67756378..c30d6ea0d 100644 --- a/test/nuxt/a11y.spec.ts +++ b/test/nuxt/a11y.spec.ts @@ -114,6 +114,13 @@ import { AppFooter, AppHeader, AppLogo, + AuthorAvatar, + AuthorList, + BlogPostListCard, + BlogPostWrapper, + BlueskyComment, + BlueskyComments, + EmbeddableBlueskyPost, BaseCard, BuildEnvironment, ButtonBase, @@ -2491,6 +2498,129 @@ describe('component accessibility audits', () => { expect(results.violations).toEqual([]) }) }) + + describe('AuthorAvatar', () => { + it('should have no accessibility violations with fallback text', async () => { + const component = await mountSuspended(AuthorAvatar, { + props: { + author: { + name: 'Daniel Roe', + blueskyHandle: 'danielroe.dev', + avatar: null, + profileUrl: 'https://bsky.app/profile/danielroe.dev', + }, + }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + }) + + describe('AuthorList', () => { + it('should have no accessibility violations', async () => { + const component = await mountSuspended(AuthorList, { + props: { + authors: [ + { name: 'Daniel Roe', blueskyHandle: 'danielroe.dev' }, + { name: 'Salma Alam-Naylor' }, + ], + }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + }) + + describe('BlogPostWrapper', () => { + it('should have no accessibility violations', async () => { + const component = await mountSuspended(BlogPostWrapper, { + props: { + frontmatter: { + authors: [{ name: 'Daniel Roe', blueskyHandle: 'danielroe.dev' }], + title: 'Building Accessible Vue Components', + date: '2024-06-15', + description: 'A guide to building accessible components in Vue.js applications.', + path: '/blog/building-accessible-vue-components', + slug: 'building-accessible-vue-components', + }, + }, + slots: { default: '

Blog post content here.

' }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + }) + + describe('BlueskyComment', () => { + it('should have no accessibility violations', async () => { + const component = await mountSuspended(BlueskyComment, { + props: { + comment: { + uri: 'at://did:plc:2gkh62xvzokhlf6li4ol3b3d/app.bsky.feed.post/3mcg7k75fdc2k', + cid: 'bafyreigincphooxt7zox3blbocf6hnczzv36fkuj2zi5iuzpjgq6gk6pju', + author: { + did: 'did:plc:2gkh62xvzokhlf6li4ol3b3d', + handle: 'patak.dev', + displayName: 'patak', + avatar: + 'https://cdn.bsky.app/img/avatar/plain/did:plc:2gkh62xvzokhlf6li4ol3b3d/bafkreifgzl4e5jqlakd77ajvnilsb5tufsv24h2sxfwmitkzxrh3sk6mhq@jpeg', + }, + text: 'our kids will need these new stories, thanks for writing this Daniel', + createdAt: '2026-01-14T23:22:05.257Z', + likeCount: 13, + replyCount: 0, + repostCount: 0, + replies: [], + }, + depth: 0, + }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + }) + + describe('BlueskyComments', () => { + it('should have no accessibility violations', async () => { + const component = await mountSuspended(BlueskyComments, { + props: { + postUri: 'at://did:plc:jbeaa5kdaladzwq3r7f5xgwe/app.bsky.feed.post/3mcg6svsgsm2k', + }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + }) + + describe('EmbeddableBlueskyPost', () => { + it('should have no accessibility violations', async () => { + const component = await mountSuspended(EmbeddableBlueskyPost, { + props: { + url: 'https://bsky.app/profile/patak.dev/post/3mcg7k75fdc2k', + }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + }) + + describe('BlogPostListCard', () => { + it('should have no accessibility violations', async () => { + const component = await mountSuspended(BlogPostListCard, { + props: { + authors: [{ name: 'Daniel Roe', blueskyHandle: 'danielroe.dev' }], + title: 'Building Accessible Vue Components', + topics: ['accessibility', 'vue'], + excerpt: 'A guide to building accessible components in Vue.js applications.', + published: '2024-06-15', + path: 'building-accessible-vue-components', + index: 0, + }, + }) + const results = await runAxe(component) + expect(results.violations).toEqual([]) + }) + }) }) function applyTheme(colorMode: string, bgTheme: string | null) { diff --git a/test/unit/a11y-component-coverage.spec.ts b/test/unit/a11y-component-coverage.spec.ts index 0f18a000e..d68832e2f 100644 --- a/test/unit/a11y-component-coverage.spec.ts +++ b/test/unit/a11y-component-coverage.spec.ts @@ -25,6 +25,7 @@ const SKIPPED_COMPONENTS: Record = { // OgImage components are server-side rendered images, not interactive UI 'OgImage/Default.vue': 'OG Image component - server-rendered image, not interactive UI', 'OgImage/Package.vue': 'OG Image component - server-rendered image, not interactive UI', + 'OgImage/BlogPost.vue': 'OG Image component - server-rendered image, not interactive UI', // Client-only components with complex dependencies 'Header/AuthModal.client.vue': 'Complex auth modal with navigation - requires full app context', From 68d8e7fa801df22bdbc42a46ce2b9815efb058ad Mon Sep 17 00:00:00 2001 From: Jonathan Yeong Date: Thu, 12 Feb 2026 21:07:08 +0900 Subject: [PATCH 2/2] chore: fix type error and unused router variable --- app/components/EmbeddableBlueskyPost.vue | 2 +- app/pages/blog/index.vue | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/components/EmbeddableBlueskyPost.vue b/app/components/EmbeddableBlueskyPost.vue index 2cd6b65ec..af6f1de29 100644 --- a/app/components/EmbeddableBlueskyPost.vue +++ b/app/components/EmbeddableBlueskyPost.vue @@ -13,7 +13,7 @@ const iframeHeight = ref(300) const { data: embedData, status } = useLazyAsyncData( `bluesky-embed-${embeddedId}`, () => - $fetch('/api/atproto/bluesky-oembed', { + $fetch('/api/atproto/bluesky-oembed', { query: { url, colorMode: 'system' }, }), { diff --git a/app/pages/blog/index.vue b/app/pages/blog/index.vue index 3bed70129..c3208a529 100644 --- a/app/pages/blog/index.vue +++ b/app/pages/blog/index.vue @@ -1,6 +1,4 @@