Skip to content

Commit 63d3adb

Browse files
committed
fix: preserve canonical routing in shared scenarios
1 parent 39dda74 commit 63d3adb

2 files changed

Lines changed: 56 additions & 3 deletions

File tree

packages/runtime-playground/src/browser-actions-runner.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -977,10 +977,13 @@ export async function runBrowserScenarioCommand({
977977
if (unsupported.length > 0) {
978978
throw new Error(`wordpress.browser-scenario browser environment is unsupported: ${unsupported.join(", ")}`)
979979
}
980+
const topology = browserPreviewTopology(args, runtimeSpec, server.serverUrl, server.previewProxyDiagnostics?.targetOrigin)
980981
const runtime = await createPlaywrightBrowserEnvironmentContext(browser, resolved, {
981-
...(runPlan.actions.storageStateImport ? { contextOptions: { storageState: runPlan.actions.storageStateImport.storageState } } : {}),
982+
contextOptions: {
983+
...topology.contextOptions(),
984+
...(runPlan.actions.storageStateImport ? { storageState: runPlan.actions.storageStateImport.storageState } : {}),
985+
},
982986
})
983-
const topology = browserPreviewTopology(args, runtimeSpec, server.serverUrl)
984987
const routeTracker = scenarioRouteTracker = createBrowserPreviewRouteTracker()
985988
if (browserPreviewNeedsContextRouting(topology.networkPolicy)) await routeBrowserPreviewContextNetwork(runtime.context, topology.networkPolicy, topology.origins.localProxyOrigin, routeTracker)
986989
scenarioSession = { browser, requested: requestedEnvironment, resolved, routeTracker, runtime }

tests/browser-actions-environment.browser.test.ts

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { runBrowserActionsCommand, runBrowserScenarioCommand } from "../packages
1010
import { runBrowserProbeCommand } from "../packages/runtime-playground/src/browser-probe-runner.js"
1111
import type { BrowserArtifact } from "../packages/runtime-playground/src/browser-artifacts.js"
1212
import { isBrowserCommandArtifactError } from "../packages/runtime-playground/src/browser-command-artifact-error.js"
13-
import type { PlaygroundCliServer } from "../packages/runtime-playground/src/preview-server.js"
13+
import { closeHttpServer, listenLocalHttpServer, withPreviewProxy, type PlaygroundCliServer } from "../packages/runtime-playground/src/preview-server.js"
1414

1515
const runtimeSpec: RuntimeCreateSpec = {
1616
backend: "wordpress-playground",
@@ -95,6 +95,56 @@ test("authored scenarios preserve init-script and page state from probe collecti
9595
}
9696
})
9797

98+
test("shared probe and actions sessions preserve canonical proxy transport and topology evidence", async () => {
99+
const canonicalHost = "shared-scenario.invalid"
100+
const upstreamRequests: Array<{ host?: string; url?: string }> = []
101+
const upstream = createServer((request, response) => {
102+
upstreamRequests.push({ host: request.headers.host, url: request.url })
103+
response.setHeader("content-type", "text/html")
104+
response.end("<!doctype html><title>Shared canonical scenario</title><button>Continue</button>")
105+
})
106+
const upstreamUrl = await listenLocalHttpServer(upstream)
107+
const proxy = await withPreviewProxy({
108+
playground: { async run() { return { text: "", exitCode: 0 } } },
109+
serverUrl: upstreamUrl,
110+
async [Symbol.asyncDispose]() {},
111+
} satisfies PlaygroundCliServer, 0)
112+
const artifactRoot = await mkdtemp(join(tmpdir(), "wp-codebox-browser-scenario-canonical-"))
113+
const canonicalUrl = `http://${canonicalHost}/preview/`
114+
try {
115+
const result = await runBrowserScenarioCommand({
116+
artifactRoot,
117+
runtimeSpec: { ...runtimeSpec, preview: { siteUrl: canonicalUrl } },
118+
server: proxy,
119+
spec: {
120+
command: "wordpress.browser-scenario",
121+
args: [
122+
`scenario-json=${JSON.stringify({
123+
url: canonicalUrl,
124+
captures: ["performance", "steps", "network"],
125+
prePageScript: "sessionStorage.setItem('shared-scenario-state', 'probe-preserved')",
126+
steps: [{ kind: "evaluate", expression: "({ origin: location.origin, state: sessionStorage.getItem('shared-scenario-state') })", assert: { origin: `http://${canonicalHost}`, state: "probe-preserved" } }],
127+
})}`,
128+
`route-host=${canonicalHost}`,
129+
],
130+
},
131+
})
132+
133+
assert.equal(new URL(result.artifact.canonicalBrowserOrigin!).origin, `http://${canonicalHost}`)
134+
assert.equal(new URL(result.artifact.localProxyOrigin!).origin, new URL(proxy.serverUrl).origin)
135+
assert.equal(new URL(result.artifact.upstreamRuntimeOrigin!).origin, new URL(upstreamUrl).origin)
136+
assert.equal(new URL(result.artifact.summary.finalUrl).hostname, canonicalHost)
137+
assert(upstreamRequests.some((request) => request.host === canonicalHost && request.url === "/preview/"), JSON.stringify(upstreamRequests))
138+
const output = JSON.parse(result.output)
139+
assert.equal(output.scenario.summary.probe.finalUrl, canonicalUrl)
140+
assert.equal(output.scenario.summary.actions.finalUrl, canonicalUrl)
141+
} finally {
142+
await rm(artifactRoot, { recursive: true, force: true })
143+
await proxy[Symbol.asyncDispose]()
144+
await closeHttpServer(upstream)
145+
}
146+
})
147+
98148
test("scenario storage state and auth remain available after probe collection", async () => {
99149
const fixture = await browserFixture()
100150
try {

0 commit comments

Comments
 (0)