UNPKG

agent-rules-kit

Version:

CLI tool to bootstrap AI agent rules for multiple IDEs and frameworks. Generates optimized rules for Cursor, VS Code, Claude, and 6+ other AI coding assistants.

230 lines (175 loc) 6.57 kB
--- title: Astro Testing Best Practices description: Guidelines for testing Astro projects effectively tags: [Astro, Testing, Best Practices] always: true --- # Astro Testing Best Practices ## Testing Strategy Testing in Astro projects typically involves multiple testing types and levels: 1. **Unit Testing**: Testing individual components and utility functions 2. **Integration Testing**: Testing how components work together 3. **End-to-End Testing**: Testing complete user flows 4. **Visual Regression Testing**: Ensuring UI consistency ## Testing Setup ### Recommended Testing Tools 1. **Vitest**: For unit and integration testing 2. **Playwright**: For end-to-end testing 3. **Astro Testing Library**: For component testing 4. **Storybook**: For component development and visual testing ### Basic Testing Configuration ```typescript // vitest.config.ts import { defineConfig } from 'vitest/config'; import { svelte } from '@sveltejs/vite-plugin-svelte'; export default defineConfig({ plugins: [svelte()], test: { globals: true, environment: 'jsdom', setupFiles: './tests/setup.js', include: ['src/**/*.{test,spec}.{js,ts,jsx,tsx}'], exclude: ['node_modules', 'dist', '.idea', '.git', '.cache'], }, }); ``` ## Unit Testing ### Testing Components When testing Astro components: 1. **Focus on functionality**: Test what the component does, not implementation details 2. **Mock external dependencies**: Use dependency injection and mocks 3. **Test props and slots**: Ensure the component renders correctly with different inputs Example of testing an Astro component with Vitest and Astro Testing Library: ```typescript // Button.test.ts import { render } from '@testing-library/svelte'; import { describe, it, expect } from 'vitest'; import Button from '../src/components/Button.astro'; describe('Button Component', () => { it('renders with the correct text', async () => { const { getByText } = await render(Button, { props: { text: 'Click me' }, }); expect(getByText('Click me')).toBeTruthy(); }); it('applies the correct class based on variant prop', async () => { const { getByRole } = await render(Button, { props: { text: 'Submit', variant: 'primary' }, }); const button = getByRole('button'); expect(button.classList.contains('btn-primary')).toBe(true); }); }); ``` ### Testing Utilities For utility functions: 1. **Test pure functions extensively**: Cover edge cases 2. **Use parameterized tests**: Test multiple inputs with the same logic 3. **Test error handling**: Ensure proper error responses ```typescript // formatDate.test.ts import { describe, it, expect } from 'vitest'; import { formatDate } from '../src/utils/formatDate'; describe('formatDate utility', () => { it('formats dates correctly', () => { expect(formatDate(new Date('2023-04-15'))).toBe('April 15, 2023'); }); it('handles invalid dates', () => { expect(() => formatDate('not a date')).toThrow(); }); }); ``` ## Integration Testing For integration tests: 1. **Focus on component interactions**: Test how components work together 2. **Mock external API calls**: Use MSW or similar tools 3. **Test user flows**: Ensure components interact correctly based on user actions ```typescript // BlogLayout.test.ts import { render, screen } from '@testing-library/svelte'; import { describe, it, expect, vi } from 'vitest'; import BlogLayout from '../src/layouts/BlogLayout.astro'; import { mockPost } from '../mocks/data'; // Mock fetch calls vi.mock('../src/utils/api', () => ({ fetchRelatedPosts: vi.fn().mockResolvedValue([mockPost]), })); describe('BlogLayout Integration', () => { it('renders blog post with related posts', async () => { await render(BlogLayout, { props: { post: mockPost }, }); // Check main content rendered expect(screen.getByText(mockPost.title)).toBeTruthy(); // Check related posts section expect(screen.getByText('Related Posts')).toBeTruthy(); expect(screen.getByText(mockPost.title)).toBeTruthy(); }); }); ``` ## End-to-End Testing For E2E tests with Playwright: 1. **Test critical user flows**: Focus on key user journeys 2. **Test across browsers**: Use multiple browser contexts 3. **Take screenshots for visual verification**: Capture UI state at key points ```typescript // navigation.spec.ts import { test, expect } from '@playwright/test'; test('navigation works correctly', async ({ page }) => { // Start from the homepage await page.goto('/'); // Navigate to the about page await page.click('text=About'); await expect(page).toHaveURL('/about'); // Check content loaded await expect(page.locator('h1')).toHaveText('About Us'); // Navigate to blog await page.click('text=Blog'); await expect(page).toHaveURL('/blog'); // Check blog posts are loaded await expect(page.locator('.blog-post')).toHaveCount.greaterThan(0); }); ``` ## Testing Content Collections When testing content collections: 1. **Test schema validation**: Ensure content matches defined schemas 2. **Test content queries**: Verify filtering and sorting work correctly 3. **Mock getCollection responses**: For testing components that consume collections ```typescript // contentCollection.test.ts import { describe, it, expect, vi } from 'vitest'; import { getCollection } from 'astro:content'; // Mock the content collection vi.mock('astro:content', () => ({ getCollection: vi.fn().mockResolvedValue([ { id: 'post-1', slug: 'post-1', data: { title: 'Test Post', date: new Date('2023-01-01'), }, }, ]), })); describe('Blog Collection', () => { it('retrieves and sorts blog posts', async () => { const posts = await getCollection('blog'); expect(posts).toHaveLength(1); expect(posts[0].data.title).toBe('Test Post'); }); }); ``` ## Testing Best Practices 1. **Write Tests First**: Use TDD when possible 2. **Keep Tests Independent**: Each test should run in isolation 3. **Use CI/CD Integration**: Run tests automatically on every pull request 4. **Test Accessibility**: Include accessibility checks in your tests 5. **Optimize Test Speed**: Balance coverage with execution time 6. **Regularly Review Test Coverage**: Identify and fill testing gaps ## Common Testing Pitfalls 1. **Testing Implementation Details**: Focus on behavior, not internal logic 2. **Brittle Selectors**: Use data-testid or accessible selectors 3. **Slow Tests**: Mock external dependencies and optimize test runs 4. **Insufficient Mocking**: Properly mock external services and APIs 5. **Ignoring Edge Cases**: Test error states and boundary conditions