Running Phase 4 Improvements
This guide provides detailed instructions for verifying that Phase 4 improvements are working correctly and how to use the comprehensive testing infrastructure.
Prerequisites: Ensure you have completed Phase 3 and have Terra running locally.
Quick Verification (2 minutes)
Run these commands to verify Phase 4 is working:
# Run all tests
pnpm test
# Check test count
pnpm --filter terra exec vitest run | grep "Test Files"
# Verify E2E setup
ls apps/terra/tests/
# Check Playwright config
cat apps/terra/playwright.config.ts | grep "webServer"
You should see 168 passing tests and E2E test infrastructure ready.
What Was Implemented
1. Fixed Existing Tests ✅
Fixed: 7 failing tests in form-renderer.test.tsx
Issues Resolved:
- ✅ Corrected schema structure (
validation: { required: true })
- ✅ Fixed FormRenderer usage (submit button as children)
- ✅ Updated error message expectations to match i18n dictionary
- ✅ Fixed test isolation issues
Verify:
# Run form renderer tests
pnpm --filter terra test form-renderer
All tests should pass.
2. Component Tests Created ✅
Added: 24 new component tests
New Test Files:
TextField Tests (13 tests)
# Location: apps/terra/src/components/engine/fields/__tests__/text-field.test.tsx
# Run them
pnpm --filter terra test text-field
Tests cover:
- Field rendering and labeling
- Required field validation
- Pattern and minLength validation
- User input handling
- Localization support
- Read-only mode
ChoiceField Tests (11 tests)
# Location: apps/terra/src/components/engine/fields/__tests__/choice-field.test.tsx
# Run them
pnpm --filter terra test choice-field
Tests cover:
- Radio vs button variant rendering
- Option selection
- Required field validation
- Multiple choice selection
- Localization support
- Read-only mode
3. Integration Tests Created ✅
Added: 10 comprehensive integration tests
New Test File:
# Location: apps/terra/src/components/engine/__tests__/form-submission-integration.test.tsx
# Run them
pnpm --filter terra test form-submission-integration
Test Coverage:
Form Submission Flow
- ✅ Multi-field form submission
- ✅ Validation error prevention
- ✅ Specific validation error messages
- ✅ Error correction and resubmission
Multi-Page Forms
- ✅ Multi-page form rendering
- ✅ Multi-page validation
- ✅ Cross-page data submission
Conditional Logic
- ✅ Conditional field visibility (show/hide)
- ✅ Hidden field validation skip
- ✅ Dynamic form behavior
4. E2E Test Infrastructure ✅
Configured: Playwright for end-to-end testing
Files Created:
apps/terra/playwright.config.ts - Playwright configuration
apps/terra/tests/form-submission.spec.ts - Form E2E tests (templates)
apps/terra/tests/dashboard.spec.ts - Dashboard E2E tests (templates)
apps/terra/tests/README.md - Comprehensive E2E guide
Verify Setup:
# Check Playwright config
cat apps/terra/playwright.config.ts
# List E2E tests
ls -la apps/terra/tests/
# Install Playwright browsers (first time only)
pnpm --filter terra exec playwright install
Configuration Features:
- ✅ Auto-starts dev server before tests
- ✅ Base URL configured (
http://localhost:3000)
- ✅ 3 browser configurations (Chromium, Firefox, WebKit)
- ✅ CI-optimized settings
Running Tests
Unit & Integration Tests
# Run all tests (watch mode)
pnpm test
# Run tests once (CI mode)
pnpm --filter terra exec vitest run
# Run specific test file
pnpm --filter terra test text-field
# Run with coverage
pnpm --filter terra test:coverage
# Run with UI
pnpm --filter terra test:ui
E2E Tests
# Run all E2E tests (headless)
pnpm test:e2e
# Run with browser visible
pnpm --filter terra test:e2e:headed
# Run with interactive UI
pnpm --filter terra test:e2e:ui
# Run specific test file
pnpm --filter terra test:e2e tests/form-submission.spec.ts
# Debug mode
pnpm --filter terra exec playwright test --debug
Note: E2E tests are currently skipped (using test.skip) because they require authentication setup and test data. See below for how to enable them.
Test Coverage
Current Status
# Check test coverage
pnpm --filter terra test:coverage
Test Files: 8
Total Tests: 168 passing
Runtime: ~3.10 seconds
Breakdown:
permissions.test.ts - 28 tests (RBAC permissions)
security.test.ts - 71 tests (path traversal, XSS, etc.)
duplicate-form.test.ts - 10 tests (form duplication)
text-field.test.tsx - 13 tests (text input component)
choice-field.test.tsx - 11 tests (choice component)
form-renderer.test.tsx - 10 tests (form rendering)
renderer.test.tsx - 15 tests (renderer logic)
form-submission-integration.test.tsx - 10 tests (full flows)
Enabling E2E Tests
Currently, E2E tests are skipped because they require:
1. Authentication Setup
Add authentication to Playwright tests:
// apps/terra/tests/auth.setup.ts
import { test as setup } from '@playwright/test';
setup('authenticate', async ({ page }) => {
await page.goto('/login');
await page.fill('[name="email"]', 'test@example.com');
await page.fill('[name="password"]', 'password');
await page.click('button[type="submit"]');
await page.waitForURL('/');
// Save authentication state
await page.context().storageState({
path: 'playwright/.auth/user.json'
});
});
2. Test Data
Create test fixtures:
// apps/terra/tests/fixtures/forms.ts
export const TEST_FORM_ID = 'test-form-uuid';
export const TEST_FORM_SLUG = 'test-application';
// Seed these in your test database
3. Enable Tests
Change test.skip to test:
// Before (skipped)
test.skip('should display form title', async ({ page }) => {
// ...
});
// After (enabled)
test('should display form title', async ({ page }) => {
// ...
});
Writing New Tests
Component Test Template
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { FormProvider, useForm } from 'react-hook-form';
describe('MyComponent', () => {
function Wrapper({ children }: { children: React.ReactNode }) {
const methods = useForm();
return <FormProvider {...methods}>{children}</FormProvider>;
}
it('should render correctly', () => {
render(
<Wrapper>
<MyComponent />
</Wrapper>
);
expect(screen.getByRole('button')).toBeInTheDocument();
});
it('should handle user interaction', async () => {
const user = userEvent.setup();
render(
<Wrapper>
<MyComponent />
</Wrapper>
);
await user.click(screen.getByRole('button'));
expect(screen.getByText('Success')).toBeInTheDocument();
});
});
E2E Test Template
import { test, expect } from '@playwright/test';
test.describe('Feature Name', () => {
test('should do something', async ({ page }) => {
// Navigate to page
await page.goto('/path');
// Interact with elements
await page.click('button');
await page.fill('input[name="field"]', 'value');
// Assert expectations
await expect(page.locator('text=Success')).toBeVisible();
});
});
Best Practices
Testing Guidelines
Write tests that focus on user behavior, not implementation details.
DO:
✅ await user.click(screen.getByRole('button', { name: 'Submit' }));
✅ expect(screen.getByText('Success')).toBeInTheDocument();
✅ await page.fill('[name="email"]', 'test@example.com');
DON’T:
❌ component.state.isOpen === true
❌ expect(mockFunction).toHaveBeenCalledTimes(1)
❌ await page.click('.css-class-xyz')
Test Organization
apps/terra/
├── src/
│ └── components/
│ └── engine/
│ ├── fields/
│ │ ├── text-field.tsx
│ │ └── __tests__/
│ │ └── text-field.test.tsx
│ └── __tests__/
│ └── form-renderer.test.tsx
└── tests/
├── form-submission.spec.ts
├── dashboard.spec.ts
└── README.md
Debugging Tests
Unit Tests
# Run in watch mode
pnpm --filter terra test
# Run specific test with console output
pnpm --filter terra test text-field --reporter=verbose
# Debug with Vitest UI
pnpm --filter terra test:ui
E2E Tests
# View test report
pnpm --filter terra exec playwright show-report
# Debug mode with inspector
pnpm --filter terra exec playwright test --debug
# Debug specific test
pnpm --filter terra exec playwright test tests/form-submission.spec.ts --debug
# View traces (after failure)
pnpm --filter terra exec playwright show-trace trace.zip
CI/CD Integration
GitHub Actions
Tests run automatically on every push:
# .github/workflows/ci.yml
- name: Run Tests
run: pnpm test
Configuration:
- ✅ Parallel execution disabled for consistency
- ✅ 2 automatic retries for flaky tests
- ✅ HTML report generation
- ✅
forbidOnly to prevent .only tests in commits
Common Issues & Solutions
Issue: “ReferenceError: document is not defined”
Cause: Running browser code in Node.js test environment
Solution: Use jsdom environment
// Add to test file
import { afterEach } from 'vitest';
import { cleanup } from '@testing-library/react';
afterEach(() => {
cleanup();
});
Issue: E2E tests timing out
Solution: Increase timeout
test('slow test', async ({ page }) => {
test.setTimeout(60000); // 60 seconds
// ...
});
Issue: “Cannot find module” in tests
Solution: Check tsconfig paths
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}
What’s Next?
Continue improving test coverage:
- Add more component tests - DateField, FilesField, etc.
- Enable E2E tests - Set up auth and test data
- Increase coverage - Aim for 40%+ code coverage
- Add visual regression tests - Use Playwright screenshots
See the monorepo README for more testing commands.
Test Files Reference
Unit Tests
apps/terra/src/app/actions/__tests__/permissions.test.ts
apps/terra/src/lib/__tests__/security.test.ts
apps/terra/src/components/engine/fields/__tests__/text-field.test.tsx
apps/terra/src/components/engine/fields/__tests__/choice-field.test.tsx
Integration Tests
apps/terra/src/components/engine/__tests__/form-submission-integration.test.tsx
E2E Tests
apps/terra/tests/form-submission.spec.ts
apps/terra/tests/dashboard.spec.ts
Documentation
apps/terra/tests/README.md - Complete E2E testing guide
Resources