strategy change to TDD
This commit is contained in:
100
openspec/templates/PestFeatureTest.php
Normal file
100
openspec/templates/PestFeatureTest.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use App\Models\User;
|
||||
|
||||
uses()->group('{{capability}}');
|
||||
|
||||
/*
|
||||
* Test Template for Pest Feature Tests
|
||||
*
|
||||
* Copy this file and replace:
|
||||
* - {{capability}} with the capability name (e.g., 'authentication')
|
||||
* - {{scenario_description}} with the spec scenario description
|
||||
*
|
||||
* Mark pending tests with ->todo() during Red Phase
|
||||
* Remove ->todo() and implement during Green Phase
|
||||
*/
|
||||
|
||||
describe('{{capability}} API', function () {
|
||||
|
||||
// Use RefreshDatabase trait for clean state
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
// Setup code runs before each test
|
||||
// e.g., create test user, authenticate, etc.
|
||||
});
|
||||
|
||||
/*
|
||||
* Scenario: {{scenario_description}}
|
||||
*
|
||||
* Spec Reference: specs/{{capability}}/spec.md
|
||||
* Scenario: {{scenario_number}}
|
||||
*/
|
||||
it('{{scenario_description}}', function () {
|
||||
// Arrange (GIVEN)
|
||||
// Set up the initial state
|
||||
|
||||
// Act (WHEN)
|
||||
// Perform the action
|
||||
$response = $this->postJson('/api/{{endpoint}}', [
|
||||
// Request data
|
||||
]);
|
||||
|
||||
// Assert (THEN)
|
||||
// Verify the expected outcome
|
||||
$response->assertStatus(200)
|
||||
->assertJson([
|
||||
// Expected response structure
|
||||
]);
|
||||
})->todo(); // Remove ->todo() when implementing
|
||||
|
||||
/*
|
||||
* Example: Error scenario
|
||||
*/
|
||||
it('returns error when {{error_condition}}', function () {
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
$response = $this->postJson('/api/{{endpoint}}', [
|
||||
'invalid' => 'data'
|
||||
]);
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(422)
|
||||
->assertJsonValidationErrors(['field_name']);
|
||||
})->todo();
|
||||
|
||||
/*
|
||||
* Example: Authorization scenario
|
||||
*/
|
||||
it('returns 403 when user lacks permission', function () {
|
||||
// Arrange: Create user without permission
|
||||
$user = User::factory()->create(['role' => 'developer']);
|
||||
|
||||
// Act
|
||||
$response = $this->actingAs($user)
|
||||
->postJson('/api/{{admin_endpoint}}');
|
||||
|
||||
// Assert
|
||||
$response->assertStatus(403);
|
||||
})->todo();
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
* Helper functions specific to this capability
|
||||
*/
|
||||
function create{{model}}(array $attributes = []): {{model}}
|
||||
{
|
||||
return {{model}}::factory()->create($attributes);
|
||||
}
|
||||
|
||||
function authenticateUser(string $role = 'manager'): User
|
||||
{
|
||||
$user = User::factory()->create(['role' => $role]);
|
||||
|
||||
// Return authenticated user or token
|
||||
return $user;
|
||||
}
|
||||
92
openspec/templates/PestUnitTest.php
Normal file
92
openspec/templates/PestUnitTest.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
use App\Services\{{service}};
|
||||
|
||||
uses()->group('{{capability}}', 'unit');
|
||||
|
||||
/*
|
||||
* Test Template for Pest Unit Tests
|
||||
*
|
||||
* Copy this file and replace:
|
||||
* - {{capability}} with the capability name
|
||||
* - {{service}} with the class being tested
|
||||
*
|
||||
* Mark pending tests with ->todo() during Red Phase
|
||||
* Remove ->todo() and implement during Green Phase
|
||||
*/
|
||||
|
||||
describe('{{service}}', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
$this->service = new {{service}}();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: {{method_description}}
|
||||
*
|
||||
* Tests the core logic of {{method_name}}
|
||||
*/
|
||||
it('{{method_description}}', function () {
|
||||
// Arrange
|
||||
$input = [
|
||||
// Test input data
|
||||
];
|
||||
|
||||
$expected = [
|
||||
// Expected output
|
||||
];
|
||||
|
||||
// Act
|
||||
$result = $this->service->{{method_name}}($input);
|
||||
|
||||
// Assert
|
||||
expect($result)->toBe($expected);
|
||||
})->todo();
|
||||
|
||||
/*
|
||||
* Test: Edge case handling
|
||||
*/
|
||||
it('handles {{edge_case}} gracefully', function () {
|
||||
// Arrange
|
||||
$edgeCaseInput = null;
|
||||
|
||||
// Act & Assert
|
||||
expect(fn () => $this->service->{{method_name}}($edgeCaseInput))
|
||||
->toThrow(\InvalidArgumentException::class);
|
||||
})->todo();
|
||||
|
||||
/*
|
||||
* Test: Calculation accuracy
|
||||
*/
|
||||
it('calculates {{calculation}} correctly', function () {
|
||||
// Arrange
|
||||
$a = 10;
|
||||
$b = 20;
|
||||
|
||||
// Act
|
||||
$result = $this->service->calculate($a, $b);
|
||||
|
||||
// Assert
|
||||
expect($result)->toBe(30);
|
||||
})->todo();
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
* Data providers for parameterized tests
|
||||
*/
|
||||
dataset('valid_inputs', function () {
|
||||
return [
|
||||
'case 1' => [['input' => 'value1'], 'expected1'],
|
||||
'case 2' => [['input' => 'value2'], 'expected2'],
|
||||
'case 3' => [['input' => 'value3'], 'expected3'],
|
||||
];
|
||||
});
|
||||
|
||||
/*
|
||||
* Example parameterized test
|
||||
*/
|
||||
it('processes valid inputs correctly', function ($input, $expected) {
|
||||
$result = $this->service->process($input);
|
||||
expect($result)->toBe($expected);
|
||||
})->with('valid_inputs')->todo();
|
||||
137
openspec/templates/PlaywrightE2ETest.spec.ts
Normal file
137
openspec/templates/PlaywrightE2ETest.spec.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
/*
|
||||
* Test Template for Playwright E2E Tests
|
||||
*
|
||||
* Copy this file and replace:
|
||||
* - {{capability}} with the capability name (e.g., 'authentication')
|
||||
* - {{scenario_description}} with the spec scenario description
|
||||
*
|
||||
* Mark pending tests with test.fixme() during Red Phase
|
||||
* Remove test.fixme() and implement during Green Phase
|
||||
*/
|
||||
|
||||
test.describe('{{capability}} Flow', () => {
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Setup: Navigate to base URL, login, etc.
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
/*
|
||||
* Scenario: {{scenario_description}}
|
||||
*
|
||||
* Spec Reference: specs/{{capability}}/spec.md
|
||||
* Scenario: {{scenario_number}}
|
||||
*/
|
||||
test('{{scenario_description}}', async ({ page }) => {
|
||||
// Arrange (GIVEN)
|
||||
// Set up initial state
|
||||
await page.goto('/{{route}}');
|
||||
|
||||
// Act (WHEN)
|
||||
// Perform user actions
|
||||
await page.fill('[name="email"]', 'test@example.com');
|
||||
await page.fill('[name="password"]', 'password');
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Assert (THEN)
|
||||
// Verify expected outcome
|
||||
await expect(page).toHaveURL('/dashboard');
|
||||
await expect(page.locator('[data-testid="success-message"]')).toBeVisible();
|
||||
await expect(page.locator('[data-testid="user-name"]')).toContainText('Test User');
|
||||
});
|
||||
|
||||
/*
|
||||
* Example: Error scenario
|
||||
*/
|
||||
test('displays error when {{error_condition}}', async ({ page }) => {
|
||||
// Arrange
|
||||
await page.goto('/{{route}}');
|
||||
|
||||
// Act
|
||||
await page.fill('[name="email"]', 'invalid@example.com');
|
||||
await page.fill('[name="password"]', 'wrongpassword');
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Assert
|
||||
await expect(page.locator('[data-testid="error-message"]')).toBeVisible();
|
||||
await expect(page.locator('[data-testid="error-message"]')).toContainText('Invalid credentials');
|
||||
await expect(page).toHaveURL('/{{route}}');
|
||||
});
|
||||
|
||||
/*
|
||||
* Example: Form validation
|
||||
*/
|
||||
test('validates required fields', async ({ page }) => {
|
||||
// Arrange
|
||||
await page.goto('/{{route}}');
|
||||
|
||||
// Act
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Assert
|
||||
await expect(page.locator('[data-testid="error-email"]')).toContainText('Email is required');
|
||||
await expect(page.locator('[data-testid="error-password"]')).toContainText('Password is required');
|
||||
});
|
||||
|
||||
/*
|
||||
* Example: CRUD operation
|
||||
*/
|
||||
test('completes full {{resource}} CRUD flow', async ({ page }) => {
|
||||
// Create
|
||||
await page.goto('/{{resource}}/new');
|
||||
await page.fill('[name="name"]', 'Test {{resource}}');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page.locator('[data-testid="success-message"]')).toBeVisible();
|
||||
|
||||
// Read
|
||||
await page.goto('/{{resource}}');
|
||||
await expect(page.locator('text=Test {{resource}}')).toBeVisible();
|
||||
|
||||
// Update
|
||||
await page.click('[data-testid="edit-{{resource}}"]');
|
||||
await page.fill('[name="name"]', 'Updated {{resource}}');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page.locator('[data-testid="success-message"]')).toBeVisible();
|
||||
|
||||
// Delete
|
||||
await page.click('[data-testid="delete-{{resource}}"]');
|
||||
await page.click('[data-testid="confirm-delete"]');
|
||||
await expect(page.locator('text=Updated {{resource}}')).not.toBeVisible();
|
||||
});
|
||||
|
||||
/*
|
||||
* Example: RBAC test
|
||||
*/
|
||||
test('restricts access based on role', async ({ page }) => {
|
||||
// Login as developer (limited permissions)
|
||||
await loginAs(page, 'developer');
|
||||
|
||||
// Try to access admin page
|
||||
await page.goto('/admin/{{resource}}');
|
||||
|
||||
// Should be redirected or show access denied
|
||||
await expect(page.locator('[data-testid="access-denied"]')).toBeVisible();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
*/
|
||||
async function loginAs(page, role: string) {
|
||||
await page.goto('/login');
|
||||
await page.fill('[name="email"]', `${role}@example.com`);
|
||||
await page.fill('[name="password"]', 'password');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page).toHaveURL('/dashboard');
|
||||
}
|
||||
|
||||
async function create{{model}}(page, data: object) {
|
||||
await page.goto('/{{resource}}/new');
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
await page.fill(`[name="${key}"]`, value);
|
||||
}
|
||||
await page.click('button[type="submit"]');
|
||||
}
|
||||
174
openspec/templates/VitestComponentTest.test.ts
Normal file
174
openspec/templates/VitestComponentTest.test.ts
Normal file
@@ -0,0 +1,174 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte';
|
||||
import {{component}} from './{{component}}.svelte';
|
||||
|
||||
/*
|
||||
* Test Template for Vitest Component Tests
|
||||
*
|
||||
* Copy this file and replace:
|
||||
* - {{component}} with the Svelte component name
|
||||
* - {{capability}} with the capability name
|
||||
*
|
||||
* Mark pending tests with test.skip() during Red Phase
|
||||
* Remove .skip and implement during Green Phase
|
||||
*/
|
||||
|
||||
describe('{{component}}', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset mocks and state
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Component renders correctly
|
||||
*/
|
||||
it.skip('renders with default props', () => {
|
||||
const { container } = render({{component}});
|
||||
|
||||
expect(container.querySelector('[data-testid="{{component}}"]')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Component displays data correctly
|
||||
*/
|
||||
it.skip('displays {{data_type}} data', () => {
|
||||
const mockData = {
|
||||
id: '123',
|
||||
name: 'Test Name',
|
||||
value: 100
|
||||
};
|
||||
|
||||
render({{component}}, { props: { data: mockData } });
|
||||
|
||||
expect(screen.getByText('Test Name')).toBeInTheDocument();
|
||||
expect(screen.getByText('100')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: User interaction
|
||||
*/
|
||||
it.skip('handles {{action}} click', async () => {
|
||||
const mockHandler = vi.fn();
|
||||
|
||||
render({{component}}, {
|
||||
props: {
|
||||
on{{action}}: mockHandler
|
||||
}
|
||||
});
|
||||
|
||||
const button = screen.getByTestId('{{action}}-button');
|
||||
await fireEvent.click(button);
|
||||
|
||||
expect(mockHandler).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Form submission
|
||||
*/
|
||||
it.skip('submits form with correct data', async () => {
|
||||
const mockSubmit = vi.fn();
|
||||
|
||||
render({{component}}, {
|
||||
props: {
|
||||
onSubmit: mockSubmit
|
||||
}
|
||||
});
|
||||
|
||||
// Fill form
|
||||
await fireEvent.input(screen.getByLabelText('Name'), {
|
||||
target: { value: 'Test Name' }
|
||||
});
|
||||
|
||||
await fireEvent.input(screen.getByLabelText('Email'), {
|
||||
target: { value: 'test@example.com' }
|
||||
});
|
||||
|
||||
// Submit
|
||||
await fireEvent.click(screen.getByText('Submit'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockSubmit).toHaveBeenCalledWith({
|
||||
name: 'Test Name',
|
||||
email: 'test@example.com'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Validation errors
|
||||
*/
|
||||
it.skip('displays validation errors', async () => {
|
||||
render({{component}});
|
||||
|
||||
// Submit empty form
|
||||
await fireEvent.click(screen.getByText('Submit'));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Name is required')).toBeInTheDocument();
|
||||
expect(screen.getByText('Email is required')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Loading state
|
||||
*/
|
||||
it.skip('shows loading state', () => {
|
||||
render({{component}}, {
|
||||
props: {
|
||||
loading: true
|
||||
}
|
||||
});
|
||||
|
||||
expect(screen.getByTestId('loading-spinner')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Empty state
|
||||
*/
|
||||
it.skip('displays empty state when no data', () => {
|
||||
render({{component}}, {
|
||||
props: {
|
||||
data: []
|
||||
}
|
||||
});
|
||||
|
||||
expect(screen.getByText('No data available')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Error state
|
||||
*/
|
||||
it.skip('displays error message', () => {
|
||||
render({{component}}, {
|
||||
props: {
|
||||
error: 'Failed to load data'
|
||||
}
|
||||
});
|
||||
|
||||
expect(screen.getByText('Failed to load data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Accessibility
|
||||
*/
|
||||
it.skip('has accessible attributes', () => {
|
||||
render({{component}});
|
||||
|
||||
const element = screen.getByRole('button');
|
||||
expect(element).toHaveAttribute('aria-label');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
*/
|
||||
function createMock{{model}}(overrides = {}) {
|
||||
return {
|
||||
id: '123',
|
||||
name: 'Test {{model}}',
|
||||
createdAt: new Date().toISOString(),
|
||||
...overrides
|
||||
};
|
||||
}
|
||||
205
openspec/templates/VitestUnitTest.test.ts
Normal file
205
openspec/templates/VitestUnitTest.test.ts
Normal file
@@ -0,0 +1,205 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
/*
|
||||
* Test Template for Vitest Unit Tests (Utilities, Stores, API Clients)
|
||||
*
|
||||
* Copy this file and replace:
|
||||
* - {{module}} with the module name
|
||||
* - {{capability}} with the capability name
|
||||
*
|
||||
* Mark pending tests with test.skip() during Red Phase
|
||||
* Remove .skip and implement during Green Phase
|
||||
*/
|
||||
|
||||
describe('{{module}}', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset state before each test
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Core functionality
|
||||
*/
|
||||
it.skip('{{functionality_description}}', () => {
|
||||
// Arrange
|
||||
const input = {
|
||||
// Test input
|
||||
};
|
||||
|
||||
const expected = {
|
||||
// Expected output
|
||||
};
|
||||
|
||||
// Act
|
||||
const result = {{module}}.{{method}}(input);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Edge cases
|
||||
*/
|
||||
it.skip('handles {{edge_case}}', () => {
|
||||
// Arrange
|
||||
const edgeCaseInput = null;
|
||||
|
||||
// Act & Assert
|
||||
expect(() => {{module}}.{{method}}(edgeCaseInput))
|
||||
.toThrow('Invalid input');
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Async operations
|
||||
*/
|
||||
it.skip('{{async_description}}', async () => {
|
||||
// Arrange
|
||||
const mockResponse = { data: 'test' };
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: () => Promise.resolve(mockResponse)
|
||||
});
|
||||
|
||||
// Act
|
||||
const result = await {{module}}.{{async_method}}();
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual(mockResponse);
|
||||
expect(fetch).toHaveBeenCalledWith('/api/{{endpoint}}');
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Error handling
|
||||
*/
|
||||
it.skip('handles API errors', async () => {
|
||||
// Arrange
|
||||
global.fetch = vi.fn().mockResolvedValue({
|
||||
ok: false,
|
||||
status: 500,
|
||||
json: () => Promise.resolve({ message: 'Server error' })
|
||||
});
|
||||
|
||||
// Act & Assert
|
||||
await expect({{module}}.{{async_method}}())
|
||||
.rejects.toThrow('Server error');
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Store behavior (if testing Svelte stores)
|
||||
*/
|
||||
it.skip('updates store value', () => {
|
||||
// Arrange
|
||||
const store = {{module}}.{{store_name}};
|
||||
|
||||
// Act
|
||||
store.set({ value: 'new value' });
|
||||
|
||||
// Assert
|
||||
let value;
|
||||
store.subscribe(v => { value = v; })();
|
||||
expect(value).toEqual({ value: 'new value' });
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Store derived values
|
||||
*/
|
||||
it.skip('computes derived value correctly', () => {
|
||||
// Arrange
|
||||
const store = {{module}}.{{store_name}};
|
||||
store.set({ items: [1, 2, 3] });
|
||||
|
||||
// Act
|
||||
let derivedValue;
|
||||
{{module}}.{{derived_store}}.subscribe(v => { derivedValue = v; })();
|
||||
|
||||
// Assert
|
||||
expect(derivedValue).toBe(6); // sum of items
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Validation logic
|
||||
*/
|
||||
it.skip('validates {{field}} correctly', () => {
|
||||
// Valid cases
|
||||
expect({{module}}.validate{{field}}('valid')).toBe(true);
|
||||
expect({{module}}.validate{{field}}('another-valid')).toBe(true);
|
||||
|
||||
// Invalid cases
|
||||
expect({{module}}.validate{{field}}('')).toBe(false);
|
||||
expect({{module}}.validate{{field}}(null)).toBe(false);
|
||||
expect({{module}}.validate{{field}}('invalid!')).toBe(false);
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Calculation accuracy
|
||||
*/
|
||||
it.skip('calculates {{calculation}} correctly', () => {
|
||||
expect({{module}}.calculate(10, 20)).toBe(30);
|
||||
expect({{module}}.calculate(0, 0)).toBe(0);
|
||||
expect({{module}}.calculate(-5, 5)).toBe(0);
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Formatting functions
|
||||
*/
|
||||
it.skip('formats {{data_type}} correctly', () => {
|
||||
expect({{module}}.format{{data_type}}(1000)).toBe('$1,000.00');
|
||||
expect({{module}}.format{{data_type}}(0)).toBe('$0.00');
|
||||
expect({{module}}.format{{data_type}}(-500)).toBe('-$500.00');
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Date/time utilities
|
||||
*/
|
||||
it.skip('parses date correctly', () => {
|
||||
const result = {{module}}.parseDate('2024-01-15');
|
||||
expect(result).toBeInstanceOf(Date);
|
||||
expect(result.getFullYear()).toBe(2024);
|
||||
expect(result.getMonth()).toBe(0); // January is 0
|
||||
expect(result.getDate()).toBe(15);
|
||||
});
|
||||
|
||||
it.skip('formats date as YYYY-MM', () => {
|
||||
const date = new Date(2024, 0, 15); // January 15, 2024
|
||||
expect({{module}}.formatMonth(date)).toBe('2024-01');
|
||||
});
|
||||
|
||||
/*
|
||||
* Test: Local storage operations
|
||||
*/
|
||||
it.skip('saves to localStorage', () => {
|
||||
const data = { key: 'value' };
|
||||
{{module}}.saveToStorage('test-key', data);
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith(
|
||||
'test-key',
|
||||
JSON.stringify(data)
|
||||
);
|
||||
});
|
||||
|
||||
it.skip('loads from localStorage', () => {
|
||||
const data = { key: 'value' };
|
||||
localStorage.getItem.mockReturnValue(JSON.stringify(data));
|
||||
|
||||
const result = {{module}}.loadFromStorage('test-key');
|
||||
|
||||
expect(result).toEqual(data);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
* Data providers for parameterized tests
|
||||
*/
|
||||
const testCases = [
|
||||
{ input: 'case1', expected: 'result1' },
|
||||
{ input: 'case2', expected: 'result2' },
|
||||
{ input: 'case3', expected: 'result3' },
|
||||
];
|
||||
|
||||
it.skip('processes multiple cases correctly', () => {
|
||||
testCases.forEach(({ input, expected }) => {
|
||||
expect({{module}}.process(input)).toBe(expected);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user