Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7b9ac38
docs: add spec for page component refactoring
GehDoc Jun 13, 2026
08ca413
docs: update SDD workflow with branching and incremental protocols
GehDoc Jun 13, 2026
2832877
docs: update multi-tiered testing strategy in CONTRIBUTING.md
GehDoc Jun 13, 2026
ac00e7b
feat: extract EmptyState component and add unit tests
GehDoc Jun 13, 2026
d4f747f
feat(testing): initialize Playwright E2E suite
GehDoc Jun 13, 2026
8391f74
chore: fix formatting in CI integration spec
GehDoc Jun 14, 2026
3e4d0dd
ci: install playwright and run e2e tests
GehDoc Jun 14, 2026
0e1b7e5
fix: exclude e2e tests from vitest
GehDoc Jun 14, 2026
08ad19a
ci: run workflow on all branches
GehDoc Jun 14, 2026
775b40a
ci: fix redundant CI triggers on push
GehDoc Jun 14, 2026
1cb58ef
Merge pull request #3 from GehDoc/feat/setup-e2e-testing
GehDoc Jun 14, 2026
b8273d6
feat: extract Navbar component and add unit tests
GehDoc Jun 14, 2026
d295f00
feat: extract GenerationForm component and add unit tests
GehDoc Jun 14, 2026
a8491aa
feat: extract WorkspaceActions component and add unit tests
GehDoc Jun 14, 2026
ccd40b0
feat: extract TripNavigator component and add unit tests
GehDoc Jun 14, 2026
e2330db
feat: extract TripViewer component and add unit tests
GehDoc Jun 14, 2026
d4bdaeb
docs: finalize execution order in refactoring spec
GehDoc Jun 14, 2026
1159873
docs: document component architecture and E2E testing strategy
GehDoc Jun 14, 2026
d4e22c1
chore: bump version to 0.2.0
GehDoc Jun 14, 2026
9e6930a
docs: add release notes for v0.2.0
GehDoc Jun 14, 2026
6ec2ee6
chore: remove separate release note file
GehDoc Jun 14, 2026
4c85662
docs: clarify release note protocol to avoid separate files
GehDoc Jun 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: write
Expand All @@ -20,7 +19,9 @@ jobs:
node-version: 22
cache: 'npm'
- run: npm ci
- run: npx playwright install --with-deps
- run: npm run check
- run: npm run test:e2e

deploy:
name: 'Build and Deploy'
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# Playwright
/playwright-report/
/test-results/
7 changes: 6 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ Before writing any implementation code, agents must:
2. **Plan (Spec)**: Create a new specification file in `specs/pending/`.
3. **Approve**: Present the plan to the user and wait for explicit approval.
4. **Execute**: Implement surgical changes following the approved plan.
5. **Validate**: Run `npm run check` to ensure zero regressions.
- **Branching**: Always create a feature branch (`feat/name`) or fix branch (`fix/name`) before execution.
- **Incrementality**: Extract/Implement one logical unit (e.g., one component) at a time.
- **Test-Driven**: Write unit tests for each unit immediately after creation.
- **Atomic Commits**: Commit and push each successful "Unit + Test" cycle.
- **No Release Files**: NEVER create separate Markdown files for release notes in the repository. Provide release notes in the final task summary or PR description only.
5. **Validate**: Run `npm run check` to ensure zero regressions before final PR.

## 🛠 Tech Stack Constraints

Expand Down
17 changes: 13 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,24 @@ If working without an agent, follow these steps to keep the project state synchr
| `npm run check:fast` | Fast checks: Lint, Format, and Type-check |
| `npm run fix` | Automatically fix linting and formatting issues |
| `npm run test` | Run unit tests with Vitest |
| `npm run test:e2e` | Run E2E tests with Playwright |
| `npm run type-check` | Validate TypeScript types |

## 🧪 Testing Strategy

Beyond end-to-end testing, we use a multi-tiered strategy for component, accessibility, and visual validation:

1. **Unit Tests (`*.test.[ts|tsx]`)**: Validate logic, utilities, and basic component interaction using Vitest.
- **Unit Tests**: Must be co-located with the source file (e.g., `src/utils/share.test.ts` for `src/utils/share.ts`).
2. **E2E Tests**: Reserved for the `e2e/` directory (to be created when needed).
1. **Unit Tests (`*.test.[ts|tsx]`)**: Validate logic, utilities, and basic component interaction using Vitest and JSDOM. These are fast and do not require a browser.
- **Co-location**: Unit tests MUST be co-located with the source file they test (e.g., `src/components/Button.test.tsx` for `src/components/Button.tsx`).
- **Command**: `npm run test` (or `npm run check` for the full suite).
2. **Visual Regression Tests (`*.spec.[ts|tsx]`)**: Validate component-level rendering and pixel-perfect consistency in a real browser (Chromium) using Playwright.
- **Location**: Co-located with the component, similar to unit tests, but using the `.spec` suffix.
- **Command**: `npm run test:visual` (Future capability).
3. E2E Tests (`e2e/*.spec.ts`): Validate full user workflows in a real browser environment.
- **Location**: Dedicated `e2e/` directory at the project root.
- **Command**: `npm run test:e2e`
4. **Storybook Interaction & A11y Tests**: Validate visual/accessibility compliance (e.g., color contrast) and component interactions in isolation.
- **Command**: `npm run test:storybook` (Future capability).

## ✅ The "Definition of Done"

Expand Down Expand Up @@ -91,7 +100,7 @@ Use the `npm version [patch|minor|major]` command before committing.

## 📝 Release Note Best Practices

To maintain consistent, high-quality release notes, follow this structure:
To maintain consistent, high-quality release notes, follow the structure below. **IMPORTANT**: Do NOT create separate Markdown files in the repository for release notes. Instead, include them in your **Pull Request description**.

- **Format**: `Release [Version] - [Short Descriptive Title]`
- **Punchline**: 2-3 sentence summary.
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ This project follows **Spec-Driven Development (SDD)** to maintain a clear roadm
```bash
npm run dev
```
5. **Open the App**: Visit `http://localhost:3000` and enter your API key in the top bar.
5. **Open the App**: Visit `http://localhost:3000` (development) or `http://localhost:3000/quick-tripper` (production-emulated) and enter your API key in the top bar.

## 🏗️ Architecture

Expand All @@ -64,8 +64,9 @@ To maintain a robust "zero-backend" application, we rely on a multi-tiered valid
1. **Architectural Design**: High-level designs and data contracts are documented in `ARCHITECTURE.md`.
2. **Static Analysis**: ESLint and Prettier ensure code consistency and catch early errors.
3. **Type Safety**: Strict TypeScript is enforced at the commit level via Husky hooks.
4. **Unit Testing**: Vitest and JSDOM validate core logic and utility functions (e.g., URL compression).
5. **Spec-First Implementation**: Every change is traced back to a technical specification in `specs/`, ensuring architectural alignment.
4. **Unit Testing**: Vitest and JSDOM validate core logic, utility functions, and presentational components (co-located tests).
5. **E2E Testing**: Playwright validates full user workflows and "golden paths" in a real browser environment.
6. **Spec-First Implementation**: Every change is traced back to a technical specification in `specs/`, ensuring architectural alignment.

## 📦 Deployment

Expand Down
20 changes: 20 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ When the `Trip` data structure changes in a breaking way, follow these steps to
5. **Test**:
- Add test cases in `src/tests/migration.test.ts` to verify the upgrade path from `v<N-1>` to `v<N>`.

## Component Architecture

The project follows a **Smart Container & Dumb Presenter** pattern (Clean Architecture) to ensure high testability and separation of concerns.

### Smart Containers (Pages/Hooks)

- **Role**: Data orchestration, service invocation (API calls), and state management.
- **Location**: Found in `src/app/` (Pages) and `src/hooks/`.
- **Responsibility**: They do not contain complex UI logic or styling. They pass data and event handlers down to presentational components.

### Dumb Presenters (Components)

- **Role**: Visual representation and user interaction.
- **Location**: Found in `src/components/`.
- **Responsibility**: They are "stateless" (logic-lite) and rely entirely on props. They must be easily unit-testable in isolation using Vitest and React Testing Library.

### Testing Co-location

To maintain architectural clarity, every presentational component MUST have a co-located unit test file (e.g., `src/components/MyComponent.test.tsx`).

## SSR and Hydration Strategy

To maintain a "zero-backend" architecture using Next.js (SSR), we must ensure that the server-rendered HTML and client-rendered UI are identical during the initial mount.
Expand Down
31 changes: 31 additions & 0 deletions e2e/golden-path.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { test, expect } from '@playwright/test';

test('golden path - generate trip', async ({ page }) => {
await page.goto('/');
// Mock API
await page.route('https://router.huggingface.co/v1/chat/completions', (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
choices: [
{
message: {
content: '# Golden Trip\nThis is a mocked itinerary.',
},
},
],
}),
}),
);

// Enter API Key
await page.getByPlaceholder('HuggingFace API Token').fill('dummy-key');
// Enter Destination
await page.getByPlaceholder('Ex: A 4-day hike').fill('Swiss Alps');
// Send
await page.locator('.join').getByRole('button').click(); // Send icon button within join component

// Verify
await expect(page.getByText('Golden Trip')).toBeVisible();
});
7 changes: 7 additions & 0 deletions e2e/smoke.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { test, expect } from '@playwright/test';

test('homepage should have correct branding and show EmptyState', async ({ page }) => {
await page.goto('/');
await expect(page.getByText('Quick-tripper')).toBeVisible();
await expect(page.getByText('No active itineraries loaded')).toBeVisible();
});
6 changes: 4 additions & 2 deletions next.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/** @type {import('next').NextConfig} */
const isProd = process.env.NODE_ENV === 'production';

const nextConfig = {
output: 'export', // Indispensable pour GitHub Pages
basePath: '/quick-tripper',
assetPrefix: '/quick-tripper',
basePath: isProd ? '/quick-tripper' : '',
assetPrefix: isProd ? '/quick-tripper/' : '',
images: {
unoptimized: true, // Recommandé pour l'export statique
},
Expand Down
68 changes: 66 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "quick-tripper",
"type": "module",
"version": "0.1.0",
"version": "0.2.0",
"private": true,
"description": "Privacy-first, zero-backend AI travel companion",
"author": "GehDoc",
Expand Down Expand Up @@ -38,6 +38,7 @@
"format:fix": "prettier --write .",
"type-check": "tsc --noEmit",
"test": "vitest run",
"test:e2e": "playwright test",
"test:watch": "vitest",
"check": "npm run lint && npm run format && npm run type-check && npm run test",
"check:fast": "npm run lint && npm run format && npm run type-check",
Expand All @@ -62,6 +63,7 @@
"rehype-raw": "^7.0.0"
},
"devDependencies": {
"@playwright/test": "^1.60.0",
"@tailwindcss/postcss": "^4",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
Expand Down
26 changes: 26 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
testDir: './e2e',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'list',
use: {
baseURL: 'http://localhost:3001',
trace: 'on-first-retry',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
webServer: {
command: 'npx next dev -p 3001',
url: 'http://localhost:3001',
reuseExistingServer: !process.env.CI,
timeout: 120000,
},
});
31 changes: 31 additions & 0 deletions specs/completed/e2e-testing-setup-v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Spec: E2E Testing Setup with Playwright (v1)

## Status

🟢 Completed

## Overview

Initialize Playwright E2E testing for Quick-tripper to ensure core functionality works end-to-end.

## Scope

- [x] **Installation**: Install `@playwright/test`.
- [x] **Configuration**: Create initial Playwright configuration in the root.
- [x] **Directory**: Create `e2e/` folder for test files.
- [x] **Tests**:
- [x] `e2e/smoke.spec.ts`: Verify homepage loading, branding, and EmptyState.
- [x] `e2e/golden-path.spec.ts`: Mock Hugging Face API, simulate user trip generation, verify output.
- [x] **Scripts**: Add `test:e2e` to `package.json`.
- [x] **Documentation**: Update `CONTRIBUTING.md` to include the new E2E testing strategy.

## Verification

- [x] Run tests using `npx playwright test`.
- [x] Ensure tests pass.
- [x] Add `test:e2e` to `package.json` and run.
- [x] Update `CONTRIBUTING.md`.

## Change Log

- 2026-06-13: E2E suite initialized, smoke and golden-path tests implemented, `package.json` and `CONTRIBUTING.md` updated. Tests verified passing.
15 changes: 15 additions & 0 deletions specs/pending/ci-e2e-integration-v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Spec: Integrate E2E Tests into CI/CD (v1)

## Overview

Include E2E tests (`npm run test:e2e`) in the `npm run check` script and ensure they run in GitHub Actions CI.

## Scope

1. **Scripts**: Add `test:e2e` to `npm run check` in `package.json`.
2. **CI**: Update `.github/workflows/ci.yml` to run Playwright E2E tests.

## Verification

1. Run `npm run check` locally to ensure it now includes E2E tests.
2. Verify CI workflow runs E2E tests.
Loading
Loading