mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-24 08:02:14 +03:00
All 10 diagnostics in this file are the `strictNullChecks: false` narrowing limitation: a boolean-literal discriminant narrows the positive branch but leaves the negative one as the full union, so `if (!resolved.ok)` and the code after `if (outcome.success)` could not see `status`/`error`. Three unions, all module-private and untouched by any test, so per the rule recorded on #8499 these are retagged rather than fixed with predicates — predicates are for exported unions whose shape callers depend on: resolveDesignerWebRequest ok: true|false -> state: "resolved"|"invalid" DesignerWebStepResult done + success -> state: "pending"|"ready"|"failed" The step union collapsed two booleans into one discriminant; `done`/`success` encoded three states across two flags, which is also why the pending arm had no `success` property for `outcome.success` to read. Also narrowed runDesignerWebPollLoop's declared return from `DesignerWebStepResult | {…504…}` to a new DesignerWebOutcome (ready | failed). The loop returns a step only after confirming it is terminal, and otherwise synthesizes a 504 — it can never return a pending step, and the old signature claiming it could is what made `.success` unreadable on the union at all. 280 -> 270, zero new, on a line-number-agnostic diff of the full tsc error set. Tests: unlike the previous slices this rewrote real control flow (three conditionals), so the existing suite is doing actual work here — microsoft-designer-web-6672.test.ts drives the handler end-to-end through 400, 401, immediate-ready, poll-then-ready, non-OK upstream and 504-timeout, i.e. every arm but one. The "empty" arm (unrecognized 200 body -> terminal 502) was tested only at the parser level, never through the handler, so the 502 itself was unasserted. Added designer-web-empty-response-502.test.ts (2 tests) pinning that it is terminal (exactly one fetch, no polling) and distinct from the 504 deadline path. Both suites pass against the parent commit too — the tests are black-box through the exported handler, so they are agnostic to the discriminant rename and prove the retag is behavior-preserving. 61/61 across the 3 suites. Co-authored-by: backryun <busan011@ormbiz.co.kr>
68 lines
2.5 KiB
TypeScript
68 lines
2.5 KiB
TypeScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
const { handleDesignerWebImageGeneration } = await import(
|
|
"../../open-sse/handlers/imageGeneration/providers/designerWeb.ts"
|
|
);
|
|
|
|
/**
|
|
* `stepDesignerWebPoll` classifies an unrecognized upstream body as a terminal
|
|
* 502 — the "empty" arm of the step union, alongside pending / ready / upstream
|
|
* failure.
|
|
*
|
|
* `microsoft-designer-web-6672.test.ts` covers every other arm end-to-end
|
|
* (400 no prompt, 401 no token, immediate ready, poll-then-ready, non-OK
|
|
* upstream, 504 timeout) but tests "empty" only at the parser level
|
|
* (`parseDesignerWebResponse: unrecognized shape is 'empty'`) — it never drives
|
|
* the handler with one, so the 502 the handler synthesizes from it was
|
|
* unasserted.
|
|
*/
|
|
|
|
function jsonResponse(status: number, body: unknown) {
|
|
return {
|
|
ok: status >= 200 && status < 300,
|
|
status,
|
|
json: async () => body,
|
|
text: async () => JSON.stringify(body),
|
|
} as Response;
|
|
}
|
|
|
|
const BASE = {
|
|
model: "dall-e-3",
|
|
provider: "microsoft-designer-web",
|
|
providerConfig: { baseUrl: "https://designerapp.officeapps.live.com/designerapp/DallE.ashx" },
|
|
credentials: { apiKey: "tok-abc" },
|
|
};
|
|
|
|
test("a 200 with an unrecognized body is a terminal 502, not a retry", async () => {
|
|
let calls = 0;
|
|
const result = await handleDesignerWebImageGeneration({
|
|
...BASE,
|
|
body: { prompt: "a cat astronaut", timeout_ms: 5_000, poll_interval_ms: 1 },
|
|
fetchImpl: async () => {
|
|
calls += 1;
|
|
return jsonResponse(200, { unexpected: true });
|
|
},
|
|
});
|
|
|
|
assert.equal(result.success, false);
|
|
assert.equal(result.status, 502, "an unparseable success body is a bad-gateway, not a timeout");
|
|
assert.match(String(result.error), /did not contain image data or polling metadata/);
|
|
assert.equal(calls, 1, "the empty classification is terminal — it must not keep polling");
|
|
});
|
|
|
|
test("a 200 with neither images nor polling metadata does not fall through to 504", async () => {
|
|
// The distinction matters: 502 says "the upstream answered with something we
|
|
// cannot use", 504 says "the upstream never finished". A timeout_ms generous
|
|
// enough to allow several polls proves the 502 came from classification, not
|
|
// from the deadline.
|
|
const result = await handleDesignerWebImageGeneration({
|
|
...BASE,
|
|
body: { prompt: "a cat astronaut", timeout_ms: 10_000, poll_interval_ms: 1 },
|
|
fetchImpl: async () => jsonResponse(200, { polling_response: {} }),
|
|
});
|
|
|
|
assert.equal(result.status, 502);
|
|
assert.notEqual(result.status, 504);
|
|
});
|