Commit Graph

8 Commits

Author SHA1 Message Date
Tim Neutkens e860cec656 test: migrate webdriver callers to next.browser (#93941)
### What?

Migrate remaining direct `next-webdriver` test callers that have a
`NextInstance` to `next.browser()`, and expose the shared `Playwright`
browser type from `e2e-utils`.

### Why?

`NextInstance.browser` should be the supported browser-opening interface
for test fixtures, with `next-webdriver` kept as the private
implementation detail.

### How?

Updated affected development, e2e, and production tests to call
`next.browser()` directly, passing `baseUrl` where tests intentionally
target a manually spawned or proxied server. Shared helpers now receive
browser callbacks from the test context, and browser types import
`Playwright` from `e2e-utils` instead of deriving from `next.browser` or
importing from private paths.

<!-- NEXT_JS_LLM_PR -->
2026-05-22 14:01:58 +02:00
Tim Neutkens 8141dcf12e Convert test/integration to isolated tests (#93247)
### What?

Converts every test under `test/integration/` to an isolated test
running through `nextTestSetup` (under `test/e2e/`, `test/production/`,
`test/development/`, or `test/unit/`), then deletes `test/integration/`
along with the legacy CI orchestration that was specific to it.

- `test/integration/` removed entirely (~327 test suites)
- New isolated suites added across the existing folders:
  - `test/e2e/` — 175
  - `test/production/` — 130
  - `test/development/` — 43
  - `test/unit/` — 1
- `.github/workflows/build_and_test.yml` and `run-tests.js` no longer
have any `integration` branches
- `nextTestSetup` gained a `baseUrl` option on `next.browser()` so a
small number of tests that drive their own proxy/static-export server
can keep using `next.browser(...)` instead of importing `next-webdriver`
directly

### Why?

`test/integration/` predated `nextTestSetup` and ran tests directly
against the source checkout via custom helpers (`launchApp`,
`nextBuild`, `nextStart`, `runNextCommand`, `webdriver`, `fetchViaHTTP`,
…). Each suite hand-rolled its own dev/start/build orchestration,
fixture mutation, and process management.

The isolated test model used by the rest of the repo gives each suite an
isolated working directory containing a packed `next.tgz` install, a
uniform `next.start()` / `next.build()` / `next.fetch()` /
`next.browser()` API, and the same lifecycle for dev, start, and deploy
modes — so a single set of assertions covers all three. Deploy-mode
skips and per-feature gates are expressed declaratively
(`skipDeployment`, `disableAutoSkewProtection`, `if (skipped) return`)
instead of branching on `process.env`.

Removing `test/integration/` lets us:

- Delete the bespoke orchestration code in the CI workflow and
`run-tests.js`
- Run every converted suite consistently in dev, start, and deploy modes
(where applicable)
- Reproduce every test locally with the same `pnpm
test-{dev,start}-{turbo,webpack}` commands; no separate `integration`
path
- Open the door to running `test/production` against deployments in the
future (the converted suites already declare `skipDeployment` so they
can be flipped on)

### How?

Mechanical conversion per suite, with targeted clean-ups:

1. **Per-suite conversion.** Each
`test/integration/<name>/test/index.test.{js,ts}` was rewritten into a
single `<name>.test.ts` under the right folder based on what the
original exercised:
   - `launchApp` / dev-only assertions → `test/development/`
- `nextBuild` + `nextStart` / start-only assertions → `test/production/`
   - Both → `test/e2e/`
- The one pure jsdom render check (`link-without-router`) → `test/unit/`

2. **API mapping.** Custom helpers were replaced by `nextTestSetup`
equivalents: `launchApp` → `next.start()`, `nextBuild` → `next.build()`,
`runNextCommand` → `next.runCommand`, `fetchViaHTTP` → `next.fetch`,
`webdriver(...)` → `next.browser(...)`. Fixture mutations switched from
raw `fs.writeFile`/`fs.rename` to `next.patchFile` (with the 3-arg
`runWithTempContent` callback when the change has a defined scope) and
`next.deleteFile`.

3. **Deploy-mode handling.** Suites that can't run in deploy mode (use
`patchFile` / `next.build()` / depend on local CLI output) declare
`skipDeployment: true` and early-return on the `skipped` boolean. Suites
where Vercel's edge mutates URLs (`&dpl=`, immutable assets) declare
`disableAutoSkewProtection: true`.

4. **`next.browser({ baseUrl })`.** A handful of tests
(`prerender-export`, `cdn-cache-busting`, `preload-viewport`, both
`react-virtualized` suites) need to drive a separate server (a
static-export server or an `http-proxy` instance) rather than the
Next.js process. Instead of importing `next-webdriver` directly, those
tests now pass `{ baseUrl: <port|url> }` to `next.browser()`. For the
proxy cases, the proxy was moved into `server.js` inside the fixture and
`http-proxy` declared via the `dependencies` option of `nextTestSetup`,
so the test runs with a fully isolated dependency graph.

5. **CI clean-up.** With `test/integration` gone, the `test
integration*` jobs and `integration-tests-manifest`-related logic in
`.github/workflows/build_and_test.yml` were removed, and `run-tests.js`
no longer has the `integration` test-folder branch.

6. **Validation.** The PR was iterated against multiple full CI runs;
the remaining failures on the latest run are pre-existing flakes
(segment-cache 60s `act` timeouts in turbopack-prod) or transient
infrastructure issues unrelated to the conversion.
2026-05-11 13:55:47 +02:00
Niklas Mischkulnig 1c1550ca7b tests: Assert dpl query string in all tests for Turbopack (#90592)
Enable skew protection for all start-mode tests when Turbopack is enabled (i.e. not dev). This works by setting `NEXT_DEPLOYMENT_ID` in the test infra

- When running the tests, `packages/next/src/server/lib/router-utils/resolve-routes.ts` now validates that all static asset requests have the correct `?dpl=...` query param value, and returns a 404 if missing.
- It can be disabled with `disableAutoSkewProtection: true` in the test options
- There were various tests that were asserting URLs and were missing the optional `?dpl` at the end.
   - `next.getDeploymentIdQuery()` can be used to get the `?dpl=dpl_123912js` string (or an empty string)
   - `next.getAssetQuery()` currently behaves like `getDeploymentIdQuery`, but will switch to prefer the immutable static token in #88607
2026-02-27 10:06:14 +01:00
Zack Tanner 2f052b16f6 fully remove clientSegmentCache flag (#85541)
Turning this flag off would have already caused client-side invariants
because we deleted all the old codepaths. This fully removes the
remaining plumbing that supported the flag.
2025-10-30 19:49:05 -07:00
Zack Tanner dd5e3ad611 [ci]: move router-act to top level testing utils (#84653)
We're starting to use this pattern in more places, so this moves `router-act` into our top level testing utils.
2025-10-08 17:01:40 -07:00
Andrew Clark 5557bdda51 [Segment Cache] Support third-party redirects in output: "export" mode (#81247)
In output: "export" mode, we can't use headers to request a particular
segment. Instead, we encode the extra request information into the URL.
This is not part of the "public" interface of the app; it's an internal
Next.js implementation detail that the app developer should not need to
concern themselves with.

For example, to request a segment:

- Path passed to <Link>:   /path/to/page
- Path passed to fetch:    /path/to/page/__next-segments/_tree

*(This is not the exact protocol, just an illustration.)*

Before we do that, though, we need to account for redirects. Even in
output: "export" mode, a proxy might redirect the page to a different
location, but we shouldn't assume or expect that they also redirect all
the segment files, too.

To check whether the page is redirected, we perform a range request of
the first N bytes of the HTML document, just enough to verify the
document comes from the same build. The canonical URL is determined from
the response.

Then we can use the canonical URL to request the route tree.

Note: We could embed the route tree into the HTML document, to avoid a
second request. We're not doing that currently because it would make the
HTML document larger and affect normal page loads.
2025-07-03 14:03:33 -04:00
Hendrik Liebau e2837fb3b4 Use onPostpone to determine if segment prefetch is partial (#79299)
When dynamicIO is enabled, missing data is encoded to an infinitely hanging promise, the absence of which we use to determine if a segment is fully static or partially static. However, when dynamicIO is not enabled, this trick doesn't work.

Previously, if PPR is enabled, and dynamicIO is not, we were conservative and assumed that all segments are partial. That doesn't need to be the case, though. We can use the `onPostpone` callback of the `prerender` function to determine if a given RSC node is partial.

To make sure that this works as expected, we're disabling `dynamicIO` in `test/e2e/app-dir/segment-cache/incremental-opt-in`.

Without this change, the following tests would fail because additional requests for the PPR-enabled routes are triggered when `dynamicIO` is disabled:

- `when a link is prefetched with <Link prefetch=true>, no dynamic request is made on navigation`
- `when prefetching with prefetch=true, refetches cache entries that only contain partial data`
- `when prefetching with prefetch=true, refetches partial cache entries even if there's already a pending PPR request`

In addition, we're also disabling `dynamicIO` in `test/e2e/app-dir/segment-cache/client-only-opt-in` as well as
`test/e2e/app-dir/segment-cache/export`, to prepare for an upcoming change where `ppr` will be enabled automatically when `dynamicIO` is enabled. Those three tests are then not compatible with `dynamicIO` because they either rely on the `'incremental'` PPR config, or on `output: 'export'`.
2025-05-17 15:32:40 +02:00
Andrew Clark db0a723db9 [Segment Cache] Support output: "export" mode (#75671)
Adds support for output: "export" mode to the Segment Cache
implementation. We output an additional `.txt` data file per segment per
page. When the client issues a per-segment request, it appends the
segment path to the end of the page URL, rather than passing it as a
request header.

The segment file output follows this convention:

```
/a/b/c.html
/a/b/c/__next.a.txt         <- corresponds to segment /a
/a/b/c/__next.a.b.txt       <- corresponds to segment /a/b
/a/b/c/__next.a.b.c.txt     <- corresponds to segment /a/b/c

... and so on
```

This scheme is designed so that the server can implement patterns like
protection rules or rewrites using just the original path. i.e. by
blocking access to `/a/b`, you also block access to all of its
associated segment data.

Technically it's possible for the segment files to clash with a nested
segment config. We add a `__next` prefix to make a clash less likely.
It's unlikely this will ever be an issue in practice but if needed we
could make this prefix configurable at build time.
2025-02-28 12:46:48 -05:00