From 8a6a6712e7554f110b5ef951f270d88fd010e040 Mon Sep 17 00:00:00 2001
From: Bertrand Yuan <noreply@bertyuan.com>
Date: Thu, 26 Mar 2026 00:02:16 +0800
Subject: add more tests

---
 src/components/json-ld.test.tsx | 66 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)
 create mode 100644 src/components/json-ld.test.tsx

(limited to 'src/components/json-ld.test.tsx')

diff --git a/src/components/json-ld.test.tsx b/src/components/json-ld.test.tsx
new file mode 100644
index 0000000..c96e5c3
--- /dev/null
+++ b/src/components/json-ld.test.tsx
@@ -0,0 +1,66 @@
+import { render } from '@testing-library/react';
+import { describe, expect, test, vi } from 'vitest';
+
+vi.mock('@/app/(main)/layout.config', () => ({
+  title: 'Blog',
+  owner: 'Test Owner',
+}));
+
+vi.mock('@/lib/constants', () => ({
+  baseUrl: new URL('http://localhost:3000'),
+}));
+
+import { PostJsonLd, TagJsonLd } from './json-ld';
+
+describe('json-ld components', () => {
+  test('renders post json-ld with blog posting and breadcrumb graph', () => {
+    const { container } = render(
+      <PostJsonLd
+        post={{
+          id: 1,
+          title: 'Testing Post',
+          slug: 'testing-post',
+          url: '/posts/testing-post',
+          description: 'A post for tests',
+          content: null,
+          image: '/cover.png',
+          author: 'Alice',
+          tags: ['testing'],
+          date: new Date('2025-01-01T00:00:00.000Z'),
+          createdAt: new Date('2025-01-01T00:00:00.000Z'),
+          updatedAt: new Date('2025-01-02T00:00:00.000Z'),
+        }}
+      />,
+    );
+
+    const script = container.querySelector('script[type="application/ld+json"]');
+    expect(script).toBeInTheDocument();
+
+    const payload = JSON.parse(script?.innerHTML ?? '{}');
+    expect(payload['@context']).toBe('https://schema.org');
+    expect(payload['@graph']).toHaveLength(2);
+    expect(payload['@graph'][0]['@type']).toBe('BlogPosting');
+    expect(payload['@graph'][0].mainEntityOfPage['@id']).toBe(
+      'http://localhost:3000/posts/testing-post',
+    );
+  });
+
+  test('returns null when post is not provided', () => {
+    const { container } = render(<PostJsonLd post={null as unknown as any} />);
+    expect(container.firstChild).toBeNull();
+  });
+
+  test('renders tag json-ld with tag-specific breadcrumb item', () => {
+    const { container } = render(<TagJsonLd tag='nextjs' />);
+
+    const script = container.querySelector('script[type="application/ld+json"]');
+    expect(script).toBeInTheDocument();
+
+    const payload = JSON.parse(script?.innerHTML ?? '{}');
+    expect(payload['@graph']).toHaveLength(1);
+    expect(payload['@graph'][0]['@type']).toBe('BreadcrumbList');
+    expect(payload['@graph'][0].itemListElement[2].item).toBe(
+      'http://localhost:3000/tags/nextjs',
+    );
+  });
+});
-- 
cgit v1.2.3


From cd3c4bc89c169616b38bdb7443bb4eb7571b020c Mon Sep 17 00:00:00 2001
From: Bertrand Yuan <noreply@bertyuan.com>
Date: Thu, 26 Mar 2026 00:15:40 +0800
Subject: fix defects in pr #11

---
 src/components/json-ld.test.tsx   |  2 +-
 src/components/json-ld.tsx        |  2 +-
 src/components/ui/button.test.tsx | 15 +++++++++++----
 vite.config.ts                    | 11 ++++++++---
 4 files changed, 21 insertions(+), 9 deletions(-)

(limited to 'src/components/json-ld.test.tsx')

diff --git a/src/components/json-ld.test.tsx b/src/components/json-ld.test.tsx
index c96e5c3..6a81414 100644
--- a/src/components/json-ld.test.tsx
+++ b/src/components/json-ld.test.tsx
@@ -46,7 +46,7 @@ describe('json-ld components', () => {
   });
 
   test('returns null when post is not provided', () => {
-    const { container } = render(<PostJsonLd post={null as unknown as any} />);
+    const { container } = render(<PostJsonLd post={null} />);
     expect(container.firstChild).toBeNull();
   });
 
diff --git a/src/components/json-ld.tsx b/src/components/json-ld.tsx
index 58cb0ba..bbfad33 100644
--- a/src/components/json-ld.tsx
+++ b/src/components/json-ld.tsx
@@ -4,7 +4,7 @@ import { baseUrl } from '@/lib/constants';
 import type { BlogPost } from '@/lib/payload-posts';
 import type { BlogPosting, BreadcrumbList, Graph } from 'schema-dts';
 
-export const PostJsonLd = ({ post }: { post: BlogPost }) => {
+export const PostJsonLd = ({ post }: { post: BlogPost | null | undefined }) => {
   if (!post) {
     return null;
   }
diff --git a/src/components/ui/button.test.tsx b/src/components/ui/button.test.tsx
index 314e9bf..f8bd3a9 100644
--- a/src/components/ui/button.test.tsx
+++ b/src/components/ui/button.test.tsx
@@ -14,9 +14,16 @@ describe('Button', () => {
 
   // Test buttons with different variants
   test('renders button with different variants', () => {
-    const variants = ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'];
+    const variants = [
+      'default',
+      'destructive',
+      'outline',
+      'secondary',
+      'ghost',
+      'link',
+    ] as const;
     variants.forEach((variant) => {
-      render(<Button variant={variant as any}>{variant} Variant</Button>);
+      render(<Button variant={variant}>{variant} Variant</Button>);
       const button = screen.getByText(`${variant} Variant`);
       expect(button).toBeInTheDocument();
     });
@@ -24,9 +31,9 @@ describe('Button', () => {
 
   // Test buttons with different sizes
   test('renders button with different sizes', () => {
-    const sizes = ['default', 'sm', 'lg', 'icon'];
+    const sizes = ['default', 'sm', 'lg', 'icon'] as const;
     sizes.forEach((size) => {
-      render(<Button size={size as any}>{size} Size</Button>);
+      render(<Button size={size}>{size} Size</Button>);
       const button = screen.getByText(`${size} Size`);
       expect(button).toBeInTheDocument();
     });
diff --git a/vite.config.ts b/vite.config.ts
index ec36e8c..507d61a 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -7,9 +7,14 @@ export default defineConfig({
   test: {
     environment: 'jsdom',
     setupFiles: './src/test/setup.ts',
-    include: ['**/*.test.tsx', '**/*.test.ts'],
-    alias: {
-      '@': path.resolve(__dirname, './src'),
+    include: ['**/*.{test,spec}.{ts,tsx,js,jsx}'],
+    coverage: {
+      include: [
+        'src/components/**/*.{ts,tsx}',
+        'src/hooks/**/*.{ts,tsx}',
+        'src/lib/**/*.{ts,tsx}',
+      ],
+      exclude: ['src/**/*.test.{ts,tsx,js,jsx}', 'src/test/**'],
     },
   },
   resolve: {
-- 
cgit v1.2.3

