Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
155 changes: 143 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,71 +7,123 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
NODE_VERSION: 22
STORE_PATH_KEY: pnpm-store-

jobs:
setup:
name: Setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: pnpm
- run: pnpm install --frozen-lockfile
- uses: actions/cache/save@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}

typecheck:
name: Type Check
runs-on: ubuntu-latest
needs: [setup]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm install --frozen-lockfile
- run: pnpm tsc --noEmit

lint:
name: Lint
runs-on: ubuntu-latest
needs: [setup]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm install --frozen-lockfile
- run: pnpm lint

format:
name: Format Check
runs-on: ubuntu-latest
needs: [setup]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm install --frozen-lockfile
- run: pnpm prettier --check .

react-compiler:
name: React Compiler Health
runs-on: ubuntu-latest
needs: [setup]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm install --frozen-lockfile
- run: npx react-compiler-healthcheck --src "src/**/*.{ts,tsx}"

react-doctor:
name: React Doctor
runs-on: ubuntu-latest
needs: [setup]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm install --frozen-lockfile
- name: Run React Doctor (full scan on main, diff on PRs)
run: |
Expand All @@ -81,6 +133,44 @@ jobs:
npx -y react-doctor@latest . --verbose --fail-on error
fi

frontend-test:
name: Frontend Tests
runs-on: ubuntu-latest
needs: [typecheck]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm install --frozen-lockfile
- run: pnpm test:frontend --reporter=verbose

backend-test:
name: Backend Tests
runs-on: ubuntu-latest
needs: [typecheck]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm install --frozen-lockfile
- run: pnpm test:backend:run --reporter=verbose

build:
name: Build
runs-on: ubuntu-latest
Expand All @@ -90,7 +180,48 @@ jobs:
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm install --frozen-lockfile
- run: pnpm vite build

e2e-test:
name: E2E Tests
runs-on: ubuntu-latest
environment: preview
needs: [build]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.local/share/pnpm/store
key: ${{ env.STORE_PATH_KEY }}${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}
- run: pnpm install --frozen-lockfile
- run: npx playwright install --with-deps chromium
- run: pnpm test:e2e
env:
VITE_CONVEX_URL: ${{ secrets.VITE_CONVEX_URL }}
VITE_CONVEX_SITE_URL: ${{ secrets.VITE_CONVEX_SITE_URL }}
VITE_SITE_URL: ${{ secrets.VITE_SITE_URL }}
E2E_TEST_EMAIL: ${{ secrets.E2E_TEST_EMAIL }}
E2E_TEST_PASSWORD: ${{ secrets.E2E_TEST_PASSWORD }}
E2E_PLAYER_EMAIL: ${{ secrets.E2E_PLAYER_EMAIL }}
E2E_PLAYER_PASSWORD: ${{ secrets.E2E_PLAYER_PASSWORD }}
TEST_RUN_ID: ${{ github.run_id }}-${{ github.run_attempt }}
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 14
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,16 @@ yarn.lock
# Sentry Config File
.env.sentry-build-plugin
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
.playwright-mcp/*

app.config.timestamp_*.js


e2e/.auth/
playwright-report/
coverage/

.claude/

48 changes: 48 additions & 0 deletions convex/_test/assertions.helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { expect } from 'vitest'
import { ConvexError } from 'convex/values'
import { isClientError } from '../errors'
import type { ClientErrorCode } from '../errors'

export async function expectClientError(
promise: Promise<unknown>,
code: ClientErrorCode,
) {
try {
await promise
expect.fail(
`Expected ConvexError with code ${code}, but no error was thrown`,
)
} catch (error) {
if (error instanceof ConvexError && isClientError(error, code)) {
return error
}
if (
error instanceof Error &&
'data' in error &&
isClientError(error, code)
) {
return error
}
throw error
}
}

export function expectNotAuthenticated(promise: Promise<unknown>) {
return expectClientError(promise, 'NOT_AUTHENTICATED')
}

export function expectPermissionDenied(promise: Promise<unknown>) {
return expectClientError(promise, 'PERMISSION_DENIED')
}

export function expectNotFound(promise: Promise<unknown>) {
return expectClientError(promise, 'NOT_FOUND')
}

export function expectValidationFailed(promise: Promise<unknown>) {
return expectClientError(promise, 'VALIDATION_FAILED')
}

export function expectConflict(promise: Promise<unknown>) {
return expectClientError(promise, 'CONFLICT')
}
Loading
Loading