Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

scripts/context-startup.test.ts

Raw
import {
	chmodSync,
	mkdirSync,
	mkdtempSync,
	readdirSync,
	readFileSync,
	rmSync,
	writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { pathToFileURL } from "node:url";
import { Agent } from "@earendil-works/pi-agent-core";
import { createAssistantMessageEventStream } from "@earendil-works/pi-ai";
import {
	DefaultResourceLoader,
	estimateTokens,
	formatSkillsForPrompt,
	loadSkills,
	SettingsManager,
} from "@earendil-works/pi-coding-agent";
import { afterEach, expect, it, vi } from "vitest";
import {
	CASES,
	comparable,
	formatOverview,
	measure,
	PROMPT,
	snapshot,
	summarize,
} from "./context-startup.mjs";
import {
	estimateSourceTokens,
	installedPiDist,
	observeRequests,
	publish,
	resourceOptions,
} from "./context-startup-session.mjs";

const message = {
	role: "assistant",
	provider: "test",
	model: "test-model",
	stopReason: "stop",
	usage: { input: 100, cacheRead: 200, cacheWrite: 30, output: 2 },
};
const event = (value = message) =>
	JSON.stringify({ type: "message_end", message: value });
const metadata = {
	cwd: "/project",
	version: "test",
	provider: "test",
	model: "test-model",
	thinking: "high",
	contextWindow: 100000,
};
let directory: string | undefined;
afterEach(() => {
	vi.unstubAllEnvs();
	if (directory) rmSync(directory, { recursive: true, force: true });
	directory = undefined;
});

it("locates installed Pi from PATH without executing it", async () => {
	directory = mkdtempSync(join(tmpdir(), "pi-locator-test-"));
	const bin = join(directory, "bin");
	mkdirSync(bin);
	writeFileSync(
		join(directory, "package.json"),
		JSON.stringify({ name: "@earendil-works/pi-coding-agent" }),
	);
	const executable = join(bin, "pi");
	writeFileSync(executable, "This file must never execute.");
	chmodSync(executable, 0o755);
	vi.stubEnv("PATH", bin);
	expect(await installedPiDist()).toBe(join(directory, "dist"));
});
it("reports missing installed Pi without a repository SDK fallback", async () => {
	directory = mkdtempSync(join(tmpdir(), "pi-locator-test-"));
	vi.stubEnv("PATH", directory);
	await expect(installedPiDist()).rejects.toThrow(
		"Could not locate installed Pi",
	);
});

it("estimates global appendix and visible skill catalog, excluding bodies and rejecting incomplete catalogs", async () => {
	directory = mkdtempSync(join(tmpdir(), "pi-overview-test-"));
	const sdk = { estimateTokens, formatSkillsForPrompt };
	const measureSources = () =>
		estimateSourceTokens(
			directory,
			sdk,
			loadSkills({
				cwd: directory,
				agentDir: directory,
				skillPaths: [join(directory, "skills")],
				includeDefaults: false,
			}),
		);
	writeFileSync(join(directory, "APPEND_SYSTEM.md"), "漢漢漢漢");
	mkdirSync(join(directory, "skills"));
	expect(await measureSources()).toEqual({
		appendix: 1,
		descriptions: [],
		piAgent: { tokens: 0, count: 0 },
		extensions: { tokens: 0, count: 0 },
		shared: 0,
		ignoredProjectSkills: 0,
		catalog: 0,
		total: 1,
	});
	const visible = join(directory, "skills", "visible.md");
	const frontmatter = "---\nname: visible\ndescription: Read & write\n---\n";
	writeFileSync(visible, frontmatter + "Body");
	const result = await measureSources();
	const expectedCatalog = formatSkillsForPrompt([
		{
			name: "visible",
			description: "Read & write",
			filePath: visible,
			baseDir: join(directory, "skills"),
			disableModelInvocation: false,
			sourceInfo: {
				path: visible,
				source: "user",
				scope: "user",
				origin: "top-level",
			},
		},
	]);
	const expectedEntry = expectedCatalog.match(
		/ {2}<skill>[\s\S]*? {2}<\/skill>\n/,
	)?.[0];
	if (!expectedEntry) throw new Error("Fixture catalog missing skill entry");
	expect(result).toEqual({
		appendix: 1,
		descriptions: [{ name: "visible", description: "Read & write", tokens: 3 }],
		piAgent: { tokens: Math.ceil(expectedEntry.length / 4), count: 1 },
		extensions: { tokens: 0, count: 0 },
		shared: Math.ceil((expectedCatalog.length - expectedEntry.length) / 4),
		ignoredProjectSkills: 0,
		catalog: Math.ceil(expectedCatalog.length / 4),
		total: 1 + Math.ceil(expectedCatalog.length / 4),
	});
	writeFileSync(visible, frontmatter + "Long skill body ".repeat(1000));
	writeFileSync(
		join(directory, "skills", "hidden.md"),
		"---\nname: hidden\ndescription: Not injected\ndisable-model-invocation: true\n---\nHidden body",
	);
	expect(await measureSources()).toEqual(result);
	writeFileSync(
		join(directory, "skills", "invalid.md"),
		"---\nname: INVALID\ndescription: Invalid uppercase name\n---\nBody",
	);
	await expect(measureSources()).rejects.toThrow(
		"Skill catalog has diagnostics",
	);
});

it("ranks only visible agent-dir descriptions by length, then name", async () => {
	directory = mkdtempSync(join(tmpdir(), "pi-overview-test-"));
	writeFileSync(join(directory, "APPEND_SYSTEM.md"), "");
	const skill = (
		name: string,
		description: string,
		sourceInfo = { source: "user", scope: "user", origin: "top-level" },
	) => ({
		name,
		description,
		filePath: join(directory, "skills", `${name}.md`),
		disableModelInvocation: false,
		sourceInfo,
	});
	const result = await estimateSourceTokens(
		directory,
		{ estimateTokens, formatSkillsForPrompt },
		{
			diagnostics: [],
			skills: [
				skill("z", "漢漢漢漢"),
				skill("short", "abc"),
				skill("long", "abcde"),
				skill("a", "1234"),
				{ ...skill("hidden", "x".repeat(100)), disableModelInvocation: true },
				skill("package", "x".repeat(100), {
					source: "fixture",
					scope: "user",
					origin: "package",
				}),
				{
					...skill("project", "x".repeat(100), {
						source: "project",
						scope: "project",
						origin: "top-level",
					}),
					filePath: join(directory, "project", "SKILL.md"),
				},
			],
		},
	);
	expect(
		result.descriptions.map(({ name, tokens }) => ({ name, tokens })),
	).toEqual([
		{ name: "long", tokens: 2 },
		{ name: "a", tokens: 1 },
		{ name: "z", tokens: 1 },
		{ name: "short", tokens: 1 },
	]);
});

it("counts cached input exactly once and ignores notices, output, and other events", () => {
	expect(summarize(`notice\nnull\n{}\n${event()}\n`)).toEqual({
		provider: "test",
		model: "test-model",
		inputTokens: 330,
		uncachedInputTokens: 100,
		cacheReadTokens: 200,
		cacheWriteTokens: 30,
		outputTokens: 2,
	});
	expect(
		summarize(
			event({
				...message,
				usage: { input: 100, cacheRead: 0, cacheWrite: 0, output: 2 },
			}),
		).inputTokens,
	).toBe(100);
});
it.each(["", `${event()}\n${event()}`])(
	"rejects missing or multiple responses",
	(stdout) => {
		expect(() => summarize(stdout)).toThrow("Expected one assistant response");
	},
);
it.each(["error", "aborted", "toolUse", "length"])(
	"rejects %s responses",
	(stopReason) => {
		expect(() => summarize(event({ ...message, stopReason }))).toThrow(
			"measurement rejected",
		);
	},
);
it.each([
	undefined,
	{ input: 0, cacheRead: 0, cacheWrite: 0, output: 1 },
	{ ...message.usage, input: -1 },
	{ ...message.usage, cacheRead: "200" },
])("rejects invalid usage", (usage) => {
	expect(() =>
		summarize(event({ ...message, usage } as typeof message)),
	).toThrow("provider token usage");
});
it("uses Pi's character heuristic for system and tool definitions, excluding implementation and display fields", () => {
	const parameters = { type: "object" };
	expect(
		snapshot(
			{
				systemPrompt: "漢漢漢漢",
				tools: [
					{
						name: "read",
						description: "Read",
						parameters,
						label: "SECRET",
						execute() {},
					},
				],
				messages: [],
			},
			estimateTokens,
		),
	).toEqual({
		system: 1,
		tools: Math.ceil(
			JSON.stringify([{ name: "read", description: "Read", parameters }])
				.length / 4,
		),
		messages: 0,
		toolCount: 1,
	});
});
it("uses Pi's per-message rounding and image allowance, excluding message metadata", () => {
	expect(snapshot({}, estimateTokens)).toEqual({
		system: 0,
		tools: 0,
		messages: 0,
		toolCount: 0,
	});
	const messages = [
		{ role: "user", content: "a", timestamp: 0 },
		{
			role: "user",
			content: [
				{ type: "text", text: "abcde" },
				{ type: "image", data: "ignored", mimeType: "image/png" },
			],
			timestamp: 0,
		},
	];
	expect(snapshot({ messages }, estimateTokens).messages).toBe(1203);
	expect(snapshot({ systemPrompt: "abcde" }, estimateTokens).system).toBe(2);
});
it("baseline prevents every discovery route including SYSTEM and APPEND, configured preserves defaults", () => {
	const extensions = [];
	expect(resourceOptions("baseline+1msg", extensions)).toEqual({
		noExtensions: true,
		noSkills: true,
		noPromptTemplates: true,
		noThemes: true,
		noContextFiles: true,
		systemPrompt: "",
		appendSystemPrompt: [],
		extensionFactories: extensions,
	});
	expect(resourceOptions("headless+1msg", extensions)).toEqual({
		extensionFactories: extensions,
	});
});
it.each([
	{ projectTrusted: true, projectPrompts: false },
	{ projectTrusted: true, projectPrompts: true },
	{ projectTrusted: false, projectPrompts: true },
])(
	"removes only agent-dir text resources through Pi's real loader: %j",
	async ({ projectTrusted, projectPrompts }) => {
		directory = mkdtempSync(join(tmpdir(), "pi-overview-test-"));
		vi.stubEnv("HOME", directory);
		vi.stubEnv("USERPROFILE", directory);
		const cwd = join(directory, "project");
		const agentDir = join(directory, "agent");
		const packageDir = join(agentDir, "packages", "fixture");
		const put = (path: string, content: string) => {
			mkdirSync(join(path, ".."), { recursive: true });
			writeFileSync(path, content);
		};
		const skill = (name: string) =>
			`---\nname: ${name}\ndescription: Fixture skill\n---\nFixture body\n`;
		put(join(agentDir, "AGENTS.md"), "Global instructions");
		put(join(agentDir, "SYSTEM.md"), "Global system");
		put(join(agentDir, "APPEND_SYSTEM.md"), "Global append");
		put(join(agentDir, "skills", "global-fixture.md"), skill("global-fixture"));
		put(join(agentDir, "prompts", "global-fixture.md"), "Global template");
		put(join(cwd, "AGENTS.md"), "Project instructions");
		mkdirSync(join(cwd, ".git"));
		put(
			join(cwd, ".pi", "skills", "project-fixture.md"),
			skill("project-fixture"),
		);
		put(join(cwd, ".pi", "prompts", "project-fixture.md"), "Project template");
		if (projectPrompts) {
			put(join(cwd, ".pi", "SYSTEM.md"), "Project system");
			put(join(cwd, ".pi", "APPEND_SYSTEM.md"), "Project append");
		}
		const settingsPath = join(agentDir, "settings.json");
		const settingsText = JSON.stringify({
			packages: [packageDir],
			contextFixture: "unchanged",
		});
		put(settingsPath, settingsText);
		put(
			join(packageDir, "package.json"),
			JSON.stringify({
				name: "context-fixture",
				pi: {
					extensions: ["index.mjs"],
					skills: ["skills"],
					prompts: ["prompts"],
				},
			}),
		);
		put(
			join(packageDir, "index.mjs"),
			`
		import { readFileSync } from 'node:fs';
		export default pi => pi.registerFlag('fixture-setting', {
			type: 'boolean', description: JSON.parse(readFileSync(${JSON.stringify(settingsPath)}, 'utf8')).contextFixture
		});
	`,
		);
		put(
			join(packageDir, "skills", "extension-fixture.md"),
			skill("extension-fixture"),
		);
		put(
			join(packageDir, "prompts", "extension-fixture.md"),
			"Extension template",
		);
		const settingsManager = SettingsManager.create(cwd, agentDir, {
			projectTrusted,
		});
		const load = async (kind: string) => {
			const loader = new DefaultResourceLoader({
				cwd,
				agentDir,
				settingsManager,
				...resourceOptions(kind, [], { cwd, agentDir, projectTrusted }),
			});
			await loader.reload();
			expect(loader.getExtensions().errors).toEqual([]);
			return loader;
		};
		const normal = await load("headless+1msg");
		const stripped = await load("headless+1msg+no_pi_config");
		const dynamicSkill = join(directory, "dynamic-fixture.md");
		put(dynamicSkill, skill("dynamic-fixture"));
		normal.extendResources({
			skillPaths: [
				{
					path: dynamicSkill,
					metadata: {
						source: "extension:fixture",
						scope: "temporary",
						origin: "top-level",
					},
				},
			],
		});
		const sources = await estimateSourceTokens(
			agentDir,
			{ estimateTokens, formatSkillsForPrompt },
			normal.getSkills(),
		);
		expect(sources.piAgent.count).toBe(1);
		expect(sources.extensions.count).toBe(2);
		expect(sources.ignoredProjectSkills).toBe(projectTrusted ? 1 : 0);
		const included = normal
			.getSkills()
			.skills.filter((skill) => skill.sourceInfo.scope !== "project");
		expect(sources.catalog).toBe(
			Math.ceil(formatSkillsForPrompt(included).length / 4),
		);
		expect(sources.shared).toBeGreaterThan(0);
		expect(sources.extensions.tokens).toBeGreaterThan(0);
		const extensionOnly = await estimateSourceTokens(
			agentDir,
			{ estimateTokens, formatSkillsForPrompt },
			{
				skills: included.filter(
					(skill) =>
						skill.sourceInfo.origin === "package" ||
						skill.sourceInfo.source.startsWith("extension:"),
				),
				diagnostics: [],
			},
		);
		expect(extensionOnly.shared).toBe(sources.shared);
		expect(extensionOnly.piAgent).toEqual({ tokens: 0, count: 0 });
		expect(extensionOnly.extensions).toEqual(sources.extensions);
		await expect(
			estimateSourceTokens(
				agentDir,
				{ estimateTokens, formatSkillsForPrompt: () => "changed" },
				normal.getSkills(),
			),
		).rejects.toThrow("Pi skill catalog format changed");
		const unknown = {
			...included[0],
			filePath: join(directory, "unknown.md"),
			sourceInfo: undefined,
		};
		await expect(
			estimateSourceTokens(
				agentDir,
				{ estimateTokens, formatSkillsForPrompt },
				{ skills: [unknown], diagnostics: [] },
			),
		).rejects.toThrow("Unattributed skill source");
		for (const loader of [normal, stripped]) {
			expect(
				loader
					.getExtensions()
					.extensions.find((ext) => ext.flags.has("fixture-setting"))
					?.flags.get("fixture-setting")?.description,
			).toBe("unchanged");
			expect(
				loader
					.getSkills()
					.skills.some((skill) => skill.name === "extension-fixture"),
			).toBe(true);
			expect(
				loader
					.getPrompts()
					.prompts.some((prompt) => prompt.name === "extension-fixture"),
			).toBe(true);
			expect(
				loader
					.getAgentsFiles()
					.agentsFiles.some((file) => file.path === join(cwd, "AGENTS.md")),
			).toBe(true);
			expect(
				loader
					.getSkills()
					.skills.some((skill) => skill.name === "project-fixture"),
			).toBe(projectTrusted);
			expect(
				loader
					.getPrompts()
					.prompts.some((prompt) => prompt.name === "project-fixture"),
			).toBe(projectTrusted);
		}
		expect(stripped.getExtensions().extensions.map((ext) => ext.path)).toEqual(
			normal.getExtensions().extensions.map((ext) => ext.path),
		);
		expect(
			normal
				.getSkills()
				.skills.some((skill) => skill.name === "global-fixture"),
		).toBe(true);
		expect(
			normal
				.getPrompts()
				.prompts.some((prompt) => prompt.name === "global-fixture"),
		).toBe(true);
		expect(
			normal
				.getAgentsFiles()
				.agentsFiles.some((file) => file.path === join(agentDir, "AGENTS.md")),
		).toBe(true);
		for (let i = 0; i < 2; i++) {
			expect(
				stripped
					.getSkills()
					.skills.some((skill) => skill.name === "global-fixture"),
			).toBe(false);
			expect(
				stripped
					.getPrompts()
					.prompts.some((prompt) => prompt.name === "global-fixture"),
			).toBe(false);
			expect(
				stripped
					.getAgentsFiles()
					.agentsFiles.some(
						(file) => file.path === join(agentDir, "AGENTS.md"),
					),
			).toBe(false);
			expect(stripped.getSystemPrompt()).toBe(
				projectTrusted && projectPrompts ? "Project system" : undefined,
			);
			expect(stripped.getAppendSystemPrompt()).toEqual(
				projectTrusted && projectPrompts ? ["Project append"] : [],
			);
			if (i === 0) await stripped.reload();
		}
		expect(readFileSync(settingsPath, "utf8")).toBe(settingsText);
	},
);
it("shows only tokens with explicit heuristic labels and a first-turn estimate diff", () => {
	const rows = CASES.map((kind, i) => ({
		...metadata,
		kind,
		local: {
			system: 1024 * (i + 1),
			tools: 2048,
			messages: i === 1 ? 2 : 1024,
		},
		...(i === 1 ? {} : { inputTokens: [100, 0, 400, 250][i] }),
	}));
	const output = formatOverview(rows);
	expect(output).toContain("Config: +300 tok (+300%)");
	expect(output).toContain("Pi text resources: +150 tok (+60%)");
	expect(output).toContain("headless+1msg+no_pi_config");
	expect(output).not.toMatch(/TUI|tui|WezTerm|KiB|bytes/);
	expect(output).toContain("~sys tok ~tools tok");
	expect(output).toContain("~ = Pi heuristic (chars/4)");
	expect(output).toContain(
		"First turn (~tok): system +1,024 · tools +0 · messages +1,022",
	);
	expect(output).toContain("n/a");
	expect(
		new Set(
			output
				.split("\n")
				.slice(3, 9)
				.map((line) => line.length),
		).size,
	).toBe(1);
	rows[2].model = "different";
	expect(formatOverview(rows)).toContain(
		"Config: n/a (failed or mismatched runs)",
	);
	expect(comparable(rows[0], { ...rows[0], error: "failure" })).toBe(false);
});
it("publishes complete JSON atomically", async () => {
	directory = mkdtempSync(join(tmpdir(), "pi-overview-test-"));
	const result = join(directory, "result.json");
	await publish(result, { error: "startup failed" });
	expect(JSON.parse(readFileSync(result, "utf8"))).toEqual({
		error: "startup failed",
	});
	expect(readdirSync(directory)).toEqual(["result.json"]);
});

it("observes the real Agent stream boundary after context hooks without changing its response", async () => {
	const response = {
		...message,
		role: "assistant" as const,
		api: "openai-responses" as const,
		stopReason: "stop" as const,
		content: [{ type: "text" as const, text: "OK" }],
		timestamp: 0,
		usage: {
			...message.usage,
			totalTokens: 332,
			cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
		},
	};
	const agent = new Agent({
		initialState: {
			model: {
				id: "test-model",
				name: "Test",
				provider: "test",
				api: "openai-responses",
				baseUrl: "https://example.invalid",
				reasoning: false,
				input: ["text"],
				contextWindow: 100000,
				maxTokens: 1000,
				cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
			},
			systemPrompt: "stock",
		},
		transformContext: async (messages) => [
			...messages,
			{ role: "user", content: "injected", timestamp: 0 },
		],
		streamFn: () => {
			const stream = createAssistantMessageEventStream();
			stream.push({ type: "done", reason: "stop", message: response });
			stream.end();
			return stream;
		},
	});
	const observe = vi.fn();
	observeRequests(agent, observe);
	await agent.prompt(PROMPT);
	expect(observe).toHaveBeenCalledTimes(1);
	expect(observe.mock.calls[0][0].messages).toHaveLength(3);
	expect(agent.state.messages.at(-1)?.role).toBe("assistant");
	expect(() => observeRequests({}, observe)).toThrow(
		"Pi stream API unavailable",
	);
});

function fixtures() {
	directory = mkdtempSync(join(tmpdir(), "pi-overview-test-"));
	const cwd = join(directory, "project with spaces");
	mkdirSync(cwd);
	const shared = join(directory, "shared.cjs");
	writeFileSync(
		shared,
		`
		const fs = require('node:fs');
		const path = require('node:path');
		const root = ${JSON.stringify(directory)};
		exports.log = value => fs.appendFileSync(path.join(root, 'calls.jsonl'), JSON.stringify(value) + '\\n');
		exports.result = options => ({ ...${JSON.stringify(metadata)}, cwd: options.cwd, kind: options.kind,
			mode: 'json', hasUI: false,
			local: { system: 1024, tools: 2048, messages: 2, toolCount: 4 },
			...(options.kind === 'headless+0msg' ? {} : { inputTokens: options.kind === 'baseline+1msg' ? 100 : 400 }),
		});
	`,
	);
	const worker = join(directory, "worker.mjs");
	writeFileSync(
		worker,
		`
		import fs from 'node:fs';
		import assert from 'node:assert/strict';
		import shared from ${JSON.stringify(pathToFileURL(shared).href)};
		const options = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
		shared.log({ options });
		assert.equal(process.cwd(), options.cwd);
		if (options.kind === 'baseline+1msg') {
			assert.notEqual(options.agentDir, options.sourceAgentDir);
			assert.deepEqual(fs.readdirSync(options.agentDir), []);
		}
		const fail = process.env.CONTEXT_TEST_FAIL === options.kind;
		const result = fail ? { kind: options.kind, error: 'controlled failure' } : shared.result(options);
		if (process.env.CONTEXT_TEST_FAIL === 'mismatch' && options.kind === 'baseline+1msg') result.model = 'other';
		fs.writeFileSync(options.resultPath, JSON.stringify(result));
	`,
	);
	// No terminal executable or control context is available to these subprocesses.
	vi.stubEnv("PATH", directory);
	vi.stubEnv("WEZTERM_PANE", "");
	const callsPath = join(directory, "calls.jsonl");
	return {
		cwd,
		worker,
		calls: () =>
			readFileSync(callsPath, "utf8")
				.trim()
				.split("\n")
				.map((line) => JSON.parse(line)),
	};
}

it("runs four isolated headless cases without WezTerm, pins selection, and cleans measurement files", async () => {
	const { cwd, worker, calls } = fixtures();
	const result = await measure(cwd, worker);
	expect(result.map((row) => row.kind)).toEqual([
		CASES[1],
		CASES[0],
		CASES[2],
		CASES[3],
	]);
	expect(result.some((row) => row.error)).toBe(false);
	expect(result.every((row) => row.mode === "json" && !row.hasUI)).toBe(true);
	const jobs = calls()
		.filter((call) => call.options)
		.map((call) => call.options);
	expect(
		jobs.slice(1).every((job) => job.selection.model === "test-model"),
	).toBe(true);
	for (const job of jobs) expect(() => readFileSync(job.resultPath)).toThrow();
	expect(jobs).toHaveLength(4);
	expect(jobs[3].agentDir).toBe(jobs[3].sourceAgentDir);
});
it.each([
	"baseline+1msg",
	"headless+1msg",
	"headless+1msg+no_pi_config",
	"mismatch",
])("reports %s failure without fabricated diffs", async (failure) => {
	const { cwd, worker } = fixtures();
	vi.stubEnv("CONTEXT_TEST_FAIL", failure);
	const result = await measure(cwd, worker);
	expect(result.some((row) => row.error)).toBe(true);
	expect(formatOverview(result)).toContain("n/a (failed or mismatched runs)");
});
it("blocks all paid runs when configured startup fails", async () => {
	const { cwd, worker, calls } = fixtures();
	vi.stubEnv("CONTEXT_TEST_FAIL", "headless+0msg");
	const result = await measure(cwd, worker);
	expect(result.every((row) => row.error)).toBe(true);
	expect(calls().filter((call) => call.options)).toHaveLength(1);
});