Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions config/quality/test-masking-allowlist.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
"tests/unit/video-dashscope.test.ts": {
"replacement": "tests/unit/alibaba-video-media.test.ts",
"reason": "v3.8.49 #8266 reorganized the Alibaba video catalog: the flat wan2.7-t2v id moved out of the plain \"alibaba\" provider (which now only exposes the dated wan2.7-t2v-2026-06-12) and lives only under \"qwen-cloud\" today. All 6 tests in the deleted file built requests against alibaba/wan2.7-t2v, which the new allowlist now rejects with HTTP 400 (verified directly against VIDEO_PROVIDERS in open-sse/config/videoRegistry.ts before deletion). Coverage for this exact id already exists and was confirmed green pre-deletion in tests/unit/alibaba-video-media.test.ts (including an explicit \"Alibaba rejects video models outside its own allowlist\" case for alibaba/wan2.7-t2v) and tests/unit/qwen-cloud-video-media.test.ts (covers the same flat id under qwen-cloud/wan2.7-t2v). Verified legitimate, not masking."
},
"tests/unit/usage-analytics-route-extra.test.ts": {
"replacement": "tests/unit/usage-analytics-route.test.ts",
"reason": "v3.8.49 base-red reconcile: the file was a 100% duplicate — all 10 of its test names exist verbatim (comm -12 verified) among the 22 in tests/unit/usage-analytics-route.test.ts, created by #7700 before #7300 fixed the retention-cutoff fixture only in the main file (reads getUserDatabaseSettings().retention.usageHistory live instead of hardcoding 30d). The stale copy red-failed 'does not double-count raw and aggregated rows' (1 !== 2) against correct production behavior. Zero unique coverage lost; the maintained main file passes 22/22. Verified legitimate, not masking."
}
},
"tests/unit/catalog-updates-v3x.test.ts": "v3.8.45 #6248: fix(providers) remove deprecated MiMo V2 entries — os 5 asserts removidos pinavam specs de modelos mimo-v2-* que deixaram de existir no catálogo (54→49). Asserts seguem a remoção dos modelos, não enfraquecimento. Verificado legítimo. Prune após v3.8.45 mergear para main.",
Expand Down
193 changes: 106 additions & 87 deletions tests/unit/executor-notion-web-thread-sessions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,34 @@ import { describe, it } from "node:test";
import assert from "node:assert/strict";

const mod = await import("../../open-sse/executors/notion-web.ts");
const { __setTlsFetchOverrideForTesting } = await import(
"../../open-sse/services/notionTlsClient.ts"
);

const COOKIE_WITH_SPACE = "token_v2=xyz; space_id=space-1; notion_user_id=user-1";

/** Mock the Chrome-JA3 path used by sendNotionInferenceRequest (not global fetch). */
function installNotionTlsMock(
handler: (url: string, opts: { headers?: Record<string, string>; body?: string }) => Promise<{
status: number;
text: string;
}>
): () => void {
__setTlsFetchOverrideForTesting(async (url, options) => {
const r = await handler(url, {
headers: options.headers as Record<string, string> | undefined,
body: options.body,
});
return {
status: r.status,
headers: new Headers(),
text: r.text,
body: null,
};
});
return () => __setTlsFetchOverrideForTesting(null);
}

describe("Notion thread session continuity", () => {
const {
__resetNotionThreadSessionsForTests,
Expand Down Expand Up @@ -119,50 +144,48 @@ describe("Notion thread session continuity", () => {
const executor = new NotionWebExecutor();
const captured: Array<{ createThread?: boolean; threadId?: string }> = [];
let n = 0;
const originalFetch = globalThis.fetch;
try {
globalThis.fetch = (async (_url: string | URL, opts: RequestInit) => {
const body = JSON.parse(String(opts.body)) as {
createThread?: boolean;
threadId?: string;
const restore = installNotionTlsMock(async (_url, opts) => {
const body = JSON.parse(String(opts.body)) as {
createThread?: boolean;
threadId?: string;
};
captured.push(body);
n++;
if (n === 1) {
return {
status: 200,
text: JSON.stringify({
id: "e1",
type: "error",
message: "Something went wrong. Please try again later.",
subType: "temporarily-unavailable",
isRetryable: false,
}),
};
captured.push(body);
n++;
if (n === 1) {
return new Response(
JSON.stringify({
id: "e1",
type: "error",
message: "Something went wrong. Please try again later.",
subType: "temporarily-unavailable",
isRetryable: false,
}),
{ status: 200 }
);
}
const ndjson = [
JSON.stringify({ type: "patch-start", data: { s: [] } }),
JSON.stringify({
type: "record-map",
recordMap: {
thread_message: {
m1: {
}
const ndjson = [
JSON.stringify({ type: "patch-start", data: { s: [] } }),
JSON.stringify({
type: "record-map",
recordMap: {
thread_message: {
m1: {
value: {
value: {
value: {
step: {
type: "agent-inference",
value: [{ type: "text", content: "recovered" }],
},
step: {
type: "agent-inference",
value: [{ type: "text", content: "recovered" }],
},
},
},
},
},
}),
].join("\n");
return new Response(ndjson, { status: 200 });
}) as typeof fetch;

},
}),
].join("\n");
return { status: 200, text: ndjson };
});
try {
const result = await executor.execute({
model: "fable-5",
body: { messages: turn1 },
Expand All @@ -178,7 +201,7 @@ describe("Notion thread session continuity", () => {
const json = (await result.response.json()) as { choices?: { message?: { content?: string } }[] };
assert.match(String(json.choices?.[0]?.message?.content || ""), /recovered/);
} finally {
globalThis.fetch = originalFetch;
restore();
__resetNotionThreadSessionsForTests();
}
});
Expand Down Expand Up @@ -206,33 +229,31 @@ describe("Notion thread session continuity", () => {
__resetNotionThreadSessionsForTests();
const executor = new mod.NotionWebExecutor();
const captured: Array<{ createThread?: boolean; threadId?: string }> = [];
const originalFetch = globalThis.fetch;
try {
globalThis.fetch = (async (_url: string | URL, opts: RequestInit) => {
captured.push(JSON.parse(String(opts.body)));
const ndjson = [
JSON.stringify({ type: "patch-start", data: { s: [] } }),
JSON.stringify({
type: "record-map",
recordMap: {
thread_message: {
m1: {
const restore = installNotionTlsMock(async (_url, opts) => {
captured.push(JSON.parse(String(opts.body)));
const ndjson = [
JSON.stringify({ type: "patch-start", data: { s: [] } }),
JSON.stringify({
type: "record-map",
recordMap: {
thread_message: {
m1: {
value: {
value: {
value: {
step: {
type: "agent-inference",
value: [{ type: "text", content: "ok" }],
},
step: {
type: "agent-inference",
value: [{ type: "text", content: "ok" }],
},
},
},
},
},
}),
].join("\n");
return new Response(ndjson, { status: 200 });
}) as typeof fetch;

},
}),
].join("\n");
return { status: 200, text: ndjson };
});
try {
const r1 = await executor.execute({
model: "fable-5",
body: { messages: [{ role: "user", content: "hello continuity" }] },
Expand Down Expand Up @@ -265,7 +286,7 @@ describe("Notion thread session continuity", () => {
assert.equal(captured[1].createThread, false);
assert.equal(captured[1].threadId, t1);
} finally {
globalThis.fetch = originalFetch;
restore();
__resetNotionThreadSessionsForTests();
}
});
Expand All @@ -276,38 +297,36 @@ describe("Notion thread session continuity", () => {
const pinned = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
let capturedCreateThread: boolean | undefined;
let capturedThreadId: string | undefined;
const originalFetch = globalThis.fetch;
try {
globalThis.fetch = (async (_url: string | URL, opts: RequestInit) => {
const body = JSON.parse(String(opts.body)) as {
createThread?: boolean;
threadId?: string;
};
capturedCreateThread = body.createThread;
capturedThreadId = body.threadId;
const ndjson = [
JSON.stringify({ type: "patch-start", data: { s: [] } }),
JSON.stringify({
type: "record-map",
recordMap: {
thread_message: {
m1: {
const restore = installNotionTlsMock(async (_url, opts) => {
const body = JSON.parse(String(opts.body)) as {
createThread?: boolean;
threadId?: string;
};
capturedCreateThread = body.createThread;
capturedThreadId = body.threadId;
const ndjson = [
JSON.stringify({ type: "patch-start", data: { s: [] } }),
JSON.stringify({
type: "record-map",
recordMap: {
thread_message: {
m1: {
value: {
value: {
value: {
step: {
type: "agent-inference",
value: [{ type: "text", content: "ok" }],
},
step: {
type: "agent-inference",
value: [{ type: "text", content: "ok" }],
},
},
},
},
},
}),
].join("\n");
return new Response(ndjson, { status: 200 });
}) as typeof fetch;

},
}),
].join("\n");
return { status: 200, text: ndjson };
});
try {
// Real ExecuteInput shape: clientHeaders only (headers is undefined).
const result = await executor.execute({
model: "fable-5",
Expand All @@ -323,7 +342,7 @@ describe("Notion thread session continuity", () => {
// Client-supplied thread id must force follow-up mode (createThread=false).
assert.equal(capturedCreateThread, false);
} finally {
globalThis.fetch = originalFetch;
restore();
__resetNotionThreadSessionsForTests();
}
});
Expand Down
Loading
Loading