8000 GitHub - spences10/sveltest
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

spences10/sveltest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Sveltest

CI/CD E2E Tests Svelte 5 SvelteKit TypeScript Vitest Playwright TailwindCSS License: MIT pnpm

A comprehensive example project demonstrating vitest-browser-svelte testing patterns for modern Svelte 5 applications. Built over a weekend as a companion piece to my blog post: Migrating from @testing-library/svelte to vitest-browser-svelte.

🎯 What is Sveltest?

Sveltest showcases real-world testing patterns using vitest-browser-svelte - the modern testing solution for Svelte applications. This project demonstrates my opinionated approach to testing with:

  • Client-side component testing with real browser environments
  • Server-side testing for SvelteKit API routes and hooks
  • SSR testing for server-side rendering validation
  • Full-stack integration patterns for modern web applications

πŸ”„ Client-Server Alignment Strategy

The Problem: Server unit tests with heavy mocking can pass while production breaks due to client-server mismatches. Forms send data in one format, servers expect another, and mocked tests miss the disconnect.

My Solution: This project demonstrates a multi-layer testing approach with minimal mocking:

  • Shared validation logic between client and server prevents contract mismatches
  • Real FormData/Request objects in server tests (only external services like databases are mocked)
  • TypeScript contracts ensure data structures align between client and server
  • E2E tests provide the final safety net to catch any integration gaps

This methodology gives you fast unit test feedback while maintaining confidence that client and server actually work together in production.

πŸš€ Features Demonstrated

Component Testing (Client-Side)

  • Button Component: Variants, sizes, loading states, accessibility
  • Input Component: Validation, error states, form integration
  • Modal Component: Focus management, keyboard navigation, portal rendering
  • Card Component: Slot testing, conditional rendering, click handlers
  • LoginForm Component: Complex form interactions, async operations
  • TodoManager Component: State management, CRUD operations, list interactions
  • Calculator Component: Interactive calculations, input validation
  • Nav Component: Navigation, responsive design, accessibility

Server-Side Testing

  • API Routes: Authentication, authorization, error handling
  • Server Hooks: Security headers, middleware, request processing
  • Form Actions: CRUD operations, validation, user feedback
  • Utility Functions: Validation logic, data processing

SSR Testing

  • Component SSR: Server-side rendering validation
  • Layout SSR: Navigation, responsive design, meta tags
  • Page SSR: Multi-page server-side rendering
  • Hydration Testing: Client-server state synchronization

πŸ› οΈ Technology Stack

  • Framework: Svelte 5 with SvelteKit
  • Testing: vitest-browser-svelte with Playwright
  • Styling: TailwindCSS + DaisyUI
  • Language: TypeScript
  • Package Manager: pnpm

πŸ“¦ Installation

# Clone the repository
git clone https://github.com/spences10/sveltest.git
cd sveltest

# Install dependencies
pnpm install

# Run the development server
pnpm dev

# Run tests
pnpm test:unit

# Run specific test suites
pnpm test:client    # Component tests in browser
pnpm test:server    # Server-side tests
pnpm test:ssr       # SSR tests

πŸ§ͺ Testing Patterns

Client-Side Component Testing

import { render } from 'vitest-browser-svelte';
import { page } from '@vitest/browser/context';
import { expect, test } from 'vitest';
import Button from './button.svelte';

test('button renders with correct variant', async () => {
	render(Button, { variant: 'primary', children: 'Click me' });

	const button = page.getByRole('button', { name: 'Click me' });
	await expect.element(button).toBeInTheDocument();
	await expect.element(button).toHaveClass('btn-primary');
});

Server-Side API Testing

import { describe, it, expect } from 'vitest';
import { GET } from './+server.ts';

describe('API Route', () => {
	it('should authenticate valid requests', async () => {
		const request = new Request('http://localhost/api/secure-data', {
			headers: { Authorization: 'Bearer valid-token' },
		});

		const response = await GET({ request });
		expect(response.status).toBe(200);
	});
});

SSR Testing

import { render } from 'svelte/server';
import { expect, test } from 'vitest';
import Layout from './+layout.svelte';

test('layout renders navigation on server', () => {
	const { html } = render(Layout);

	expect(html).toContain('<nav');
	expect(html).toContain('aria-label="Main navigation"');
});

πŸ“ Project Structure

src/
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ components/           # Reusable components with tests
β”‚   β”‚   β”œβ”€β”€ button.svelte
β”‚   β”‚   β”œβ”€β”€ button.svelte.test.ts
β”‚   β”‚   β”œβ”€β”€ button.ssr.test.ts
β”‚   β”‚   β”œβ”€β”€ input.svelte
β”‚   β”‚   β”œβ”€β”€ input.svelte.test.ts
β”‚   β”‚   β”œβ”€β”€ modal.svelte
β”‚   β”‚   β”œβ”€β”€ modal.svelte.test.ts
β”‚   β”‚   β”œβ”€β”€ card.svelte
β”‚   β”‚   β”œβ”€β”€ card.svelte.test.ts
β”‚   β”‚   β”œβ”€β”€ login-form.svelte
β”‚   β”‚   β”œβ”€β”€ login-form.svelte.test.ts
β”‚   β”‚   β”œβ”€β”€ todo-manager.svelte
β”‚   β”‚   β”œβ”€β”€ todo-manager.svelte.test.ts
β”‚   β”‚   β”œβ”€β”€ todo-manager.ssr.test.ts
β”‚   β”‚   β”œβ”€β”€ calculator.svelte
β”‚   β”‚   β”œβ”€β”€ calculator.svelte.test.ts
β”‚   β”‚   β”œβ”€β”€ calculator.ssr.test.ts
β”‚   β”‚   β”œβ”€β”€ nav.svelte
β”‚   β”‚   β”œβ”€β”€ nav.svelte.test.ts
β”‚   β”‚   └── nav.ssr.test.ts
β”‚   β”œβ”€β”€ utils/               # Utility functions with tests
β”‚   β”‚   β”œβ”€β”€ validation.ts
β”‚   β”‚   └── validation.test.ts
β”‚   β”œβ”€β”€ state/               # State management
β”‚   └── icons/               # Icon components
β”œβ”€β”€ routes/
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”œβ”€β”€ secure-data/
β”‚   β”‚   β”‚   β”œβ”€β”€ +server.ts
β”‚   β”‚   β”‚   └── server.test.ts
β”‚   β”‚   β”œβ”€β”€ health/
β”‚   β”‚   └── csp-report/
β”‚   β”‚       └── server.test.ts
β”‚   β”œβ”€β”€ components/          # Component showcase pages
β”‚   β”œβ”€β”€ docs/                # Documentation pages
β”‚   β”œβ”€β”€ examples/            # Example pages
β”‚   β”œβ”€β”€ todos/               # Todo application
β”‚   β”‚   └── page.server.test.ts
β”‚   β”œβ”€β”€ +layout.svelte
β”‚   β”œβ”€β”€ layout.ssr.test.ts
β”‚   β”œβ”€β”€ +page.svelte
β”‚   β”œβ”€β”€ page.svelte.test.ts
β”‚   └── page.ssr.test.ts
β”œβ”€β”€ hooks.server.ts
└── hooks.server.test.ts

πŸ€– AI Assistant Rules for Teams

One of the key outcomes of this project was creating comprehensive AI assistant rules that help teams adopt this testing methodology more easily. I'm onboarding my team to use this approach!

Cursor Rules (.cursor/rules/testing.mdc)

  • Comprehensive testing patterns for Cursor AI
  • Complete vitest-browser-svelte best practices
  • Code style enforcement (snake_case, kebab-case conventions)
  • Common error solutions and troubleshooting

Windsurf Rules (.windsurf/rules/testing.md)

  • Adapted for Windsurf's modern rule system
  • Trigger-based activation for test files
  • Same comprehensive patterns as Cursor rules
  • Team-ready configuration

These rules files contain:

  • Foundation First testing approach guidelines
  • Complete vitest-browser-svelte patterns and anti-patterns
  • Svelte 5 runes testing strategies
  • SSR testing methodologies
  • Form validation lifecycle patterns
  • Quick reference DO's and DON'Ts

For Teams: Copy these rule files to your projects to ensure consistent testing patterns across your team. The AI assistants will automatically follow the established patterns when writing or reviewing tests.

🎨 Testing Conventions

My Opinionated Naming Conventions

I use specific naming conventions to help me identify code I've written versus external libraries:

  • Files: kebab-case (e.g., login-form.svelte.test.ts)
  • Variables & Functions: snake_case (e.g., submit_button, error_message) - This helps me instantly recognize my own code
  • Test IDs: kebab-case (e.g., data-testid="submit-button")
  • Interfaces: TitleCase (following TypeScript conventions)

Test Organization

  • Descriptive test groups with describe()
  • Comprehensive edge case coverage
  • Real-world interaction patterns
  • Accessibility testing integration

πŸ“Š Test Coverage

  • 32 test files across client, server, and SSR
  • 576 passing tests with comprehensive component coverage
  • Full server-side testing for API routes and hooks
  • SSR validation for critical rendering paths

πŸš€ Migration from @testing-library/svelte

This project was inspired by my experience migrating from @testing-library/svelte to vitest-browser-svelte. Read the full story in my blog post: Migrating from @testing-library/svelte to vitest-browser-svelte.

You can also check the comprehensive Migration Guide which documents:

  • Step-by-step migration process
  • Before/after code examples
  • Common patterns and transformations
  • Performance improvements
  • Troubleshooting guide

🀝 Contributing

This project serves as a reference implementation of my testing methodology. Feel free to:

  • Open issues for questions about testing patterns
  • Submit PRs to improve examples
  • Share your own testing patterns
  • Report bugs or suggest improvements

Keep in mind that the conventions used here are opinionated and reflect my personal coding style preferences.

πŸ“„ License

MIT License - see LICENSE for details.

πŸ”— Related Resources


Sveltest - My comprehensive vitest-browser-svelte testing patterns for modern Svelte applications.

About

Resources

License

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  
0