Files
rea/src/domain/javascript/javascriptSemanticAnalysis.response_endpoints.test.ts
T

94 lines
2.8 KiB
TypeScript
Raw Normal View History

import { expect, it } from "vitest";
import { analyzeJavaScriptSemantics } from "./javascriptSemanticAnalysis.js";
const responses = (source: string) =>
analyzeJavaScriptSemantics(source)
.requestOperations.filter(({ kind }) => kind === "response-consumer")
.map(({ method, endpoint, resolution }) => ({
method,
endpoint,
resolution,
}));
it("keeps the endpoint of a uniquely consumed request response", () => {
expect(
responses(`
async function load() {
const a = await fetch("https://example.test/a");
const b = await fetch("https://example.test/b");
return [await a.json(), await b.text()];
}
`),
).toEqual([
{
method: "json",
endpoint: "https://example.test/a",
resolution: "complete",
},
{
method: "text",
endpoint: "https://example.test/b",
resolution: "complete",
},
]);
});
it("leaves an ambiguous response consumer without an endpoint", () => {
expect(
responses(`
async function load(flag) {
let response = await fetch("https://example.test/a");
if (flag) response = await fetch("https://example.test/b");
return response.json();
}
`),
).toEqual([{ method: "json", endpoint: null, resolution: "partial" }]);
});
it("leaves a response replaced by a non-request value without an endpoint", () => {
expect(
responses(`
async function load(cachedResponse) {
let response = await fetch("https://example.test/a");
response = cachedResponse;
return response.json();
}
`),
).toEqual([expect.objectContaining({ method: "json", endpoint: null })]);
});
it.each([
[
"ordered",
`async function load() { const res = await fetch("https://example.invalid/api"); return res.json(); }`,
"https://example.invalid/api",
],
[
"parameter-replaced-before",
`async function load(res) { res = await fetch("https://example.invalid/api"); return res.json(); }`,
"https://example.invalid/api",
],
[
"parameter-conditional",
`async function load(res, maybe) { if (maybe) res = await fetch("https://example.invalid/api"); return res.json(); }`,
null,
],
[
"parameter-later",
`async function load(res) { const value = await res.json(); res = await fetch("https://example.invalid/api"); return value; }`,
null,
],
[
"multiple-requests",
`async function load(maybe) { let res = await fetch("https://example.invalid/a"); if (maybe) res = await fetch("https://example.invalid/b"); return res.json(); }`,
null,
],
] as const)(
"keeps a response endpoint only when its request reaches the read: %s",
(_name, source, endpoint) => {
expect(responses(source)).toEqual([
expect.objectContaining({ method: "json", endpoint }),
]);
},
);