Skip to content
Open
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
82 changes: 82 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: E2E

on:
push:
branches:
- main
paths:
- "packages/**"
- "examples/**"
- "e2e/**"
- "scripts/**"
- "firebase.json"
- ".github/workflows/e2e.yaml"
- ".github/workflows/test.yaml"
- "package.json"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
pull_request:
paths:
- "packages/**"
- "examples/**"
- "e2e/**"
- "scripts/**"
- "firebase.json"
- ".github/workflows/e2e.yaml"
- ".github/workflows/test.yaml"
- "package.json"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"

permissions:
contents: read

jobs:
ui-e2e:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Setup pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
version: 10.34.4

- name: Setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22.13.0
cache: pnpm
cache-dependency-path: pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Resolve Playwright version
id: playwright-version
run: |
version="$(pnpm --filter=e2e exec node -p "require('@playwright/test/package.json').version")"
echo "playwright-version=${version}" >> "$GITHUB_OUTPUT"

- name: Cache Playwright browsers
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.playwright-version }}

- name: Install Playwright browsers
run: pnpm --filter=e2e exec playwright install --with-deps chromium

- name: Run UI e2e smoke
run: pnpm test:e2e

- name: Upload Playwright report and coverage
if: always()
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
with:
name: e2e-artifacts
path: |
e2e/playwright-report/
e2e/coverage-report/
if-no-files-found: ignore
17 changes: 10 additions & 7 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,27 @@ on:
- main
pull_request:

permissions:
contents: read

jobs:
lint:
name: Lint and Format Check
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wiz flags a file if it has problems and you touch it - I touched this (and tset.yaml) to pin the pnpm version, so I had to then pin all the SHAs for actions in order to satisfy wiz


- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '22.13.0'

- name: Setup pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
version: 10
version: 10.34.4

- name: Install addlicense
run: |
Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,26 @@ on:
- main
pull_request:

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

- name: Setup node
uses: actions/setup-node@v4
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22.13.0
check-latest: true

- name: Setup pnpm
uses: pnpm/action-setup@v4
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
version: 10
version: 10.34.4

- name: Install addlicense
run: |
Expand Down
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,19 @@ packages/angular/src/version.ts
# Coverage
coverage

# Playwright
e2e/test-results/
e2e/.state/
e2e/playwright-report/
e2e/coverage-report/
playwright-report/

# Firebase
.firebase

# Agent ephemeral output
.agents/reports/

# Editor directories and files
.vscode/*
!.vscode/extensions.json
Expand Down
12 changes: 12 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Agent entry point

Start at [developer-docs/index.md](developer-docs/index.md).

**Before editing documentation:** read [developer-docs/documentation-policy.md](developer-docs/documentation-policy.md).

For architecture or testing work, also read:

* [developer-docs/decisions.md](developer-docs/decisions.md) — `AD-<number>` decision log
* [developer-docs/work-queues/playwright-e2e-smoke.md](developer-docs/work-queues/playwright-e2e-smoke.md) — active Playwright backlog

Human onboarding (commands, emulator): [LOCAL_DEVELOPMENT.md](LOCAL_DEVELOPMENT.md) owns that content; do not duplicate here.
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ This is a monorepo managed with pnpm, containing both `packages` and `examples`

For a step-by-step guide on running the project locally (emulator setup, watch mode, example apps), see [LOCAL_DEVELOPMENT.md](LOCAL_DEVELOPMENT.md).

Architecture decisions, testing strategy, and agent-oriented docs live in the [developer-docs/](developer-docs/index.md) OKF bundle. Read [developer-docs/documentation-policy.md](developer-docs/documentation-policy.md) before editing that tree.

#### Building

Build all packages:
Expand Down
37 changes: 25 additions & 12 deletions LOCAL_DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ if (import.meta.env.MODE === "development") {
```

Each framework detects dev mode differently:

- **Vite examples** (react, shadcn): `import.meta.env.MODE === "development"`
- **Next.js examples**: `process.env.NODE_ENV === "development"`
- **Angular**: `isDevMode()` from `@angular/core`
Expand All @@ -124,27 +125,39 @@ All automatic when using the `dev` / `start` scripts.

## Which example app should I use?

| I'm working on... | Use this example |
|---|---|
| Core auth logic, sign-in flows, state | `react` |
| React components, hooks, UI | `react` |
| Angular components or DI | `angular` |
| Shadcn components or theming | `shadcn` |
| Server-side rendering, server components | `nextjs-ssr` |
| Static Next.js / client-only | `nextjs` |
| Translations or CSS | `react` (easiest) |
| Custom OAuth flows | `custom-auth-server` (see [CUSTOM_AUTHENTICATION.md](CUSTOM_AUTHENTICATION.md)) |
| I'm working on... | Use this example |
| ---------------------------------------- | ------------------------------------------------------------------------------- |
| Core auth logic, sign-in flows, state | `react` |
| React components, hooks, UI | `react` |
| Angular components or DI | `angular` |
| Shadcn components or theming | `shadcn` |
| Server-side rendering, server components | `nextjs-ssr` |
| Static Next.js / client-only | `nextjs` |
| Translations or CSS | `react` (easiest) |
| Custom OAuth flows | `custom-auth-server` (see [CUSTOM_AUTHENTICATION.md](CUSTOM_AUTHENTICATION.md)) |

The `react` example is recommended as the default — it has the fastest reload cycle.

## Running tests

Start the emulator first, then:
Start the emulator first (or let `pnpm test:e2e` start it via Playwright `globalSetup` when it is not already running), then:

```bash
# All tests:
# Package unit tests:
pnpm test

# Example smoke (all six examples, serial):
pnpm test:e2e

# Single example smoke:
pnpm test:e2e:react
pnpm test:e2e:angular
# … see root package.json for test:e2e:<example> scripts
```

E2E scope and CI layers: [developer-docs/architecture/testing-strategy.md](developer-docs/architecture/testing-strategy.md).

```bash
# Watch mode (core, react, angular):
pnpm test:watch

Expand Down
57 changes: 57 additions & 0 deletions developer-docs/architecture/examples-inventory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
type: Reference
title: Examples inventory
description: How each monorepo example is started, which port it uses, and emulator requirements.
resource: firebaseui-web/examples/
tags: [examples, monorepo, emulator]
timestamp: 2026-07-01T00:00:00Z
---

# Workspace layout

pnpm workspace members: `packages/*`, `examples/*` ([pnpm-workspace.yaml](../../pnpm-workspace.yaml)). Examples consume `@firebase-oss/ui-*` via `workspace:*`.

# Examples in scope for e2e smoke

| Example | pnpm filter | Dev command | Default port | E2E port | Emulator in dev | Smoke type |
| ------------------ | -------------------- | --------------------------------------------- | ------------- | -------- | -------------------------------------------------- | -------------------------- |
| react | `react` | `vite` | 5173 | 5173 | `import.meta.env.MODE === "development"` → `:9099` | browser (S1–S3) |
| shadcn | `shadcn` | `vite` | 5173 | 5174 | same as react | browser (S1–S3) |
| nextjs (SSG) | `nextjs` | `next dev --turbopack` | 3000 | 3000 | `NODE_ENV === "development"` → `:9099` | browser (S1–S3) |
| nextjs-ssr | `nextjs-ssr` | `next dev` | 3000 | 3001 | same as nextjs | browser (S1–S3) |
| angular-example | `angular-example` | `run start --port 4200` (`clean && ng serve`) | 4200 | 4200 | `isDevMode()` → `:9099` | browser (S1–S3) |
| custom-auth-server | `custom-auth-server` | `start` (built Express) | 4000 (`PORT`) | 4001 | n/a (uses `firebase-admin`) | HTTP boot + `fetch`/`curl` |

**Port configurability:** not pinned in `vite.config.ts` / `next.config.ts`. All examples accept CLI/`PORT` overrides for e2e; Playwright's top-level `webServer` (selected by `E2E_PROJECT`) owns lifecycle. Exact e2e commands: `e2e/fixtures/example-meta.ts`. See [AD-4](../decisions.md#ad-4-playwright-managed-dev-servers-serial-shared-emulator).

**custom-auth-server port:** default `:4000` collides with the Firebase Emulator UI (`:4000`), so e2e binds `:4001` — [AD-6](../decisions.md#ad-6-custom-auth-server-binds-4001-for-e2e). Its smoke is non-browser (boot + HTTP assert); it is not in root `pnpm build`.

**Angular:** e2e reuses the package `start` script (`pnpm clean && ng serve`) so the `.angular/cache` clean is not duplicated — [AD-4](../decisions.md#ad-4-playwright-managed-dev-servers-serial-shared-emulator).

**Auth behaviors affecting smoke:** react/shadcn use `oneTapSignIn`; nextjs/nextjs-ssr use `autoAnonymousLogin`. Neither hides the sign-in form (`SignInAuthScreen` renders regardless of auth state), so E2E flags are optional — [AD-5](../decisions.md#ad-5-auth-behavior-e2e-flags-are-optional-only-if-flaky). The One Tap external script is blocked in the harness.

**Next.js paths:** both nextjs (SSG) and nextjs-ssr use `trailingSlash: true` — e2e URLs end with `/` (e.g. `/screens/sign-in-auth-screen-w-handlers/`).

**Forgot-password route varies per example** (S3 asserts rendered UI, not a fixed path):

| Example | Forgot-password route from sign-in-with-handlers |
| ---------------------- | ------------------------------------------------ |
| react, angular-example | `/screens/forgot-password-auth-screen` |
| shadcn | `/screens/forgot-password-screen` |
| nextjs, nextjs-ssr | `/screens/forgot-password-auth-screen` |

# Shared prerequisites

1. `pnpm install`
2. `pnpm build:packages` (or full `pnpm build` in CI)
3. Auth emulator: `pnpm emulators` → `http://localhost:9099` ([firebase.json](../../firebase.json))

Procedural steps: [LOCAL_DEVELOPMENT.md](../../LOCAL_DEVELOPMENT.md) (owner for command copy-paste).

# Smoke test entry path (all UI examples)

Deep-link: `/screens/sign-in-auth-screen-w-handlers` (with trailing slash for Next). Smoke scope: [AD-3](../decisions.md#ad-3-playwright-example-smoke-tests-mvp-scope-dev-server).

# Citations

[1] [LOCAL_DEVELOPMENT.md](../../LOCAL_DEVELOPMENT.md)
34 changes: 34 additions & 0 deletions developer-docs/architecture/testing-strategy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
type: Reference
title: Testing strategy
description: Verification layers for firebaseui-web packages and examples.
tags: [testing, ci, playwright]
timestamp: 2026-07-03T00:00:00Z
---

# Layers

| Layer | Command | Owner doc | Catches |
|-------|---------|-----------|---------|
| Package unit tests | `pnpm test` | [CONTRIBUTING.md](../../CONTRIBUTING.md) | Core/react/angular/shadcn/translations/styles logic |
| Compile (packages + examples) | `pnpm build` | [CONTRIBUTING.md](../../CONTRIBUTING.md) | TS, bundler, framework build errors |
| Lint / format | `pnpm lint:check`, `pnpm format:check` | [CONTRIBUTING.md](../../CONTRIBUTING.md) | Style regressions |
| Example smoke (browser + HTTP) | `pnpm test:e2e` | [AD-3](../decisions.md#ad-3-playwright-example-smoke-tests-mvp-scope-dev-server), [AD-4](../decisions.md#ad-4-playwright-managed-dev-servers-serial-shared-emulator), [AD-6](../decisions.md#ad-6-custom-auth-server-binds-4001-for-e2e) | Dev-server UI interactivity (five UI examples) and `custom-auth-server` HTTP boot |
| Security audit | `pnpm audit` | [playbooks/dependency-update-verification.md](../playbooks/dependency-update-verification.md) | Known CVEs in lockfile |

# CI today

[`.github/workflows/test.yaml`](../../.github/workflows/test.yaml): `pnpm build`, Auth emulator start, `pnpm test`.

[`.github/workflows/e2e.yaml`](../../.github/workflows/e2e.yaml): `pnpm test:e2e` (six examples), Playwright Chromium, HTML/coverage artifacts — [AD-7](../decisions.md#ad-7-e2e-runs-in-a-separate-ci-workflow-with-broad-triggers). Auth emulator is ensured by Playwright `globalSetup` (reuse-aware).

# Gaps

* Skipped package integration tests (`describe.skip`).
* `custom-auth-server` not built by root `pnpm build` (e2e builds it on demand).
* Production build artifacts not exercised by e2e — deferred, [AD-8](../decisions.md#ad-8-production-artifact-e2e-deferred-future-phase).
* `pnpm audit` not gated in CI.

# Post-dependency-update gate (target)

See [playbooks/dependency-update-verification.md](../playbooks/dependency-update-verification.md).
Loading
Loading