Commit Graph

6 Commits

Author SHA1 Message Date
Miranda Limonczenko
f10f00ae69 fix(e2e): install e2e-shared when CI filters to a single suite (#48960)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Bug fix. Unblocks the WWW E2E check on `master`.

## What is the current behavior?

The WWW E2E job fails before running any test:

```
Error: Cannot find package '@axe-core/playwright' imported from /home/runner/_work/supabase/supabase/e2e/shared/axe.ts
Error: No tests found
```

Both E2E workflows install with a filter:

```
pnpm install --frozen-lockfile --filter=e2e-www...
```

The `...` suffix pulls in a package's declared dependencies. Neither
`e2e-www` nor `e2e-docs` declared `e2e-shared`; both reach it through
relative imports such as `../../shared/axe.ts`, which pnpm's dependency
graph cannot see. So the filter selected one project,
`e2e/shared/node_modules` was never created, and Node resolving
`@axe-core/playwright` from `e2e/shared/axe.ts` walked up to a root that
does not carry it under pnpm's isolated layout.

`e2e-docs` is broken the same way. It had not run against the shared
module yet, so it has not gone red.

## What is the new behavior?

`e2e-shared` is declared as a workspace dependency of both suites, so
the filter installs it.

| | Filter scope | Importing `e2e/shared/axe.ts` |
| --- | --- | --- |
| Before | 1 of 28 projects | `Cannot find package
'@axe-core/playwright'` |
| After | 2 of 28 projects | Imports cleanly |

The lockfile gains two `link:../shared` entries and no new downloads.

## Manual Testing

1. Check out this branch and delete the shared package's modules: `rm
-rf e2e/shared/node_modules`
2. Run the command CI runs: `pnpm install --frozen-lockfile
--filter=e2e-www...`
3. Confirm the output reports `Scope: 2 of 28 workspace projects` and
that `e2e/shared/node_modules` exists again.
4. Repeat steps 1 - 3 with `--filter=e2e-docs...`.

## Additional context

Fixing only the workflow lines, by adding a second
`--filter=e2e-shared`, would work as well. Declaring the dependency was
chosen instead because the dependency is real and every consumer of the
filter gets it, not just the two workflow files.

The imports stay relative. Declaring the workspace dependency is enough
to get the package installed, so no import paths change in this PR.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated end-to-end test packages to use shared testing utilities at
runtime.
  * Improved consistency between documentation and website test suites.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 16:17:29 -07:00
Miranda Limonczenko
777c02c205 test(docs): scan changed pages for WCAG 2.1 A/AA in warn mode (#48727)
Closes DOCS-1233

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Test coverage. The docs accessibility check now covers the full WCAG 2.1
A/AA rule set instead of two rules.

**Note:** This PR tests _only_ the main article of changed pages
(meaning, the content itself). A follow-up Linear issue is to address
scanning the pieces outside of that: header, navigation, and interactive
elements.

## What is the current behavior?

The `@a11y` test in `e2e/docs` runs two axe rules against each in-scope
page, `heading-order` and `page-has-heading-one`. Both already pass
everywhere, so the check only guards a result we have. Nothing else in
WCAG A/AA is checked.

## What is the new behavior?

The same test runs the full WCAG 2.1 A/AA rule set.

- **Existing debt does not block PRs.** Only the two heading rules fail.
Everything else reports.
- **The check stays fast.** It scans the article only and skips nine
rules that cannot fire there. Scan time drops from 2405ms to 981ms.
- **Findings belong to us.** Legacy mode excludes cross-origin frames.
YouTube embeds were counting against us, 11 of 15 violations on one
page.
- **A pass carries meaning.** A 404 reports as a load failure, not an
a11y bug. A page scanned before it hydrates warns instead of quietly
reporting clean.

## How the findings appear

The test is named `has no blocking accessibility violations`, so a
failure listed by CI is always something to fix. It is not named for the
full rule set, because a green check would then claim more than the
check verifies.

| | Rules | Where you see it |
| --- | --- | --- |
| Blocking | `heading-order`, `page-has-heading-one` | Test failure, so
the runner reports it on the PR |
| Reported | Everything else in WCAG A/AA | `::warning` annotation on
the run |

An annotation looks like this, on a run that still passes:

```
::warning title=Accessibility::/docs/guides/database/functions has 1 non-blocking accessibility finding(s): frame-title (4)
```

The full axe result for each page is attached to the report as
`axe-results.json`.

## Matching the Studio ratchet

This follows the ESLint ratchet in `apps/studio`. That pattern warns on
pre-existing debt rather than blocking on it, surfaces findings as
annotations rather than PR comments, and promotes a rule to an error
once its violations reach zero.

The mechanism here is `ENFORCED_RULES` in `utils/axe-helpers.ts`. The
two heading rules are on it because the heading-hierarchy work drove
them to zero site-wide.

The intent is to migrate rules into that list one at a time. Pick a
rule, fix its violations, then move it into `ENFORCED_RULES` so it
cannot come back. An exhaustive scan of the site groups the current
backlog by root cause to sequence that work, and two fixes cover 99.1%
of it.

Studio keeps per-file baseline counts, which this does not. A whole-rule
list is coarser, and it works here because docs violations reach zero
across the site rather than per file.

## Manual testing

Install the browser once, then run each step from the repo root. Every
command scans production, so you do not need a local docs server.

```bash
pnpm -C e2e/docs exec playwright install chromium
```

1. Confirm a reported finding does not fail the check.

   ```bash
DOCS_E2E_PAGE_PATHS=/docs/guides/database/functions
PLAYWRIGHT_BASE_URL=https://supabase.com pnpm e2e:docs:a11y
   ```

Expect `1 passed`, and the `::warning` annotation above in the output.

2. Confirm the scan finds that violation. Same page, now failing on
every rule.

   ```bash
A11Y_ENFORCE_ALL=1 DOCS_E2E_PAGE_PATHS=/docs/guides/database/functions
PLAYWRIGHT_BASE_URL=https://supabase.com pnpm e2e:docs:a11y
   ```

Expect `1 failed`, reporting `frame-title (serious, 4 node(s))`. Steps 1
and 2 together are the point of this PR.

3. Confirm the skipped rules stay skipped.

   ```bash
A11Y_ENFORCE_ALL=1
DOCS_E2E_PAGE_PATHS=/docs/guides/getting-started/quickstarts/nextjs
PLAYWRIGHT_BASE_URL=https://supabase.com pnpm e2e:docs:a11y
   ```

Expect `button-name (critical, 2 node(s))` and `label (critical, 2
node(s))`, and no `color-contrast`.

4. Confirm a page that does not load reports a load failure.

   ```bash
DOCS_E2E_PAGE_PATHS=/docs/guides/does-not-exist-xyz
PLAYWRIGHT_BASE_URL=https://supabase.com pnpm e2e:docs:a11y
   ```

Expect `Expected a successful response for
/docs/guides/does-not-exist-xyz, got 404`, and no axe assertion.

5. Confirm the link checker still passes alongside the a11y test.

   ```bash
DOCS_E2E_PAGE_PATHS=/docs/guides/auth/passwords
PLAYWRIGHT_BASE_URL=https://supabase.com pnpm e2e:docs
   ```

   Expect `3 passed`.

## Known gaps

- `/docs/reference/*` is not scanned. Those routes render client-side
into tens of thousands of elements, where axe exceeds its timeout and
results depend on whether the scan caught the page mid-render.
- Shared chrome is outside the article scope, so nav, sidebar, footer,
menus, and drawers are not covered.
- axe catches roughly 30-40% of WCAG issues. Keyboard navigation, focus
management, and screen reader behavior still need manual testing.

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 10:41:23 -07:00
Miranda Limonczenko
8dda0c3910 Add heading-hierarchy a11y check to docs E2E tests (#48422)
Closes DOCS-1232

## Problem

We do not have any tests to verify that we are following a proper
heading hierarchy. For a documentation site that deals in mostly static
content, this test is important.

Single h1 + logical heading hierarchy (h1→h2→h3, no skips) matters
because screen reader users navigate by jumping between headings —
broken structure breaks that navigation.

Relevant: WCAG 1.3.1 Info and Relationships (Level A) —
https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships.html

## Solution

Add Playwright axe-core, which we plan to expand later, to test only the
h1 and header-hierarchy rule.
This is added to our current suite that dynamically checks only pages
that are edited.

## Manual testing

1. Find a docs guide and intentionally break the header hierarchy.
2. Run `pnpm e2e:docs:a11y` and see your errors.
3. Resolve the issue and run again to see errors resolved. Ensure there
is at least a line changed to see the page tested.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Tests**
  * Added automated accessibility checks for documentation pages.
* Verified heading order and the presence of a level-one heading on each
page.
  * Added a dedicated command to run documentation accessibility tests.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-31 12:31:39 -07:00
Miranda Limonczenko
52cb1c2600 feat(docs) Dynamically E2E test all docs-owned content (#48320)
Closes DOCS-1203

## Problem

The docs E2E workflow only ever tested one hardcoded page: the Next.js
quickstart. All other docs content had no E2E coverage.

## Solution

This PR expands the initial scaffolding to generalize the Next.js
quickstart tests, page runs and checks local links, to all pages
affecting Docs content:


- Add `resolveDocsScope` (`e2e/docs/utils/resolve-docs-scope.ts`) to map
changed guide and troubleshooting `.mdx` files to their `/docs/...` page
paths, and to expand changed `_partials` to every page that includes
them (including transitively, through partials nested inside other
partials). Federated guide sections (`graphql`,
`database/extensions/wrappers`, `ai/python`, `deployment/terraform`,
`deployment/ci`) and reference docs stay out of scope, and resolution is
capped at 20 pages to keep runtime bounded.
- Replace the single `quickstarts.spec.ts` test with a generic
`docs-pages.spec.ts` that loads whatever pages are resolved, asserting
each renders with an `<h1>` and that its docs-owned links resolve.
- Add `run-e2e-docs.ts` so `pnpm e2e:docs` resolves scope locally (from
commits since `origin/master`, plus staged/unstaged changes) and skips
Playwright entirely when nothing in scope changed.
- Update `.github/workflows/docs-e2e.yml` to widen the trigger paths to
all guides/troubleshooting/partials, resolve scope in a dedicated step,
skip the rest of the job when scope is empty, and accept a `page_paths`
input for manual `workflow_dispatch` runs.
- Rewrite `e2e/docs/README.md` to document the new scoping behavior, the
override envs (`DOCS_E2E_PAGE_PATHS`, `DOCS_E2E_BASE_REF`), and how CI
uses the suite.
- `pnpm e2e:docs:all` is also added to run tests on every page locally.
Good for scoping issues but should not be included in CI.

## Manual testing

Walk through the following steps to verify this works:

- [x] `pnpm e2e:docs` from repo root resolves the expected pages for a
local guide edit and can run against local dev
**Note:** Challenges with testing on local in part because of the long
lag for first page load. Recommendation to use a hosted URL is added to
docs.
- [x] Editing a shared `_partials` file resolves to every page that
includes it (including through nested partials)
- [x] `pnpm e2e:docs` exits cleanly with no Playwright run when no
in-scope files changed
- [x] `git diff --name-only ... | pnpm -C e2e/docs resolve-docs-scope`
prints the expected page list for a sample diff
- [x] Workflow run on a PR that only touches `e2e/docs`/workflow files
skips the Playwright steps
- [x] Manual `workflow_dispatch` run with `page_paths` set tests only
those pages
- [x] Run `pnpm e2e:docs:all` to run the suite on all docs content,
which takes awhile

## Next steps

After this PR merges, we have the scaffolding to add more fun tests like
a11y 😁

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added scoped Docs E2E runs that target eligible doc pages based on
changes, plus manual page-targeted runs and an “all eligible pages”
mode.
* Introduced `DOCS_E2E_PAGE_PATHS` (and updated base ref/base URL
behavior) to control which pages are tested.
* **Bug Fixes**
* Automatically skips Playwright setup when no relevant pages are in
scope; Playwright reporting now uploads only on failure.
* **Documentation**
* Updated the Docs E2E README with new run/CI behavior, troubleshooting
notes, and commands to inspect the resolved page list.
* **Tests**
* Added a Docs-owned pages E2E suite; removed the Next.js quickstart E2E
spec.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 00:04:58 +00:00
Miranda Limonczenko
b5cae478bc fix(docs) Add smoke test for local development without credentials (#48218)
Closes DOCS-1210
Closes DOCS-1209

#48226 needs to merge first for CI failure

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Test coverage and several small bug fixes discovered during
implementation.

## What is the current behavior?

Nothing verified that `pnpm run dev:docs` keeps working without private
credentials.
We value this command working, especially for community contributors.

However, this issue can go undetected by employees at Supabase since
many of us have credentials in place. We do not want this to go a week
before finding and fixing like in the previous instance.

## What is the new behavior?

- **New Playwright test suite**:
`e2e/docs/local-smoke/no-credentials.spec.ts` boots the docs dev server
with zero GitHub App/Supabase secrets and checks 5 routes covering each
known failure point.
- **CI**: a new `local-dev-smoke` job in `docs-tests.yml` runs this
suite with no credentials configured.


## Additional bugs resolved

Setting up this test exposed other issues that are fixed in this PR:

- **Troubleshooting.utils.ts crash** — Unguarded Supabase call pattern,
crashing every troubleshooting article. Added the same guard as previous
fixes.
- **Missing manifest.json** — middleware.ts statically imports
public/markdown/manifest.json, which is gitignored and only generated by
a build step that's skipped in local dev. On a fresh checkout it doesn't
exist, so middleware fails to compile and takes down every page. Fixed
by committing a placeholder [] (real builds still regenerate the full
file).
- **Phantom @code-hike/mdx import** — apps/docs/app/layout.tsx imported
@code-hike/mdx/styles.css, but only apps/www actually declares that
dependency. Worked by accident whenever both apps were installed
together; broke in CI's docs-only install. Turned out to be dead code
(nothing in docs actually uses code-hike), so fixed by deleting the
unused imports rather than adding the dependency.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary by CodeRabbit

* **New Features**
* Added a credential-free “local smoke” end-to-end test suite for key
documentation routes.

* **Bug Fixes**
* Improved troubleshooting behavior when required external service
credentials are missing.
* Updated federated “wrappers” documentation pages to gracefully show a
fallback message when external content can’t be fetched.

* **Tests**
* Added a dedicated local-smoke Playwright runner and enhanced CI
path-based triggering and reporting (failure-focused artifacts).

* **Chores**
* Refined docs workflow path filters and adjusted docs markdown
manifest/ignore rules for generated content.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-24 10:29:12 -07:00
Miranda Limonczenko
9199aad57e feat(docs) Add scaffolding and CI/CD step for Docs Playwright (#48120)
Closes DOCS-1197



## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## Problem

We do not have any E2E testing established. 

## Solution

This PR creates an ultra-lean starting place for Docs Playwright:

- A CI/CD step that skips on draft and relies on Preview for testing
- One simple broken link check for one page

The goal: 
- Playwright is implemented where we want it, with an architecture we
want, with set-up steps we can build from

The anti-goal of this PR:
- We have meaningful tests running

## CI/CD steps

<img width="1191" height="72" alt="Screenshot 2026-07-21 at 10 17 06 AM"
src="https://github.com/user-attachments/assets/eeb2454c-d864-4574-a050-ce39bb3f083f"
/>

1. Checkout a thin slice of the repo (`apps/docs`, `packages`,
`patches`).
2. Wait for the Vercel **docs** preview for that commit SHA.
3. Use that preview URL as `PLAYWRIGHT_BASE_URL`.
4. Install Node deps and Chromium.
5. Run `pnpm run e2e:docs` (`--grep @quickstart`).
6. If anything fails, upload the HTML report + traces.

Manual runs skip the Vercel wait and default to `https://supabase.com`
(or whatever URL you enter), then run the full suite (`pnpm run e2e`).

## What the test checks

Because this PR is scaffolding, it is doing something very basic:

1. Opens `/docs/guides/getting-started/quickstarts/nextjs` only if a
connected file was edited in CI/CD step
2. Asserts the page loaded and the H1 is visible.
3. Collects docs-owned `/docs/**` links from
`#sb-docs-guide-main-article`.
4. HTTP-checks each link (no full navigation) and soft-fails so every
broken link is reported.

Config keeps it cheap: Chromium only, 1 worker, 2 CI retries, failure
screenshots/traces.


## Docs vs Studio/Dashboard

The setup of Docs Playwright differs from Studio.

| | Docs E2E | Studio E2E |
|---|---|---|
| Location |`e2e/docs/` | `e2e/studio/` |
| What it tests | One published docs page + its links | Many Studio UI
flows (tables, auth, storage, …) |
| Where the app runs | Already-deployed **Vercel preview** | Built and
started **on the runner** |
| Backend needed | None | Local Supabase via Docker |
| Path filtering | Native `on.pull_request.paths` (skip whole workflow)
| `dorny/paths-filter` after checkout (workflow starts, heavy steps
gated) |
| Parallelism | 1 worker, no shards | Matrix of frameworks × 2 shards |
| Retries | 2 in CI | 5 in CI |
| Reports | HTML report on failure | Blob reports per shard → merge → PR
comment |
| Draft handling | Explicit draft skip | No draft skip today |
| Manual broader run | Yes (`workflow_dispatch`) | No |

The big conceptual difference: **Studio owns the environment** (build
Studio, start Supabase, hit `localhost`). **Docs borrows Vercel’s
preview** and only asks “does this page and its docs links work on the
deployed site?”

## Docs architecture justification

The docs architecture is deliberately lightweight because docs are
**static, published content served by Vercel**, not an interactive app
with a backend. That single fact justifies every difference:

- **Borrow the Vercel preview instead of building on the runner.** The
preview is already the exact artifact users will see, and Vercel builds
it for free on every PR. Rebuilding docs on the runner would duplicate
that work and risk testing something different from what ships. Studio,
by contrast, needs a running app plus a local Supabase, so it *has* to
own its environment.

- **No backend.** Docs pages don't need a database or auth to render, so
there's nothing to spin up. This is what keeps the job cheap enough to
run per-PR.

- **Native `paths` filtering.** Since the job is cheap and
self-contained, an all-or-nothing skip at the workflow level is
sufficient—no need for `dorny/paths-filter` to gate expensive setup
steps mid-run like Studio does.

- **Low parallelism and modest retries.** One page and its links is a
tiny surface, so 1 worker is plenty and there's no sharding to
coordinate. Retries exist only to absorb transient network flakiness
against a live URL, hence 2 rather than Studio's 5 (which also cushions
a heavier, stateful environment).

- **Non-blocking + draft skip + manual dispatch.** As initial
scaffolding checking link health on a deployed site, it should inform
rather than gate merges, avoid burning minutes on drafts, and still be
runnable on demand against production.

In short: **Studio owns its environment because it must; docs borrows
Vercel's preview because it can.** The scope is intentionally minimal
today.

## Testing

1. Break a docs-owned link in the Next.js quickstart.
1. Follow README instructions to set up and run e2e docs test.
1. Confirm the suite fails.
1. Restore the broken link and re-run.
1. Confirm the suite **passes** (`1 passed`).



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Summary

- **New Features**
- Added a GitHub Actions workflow to run Playwright docs end-to-end
tests on PRs and via manual dispatch (with optional base URL), including
docs-preview waiting and concurrency cancellation.
- **Documentation**
- Added `e2e/docs` README with setup, how to run the suite (including
UI/debug and single-spec), and how base URL selection works.
- **Tests**
- Added a quickstarts E2E spec that validates the page and soft-checks
docs-owned links resolve.
- **Chores**
- Added shared Playwright configuration/package scripts and an
`e2e/docs` `.gitignore` for test outputs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-21 14:59:10 -07:00