diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 8dfff1f..56a2c03 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -56,9 +56,9 @@ This guide enables AI coding agents to work productively in the GSD Task Manager - `bun dev` — Dev server at http://localhost:3000 - `bun typecheck` — TypeScript type checking (no emit) - `bun lint` — ESLint with Next.js config -- `bun test` — Vitest CI mode -- `bun test:watch` — Vitest watch mode -- `bun test -- --coverage` — Coverage report (target: ≥80% statements/lines/functions, ≥75% branches) +- `bun run test` — Vitest CI mode (`bun test` invokes bun's built-in runner, not vitest) +- `bun run test:watch` — Vitest watch mode +- `bun run test -- --coverage` — Coverage report (target: ≥80% statements/lines/functions, ≥75% branches) - `bun run build` — Production build (includes typecheck) - `bun run export` — Static export for S3/CloudFront diff --git a/CLAUDE.md b/CLAUDE.md index 9de79e5..9f4551e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -22,9 +22,9 @@ GSD Task Manager is a privacy-first Eisenhower matrix task manager built with Ne - `bun typecheck` - Run TypeScript type checking ### Testing & Quality -- `bun test` - Run Vitest tests in CI mode -- `bun test:watch` - Run Vitest in watch mode -- `bun test -- --coverage` - Generate coverage report (target: ≥80%) +- `bun run test` - Run Vitest tests in CI mode (`bun test` invokes bun's built-in runner, not vitest) +- `bun run test:watch` - Run Vitest in watch mode +- `bun run test -- --coverage` - Generate coverage report (target: ≥80%) - `bun lint` - Run ESLint ### Build & Deployment @@ -159,7 +159,7 @@ Logic in `lib/quadrants.ts` with `resolveQuadrantId()` and `quadrantOrder`. - `SyncAuthDialog` adds delay to avoid duplicate encryption dialogs ### Pre-commit -- Run `bun typecheck` and `bun lint` before committing +- Run `bun run test`, `bun typecheck`, and `bun lint` before committing - Static export mode means no API routes or SSR ## Modular Architecture @@ -179,4 +179,8 @@ The codebase follows coding standards (<350 lines per file, <30 lines per functi All modules maintain backward compatibility through re-export layers. +## Git Workflow + +For git operations: when asked to commit and push, write a descriptive conventional commit message, bump the version if appropriate, and create a PR unless told otherwise. Standard workflow: commit → push → create PR. + Always leverage @coding-standards.md for coding standards and guidelines. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d118bed..902b756 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -62,7 +62,7 @@ bun typecheck bun lint # Tests -bun test +bun run test # Build verification bun run build @@ -75,7 +75,7 @@ All checks must pass before submitting a PR. - Write tests for new features and bug fixes - Place UI tests in `tests/ui/`, data logic in `tests/data/` - Maintain ≥80% code coverage -- Run `bun test:watch` during development +- Run `bun run test:watch` during development ### Commit Messages diff --git a/GSD_FEATURES_GUIDE.md b/GSD_FEATURES_GUIDE.md index 0b4abf7..6db2fd4 100644 --- a/GSD_FEATURES_GUIDE.md +++ b/GSD_FEATURES_GUIDE.md @@ -2095,8 +2095,8 @@ bun run build # Build production bundle bun start # Start production server (requires build) bun typecheck # Run TypeScript compiler (no emit) bun lint # Run ESLint -bun test # Run Vitest tests (CI mode) -bun test:watch # Run tests in watch mode +bun run test # Run Vitest tests (CI mode) +bun run test:watch # Run tests in watch mode # Worker (optional, for sync development) cd worker/ @@ -2128,16 +2128,16 @@ NEXT_PUBLIC_API_BASE_URL=http://localhost:8787 ```bash # Run all tests -bun test +bun run test # Run specific test file -bun test tasks.test.ts +bun run test tasks.test.ts # Run with coverage -bun test -- --coverage +bun run test -- --coverage # Watch mode (re-run on file changes) -bun test:watch +bun run test:watch ``` **Debugging:** @@ -2345,7 +2345,7 @@ bun test:watch ```bash bun typecheck # No TypeScript errors bun lint # No ESLint errors - bun test # All tests pass + bun run test # All tests pass bun run build # Production build succeeds ``` diff --git a/OAUTH_OIDC_GUIDE.md b/OAUTH_OIDC_GUIDE.md index 289408b..68dcb44 100644 --- a/OAUTH_OIDC_GUIDE.md +++ b/OAUTH_OIDC_GUIDE.md @@ -1379,7 +1379,7 @@ window.addEventListener('storage', handleMessage); **OAuth Security Tests:** ```bash -bun test tests/security/oauth-security.test.ts +bun run test tests/security/oauth-security.test.ts ``` **Coverage:** diff --git a/TECHNICAL.md b/TECHNICAL.md index e56f6e9..05ccd25 100644 --- a/TECHNICAL.md +++ b/TECHNICAL.md @@ -38,9 +38,9 @@ Development server runs at `http://localhost:3000`. - `bun start` — Start production server (note: app uses static export) - `bun typecheck` — Run TypeScript type checking without emitting files - `bun lint` — Run ESLint with Next.js config -- `bun test` — Run Vitest tests in CI mode -- `bun test:watch` — Run Vitest in watch mode -- `bun test -- --coverage` — Generate coverage report (target: ≥80% statements) +- `bun run test` — Run Vitest tests in CI mode (`bun test` invokes bun's built-in runner, not vitest) +- `bun run test:watch` — Run Vitest in watch mode +- `bun run test -- --coverage` — Generate coverage report (target: ≥80% statements) ## Architecture @@ -388,9 +388,9 @@ Tests use Vitest with Testing Library for component and integration testing. Run tests: ```bash -bun test # CI mode -bun test:watch # Watch mode -bun test -- --coverage # With coverage report +bun run test # CI mode +bun run test:watch # Watch mode +bun run test -- --coverage # With coverage report ``` ## Code Style @@ -459,7 +459,7 @@ Output is in the `out/` directory. Upload to your static hosting provider. 1. Fork the repository 2. Create a feature branch (`git checkout -b feature/amazing-feature`) 3. Make your changes -4. Run tests and linting (`bun test && bun lint && bun typecheck`) +4. Run tests and linting (`bun run test && bun lint && bun typecheck`) 5. Commit your changes with a clear message 6. Push to your fork and open a pull request diff --git a/components/sync/oauth-buttons.tsx b/components/sync/oauth-buttons.tsx index 9470b4b..e66ebbe 100644 --- a/components/sync/oauth-buttons.tsx +++ b/components/sync/oauth-buttons.tsx @@ -191,6 +191,7 @@ export function OAuthButtons({ onSuccess, onError, onStart }: OAuthButtonsProps) window.location.href = authUrl; } } catch (error) { + setLoading(null); console.error("[OAuth] Flow failed:", error); if (error instanceof Error && error.message) { onError?.(error); diff --git a/package.json b/package.json index bdbbd8a..6abfd31 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gsd-taskmanager", - "version": "6.8.4", + "version": "6.8.5", "private": true, "scripts": { "dev": "next dev", diff --git a/tests/ui/oauth-buttons.test.tsx b/tests/ui/oauth-buttons.test.tsx index 471d380..36f7d3c 100644 --- a/tests/ui/oauth-buttons.test.tsx +++ b/tests/ui/oauth-buttons.test.tsx @@ -43,6 +43,17 @@ vi.mock('@/lib/oauth-config', () => ({ getOAuthEnvironment: () => 'local', })); +vi.mock('@/lib/env-config', () => ({ + getEnvironmentConfig: () => ({ + apiBaseUrl: 'http://localhost:8787', + oauthCallbackUrl: 'http://localhost:3000/auth/callback', + isDevelopment: true, + isProduction: false, + isStaging: false, + environment: 'development', + }), +})); + // Import component after mocks import { OAuthButtons } from '@/components/sync/oauth-buttons'; @@ -511,11 +522,12 @@ describe('OAuthButtons', () => { const user = userEvent.setup(); mockCanUsePopups.mockReturnValue(false); - // Mock window.location.href + // Save original location and replace with mock + const originalLocation = window.location; // eslint-disable-next-line @typescript-eslint/no-explicit-any delete (window as any).location; // eslint-disable-next-line @typescript-eslint/no-explicit-any - window.location = { href: '' } as any; + window.location = { href: '', hostname: 'localhost' } as any; render(); @@ -525,6 +537,9 @@ describe('OAuthButtons', () => { await waitFor(() => { expect(window.location.href).toBe('https://accounts.google.com/oauth'); }); + + // Restore original location to prevent test contamination + window.location = originalLocation; }); });