mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-08 01:14:52 +00:00
fix(desktop): browser_logs reports the HTTP status of each request (#8956)
* fix(desktop): browser_logs reports the HTTP status of each request * test(desktop): browser_logs reports the status the browser recorded * test(desktop): e2e checks browser_logs reports a 404 and a 200 * docs(browser): browser_logs also reports the HTTP status
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { resolve as resolvePath } from "node:path";
|
||||
import { createContext, runInContext } from "node:vm";
|
||||
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
import type {
|
||||
@@ -434,6 +435,26 @@ function containsScript(tab: FakeTab, ...parts: string[]): boolean {
|
||||
return tab.scripts.some((script) => parts.every((part) => script.includes(part)));
|
||||
}
|
||||
|
||||
/**
|
||||
* A browser whose tab runs the network script the host injects against `performance`, the way a
|
||||
* page runs it, so the test sees what the script reads from Chromium's timing entries.
|
||||
*/
|
||||
function browserWithTimingEntries(entries: { resource: unknown[]; navigation: unknown[] }) {
|
||||
const browser = new BrowserAutomationHarness();
|
||||
const fakeAnswer = browser.tab.executeJavaScript.bind(browser.tab);
|
||||
const page = createContext({
|
||||
performance: {
|
||||
getEntriesByType: (type: string) =>
|
||||
type === "navigation" ? entries.navigation : entries.resource,
|
||||
},
|
||||
});
|
||||
browser.tab.executeJavaScript = async (script: string) =>
|
||||
script.includes("performance.getEntriesByType")
|
||||
? runInContext(script, page)
|
||||
: fakeAnswer(script);
|
||||
return browser;
|
||||
}
|
||||
|
||||
function requireSnapshotRefs(result: Awaited<ReturnType<BrowserAutomationHarness["snapshot"]>>) {
|
||||
expect(result).toEqual({
|
||||
requestId: "req-snapshot",
|
||||
@@ -1406,6 +1427,72 @@ describe("executeAutomationCommand", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("logs reports the HTTP status the browser recorded, and none it did not", async () => {
|
||||
const timing = (name: string, initiatorType: string, responseStatus?: number) => ({
|
||||
name,
|
||||
initiatorType,
|
||||
startTime: 1,
|
||||
duration: 2,
|
||||
transferSize: 3,
|
||||
...(responseStatus === undefined ? {} : { responseStatus }),
|
||||
});
|
||||
const browser = browserWithTimingEntries({
|
||||
resource: [
|
||||
timing("https://a.test/api/orders", "fetch", 404),
|
||||
// Chromium reports 0 for a cross-origin response that sends no Timing-Allow-Origin.
|
||||
timing("https://cdn.test/lib.js", "script", 0),
|
||||
// A browser without the field.
|
||||
timing("https://a.test/old.css", "css"),
|
||||
],
|
||||
navigation: [timing("https://a.test/form", "navigation", 200)],
|
||||
});
|
||||
|
||||
const result = await browser.execute({ command: "logs", args: { browserId: BROWSER_A } });
|
||||
|
||||
expect(result).toEqual({
|
||||
requestId: "req-logs",
|
||||
ok: true,
|
||||
result: {
|
||||
command: "logs",
|
||||
browserId: BROWSER_A,
|
||||
console: [],
|
||||
network: [
|
||||
{
|
||||
url: "https://a.test/api/orders",
|
||||
type: "fetch",
|
||||
status: 404,
|
||||
startTime: 1,
|
||||
duration: 2,
|
||||
transferSize: 3,
|
||||
},
|
||||
{
|
||||
url: "https://cdn.test/lib.js",
|
||||
type: "script",
|
||||
startTime: 1,
|
||||
duration: 2,
|
||||
transferSize: 3,
|
||||
},
|
||||
{
|
||||
url: "https://a.test/old.css",
|
||||
type: "css",
|
||||
startTime: 1,
|
||||
duration: 2,
|
||||
transferSize: 3,
|
||||
},
|
||||
{
|
||||
url: "https://a.test/form",
|
||||
method: "GET",
|
||||
type: "navigation",
|
||||
status: 200,
|
||||
startTime: 1,
|
||||
duration: 2,
|
||||
transferSize: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("evaluate returns primitive JSON from the page context", async () => {
|
||||
const browser = new BrowserAutomationHarness();
|
||||
browser.tab.evaluateScriptResult = { ok: true, resultJson: "42" };
|
||||
|
||||
@@ -1628,6 +1628,8 @@ const NETWORK_PERFORMANCE_SCRIPT = String.raw`(() => {
|
||||
url: entry.name,
|
||||
method: entry.initiatorType === 'navigation' ? 'GET' : undefined,
|
||||
type: entry.initiatorType,
|
||||
// 0 when the browser does not say (a cross-origin response without Timing-Allow-Origin).
|
||||
status: typeof entry.responseStatus === 'number' && entry.responseStatus > 0 ? entry.responseStatus : undefined,
|
||||
startTime: entry.startTime,
|
||||
duration: entry.duration,
|
||||
transferSize: typeof entry.transferSize === 'number' ? entry.transferSize : undefined,
|
||||
|
||||
Reference in New Issue
Block a user