🆙 Fix full cms 🆙
This commit is contained in:
@@ -140,7 +140,7 @@ test.describe("rejects malformed figures", () => {
|
||||
test(name, async ({ request }) => {
|
||||
const response = await getThroughEdge(
|
||||
request,
|
||||
`/api/imaging/avatar${query}`,
|
||||
`/cms_api/imaging/avatar${query}`,
|
||||
);
|
||||
expect(response.status()).toBe(400);
|
||||
});
|
||||
@@ -171,14 +171,14 @@ test("collapses a burst of concurrent requests for one figure", async ({
|
||||
test("the badge endpoint serves an image and revalidates", async ({
|
||||
request,
|
||||
}) => {
|
||||
const first = await getThroughEdge(request, "/api/imaging/badge?code=ADM");
|
||||
const first = await getThroughEdge(request, "/cms_api/imaging/badge?code=ADM");
|
||||
expect(first.status()).toBe(200);
|
||||
expect(first.headers()["content-type"]).toContain("image/");
|
||||
expect(first.headers()["access-control-allow-origin"]).toBe("*");
|
||||
const etag = first.headers().etag;
|
||||
expect(etag).toBeTruthy();
|
||||
|
||||
const second = await getThroughEdge(request, "/api/imaging/badge?code=ADM", {
|
||||
const second = await getThroughEdge(request, "/cms_api/imaging/badge?code=ADM", {
|
||||
headers: { "if-none-match": etag as string },
|
||||
});
|
||||
expect(second.status()).toBe(304);
|
||||
@@ -189,7 +189,7 @@ test("the badge endpoint can resolve from a local source", async ({
|
||||
}) => {
|
||||
const response = await getThroughEdge(
|
||||
request,
|
||||
"/api/imaging/badge?code=ADM&source=local",
|
||||
"/cms_api/imaging/badge?code=ADM&source=local",
|
||||
);
|
||||
expect(response.status()).toBe(200);
|
||||
expect(response.headers()["content-type"]).toContain("image/");
|
||||
@@ -208,7 +208,7 @@ test.describe("rejects malformed badge codes", () => {
|
||||
test(name, async ({ request }) => {
|
||||
const response = await getThroughEdge(
|
||||
request,
|
||||
`/api/imaging/badge${query}`,
|
||||
`/cms_api/imaging/badge${query}`,
|
||||
);
|
||||
expect(response.status()).toBe(400);
|
||||
});
|
||||
@@ -218,7 +218,7 @@ test.describe("rejects malformed badge codes", () => {
|
||||
test("the badge preflight advertises GET", async ({ request }) => {
|
||||
const response = await fetchThroughEdge(
|
||||
request,
|
||||
"/api/imaging/badge?code=ADM",
|
||||
"/cms_api/imaging/badge?code=ADM",
|
||||
{
|
||||
method: "OPTIONS",
|
||||
},
|
||||
|
||||
@@ -71,7 +71,7 @@ export const FIGURE =
|
||||
"hr-11782-40-40.hd-180-7-14.ch-11592-66.lg-10726-79-1408.sh-11764-1408.ha-11958-70-1408.wa-2007-0.0";
|
||||
|
||||
export const avatarPath = (params: Record<string, string> = {}) =>
|
||||
`/api/imaging/avatar?${new URLSearchParams({ figure: FIGURE, ...params })}`;
|
||||
`/cms_api/imaging/avatar?${new URLSearchParams({ figure: FIGURE, ...params })}`;
|
||||
|
||||
/** Public imager endpoint served through the edge proxy (imager container). */
|
||||
export const IMAGER_PATH = (params: Record<string, string> = {}) =>
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
} from "./imaging-target";
|
||||
|
||||
// Regression guard for the public topology: the edge proxy must front the
|
||||
// imager container at `/imaging/*` while `/api/imaging/*` reaches the CMS.
|
||||
// imager container at `/imaging/*` while `/cms_api/imaging/*` reaches the CMS.
|
||||
// Mis-routing here blanks avatars for every visitor, and no unit test sees it.
|
||||
// Only meaningful against the public origin, so it is skipped when the CMS is
|
||||
// reached directly (set `IMAGING_EDGE=1` for the public origin).
|
||||
@@ -40,7 +40,7 @@ test("the CMS avatar endpoint is reachable through the edge", async ({
|
||||
});
|
||||
|
||||
test("the edge does not shadow the CMS badge endpoint", async ({ request }) => {
|
||||
const response = await getThroughEdge(request, "/api/imaging/badge?code=ADM");
|
||||
const response = await getThroughEdge(request, "/cms_api/imaging/badge?code=ADM");
|
||||
expect(response.status()).toBe(200);
|
||||
expect(response.headers()["content-type"]).toContain("image/");
|
||||
});
|
||||
|
||||
@@ -93,7 +93,7 @@ test("staff signs in, saves a draft, previews it and publishes to anonymous read
|
||||
// navigates there explicitly anyway; this asserts the redirect target.
|
||||
await expect(page).toHaveURL(/\/admin\/articles\/new(?:\?|$)/);
|
||||
const session = await context.request
|
||||
.get("/api/auth/session")
|
||||
.get("/cms_api/auth/session")
|
||||
.then((response) => response.json());
|
||||
expect(session.user).toMatchObject({
|
||||
id: String(fixture.userId),
|
||||
@@ -168,7 +168,7 @@ test("staff signs in, saves a draft, previews it and publishes to anonymous read
|
||||
await expect(reader.locator(".error-screen-code")).toHaveText("404");
|
||||
await expect(publicTitle).toHaveCount(0);
|
||||
const listing = await anonymous.request
|
||||
.get("/api/articles")
|
||||
.get("/cms_api/articles")
|
||||
.then((response) => response.json());
|
||||
expect(listing.data).toEqual([]);
|
||||
expect(listing.meta.total).toBe(0);
|
||||
@@ -266,7 +266,7 @@ test("staff signs in, saves a draft, previews it and publishes to anonymous read
|
||||
await expect(reader.locator(".article-body")).toContainText(body);
|
||||
await expect(reader.locator(".error-screen-code")).toHaveCount(0);
|
||||
const listing = await anonymous.request
|
||||
.get("/api/articles")
|
||||
.get("/cms_api/articles")
|
||||
.then((response) => response.json());
|
||||
expect(listing.data).toHaveLength(1);
|
||||
expect(listing.data[0]).toMatchObject({
|
||||
|
||||
@@ -253,7 +253,7 @@ try {
|
||||
LOG_LEVEL: "warn",
|
||||
})
|
||||
.withExposedPorts(3002)
|
||||
.withWaitStrategy(Wait.forHttp("/api/health", 3002).forStatusCode(200))
|
||||
.withWaitStrategy(Wait.forHttp("/cms_api/health", 3002).forStatusCode(200))
|
||||
.withStartupTimeout(120_000)
|
||||
.withLogConsumer((stream) =>
|
||||
stream.on("data", (chunk: Buffer) => {
|
||||
@@ -263,7 +263,7 @@ try {
|
||||
.start();
|
||||
upstream = new URL(`http://${app.getHost()}:${app.getMappedPort(3002)}`);
|
||||
abort.signal.throwIfAborted();
|
||||
const health = (await fetch(new URL("/api/health", upstream), {
|
||||
const health = (await fetch(new URL("/cms_api/health", upstream), {
|
||||
signal: AbortSignal.timeout(10_000),
|
||||
}).then((response) => response.json())) as {
|
||||
status?: string;
|
||||
|
||||
@@ -18,7 +18,7 @@ test("attachment upload and double-click resume send one retry and refresh histo
|
||||
page,
|
||||
}) => {
|
||||
let retries = 0;
|
||||
await page.route("**/api/admin/studio/import-attachment", async (route) => {
|
||||
await page.route("**/cms_api/admin/studio/import-attachment", async (route) => {
|
||||
expect(route.request().method()).toBe("POST");
|
||||
expect(route.request().postData()).toContain('name="classname"');
|
||||
expect(route.request().postData()).toContain("fixture_chair");
|
||||
@@ -27,7 +27,7 @@ test("attachment upload and double-click resume send one retry and refresh histo
|
||||
);
|
||||
await route.fulfill({ json: { ok: true, attachmentId } });
|
||||
});
|
||||
await page.route("**/api/admin/studio/import-jobs", async (route) => {
|
||||
await page.route("**/cms_api/admin/studio/import-jobs", async (route) => {
|
||||
retries++;
|
||||
expect(route.request().method()).toBe("PATCH");
|
||||
expect(route.request().postDataJSON()).toEqual({
|
||||
@@ -82,11 +82,11 @@ for (const scenario of [
|
||||
page,
|
||||
}) => {
|
||||
let retries = 0;
|
||||
await page.route("**/api/admin/studio/import-jobs", async (route) => {
|
||||
await page.route("**/cms_api/admin/studio/import-jobs", async (route) => {
|
||||
retries++;
|
||||
await route.fulfill({ json: { ok: true } });
|
||||
});
|
||||
await page.route("**/api/admin/studio/import-attachment", (route) =>
|
||||
await page.route("**/cms_api/admin/studio/import-attachment", (route) =>
|
||||
scenario.status
|
||||
? route.fulfill({
|
||||
status: scenario.status,
|
||||
|
||||
@@ -33,12 +33,12 @@ const catalog = {
|
||||
};
|
||||
|
||||
async function mockStudio(page: Page) {
|
||||
await page.route("**/api/**", async (route) => {
|
||||
await page.route("**/cms_api/**", async (route) => {
|
||||
const url = new URL(route.request().url());
|
||||
if (url.pathname === "/api/admin/catalog/revision")
|
||||
if (url.pathname === "/cms_api/admin/catalog/revision")
|
||||
return route.fulfill({ json: { ok: true, revision: catalog.revision } });
|
||||
if (
|
||||
url.pathname === "/api/admin/catalog/tree" &&
|
||||
url.pathname === "/cms_api/admin/catalog/tree" &&
|
||||
url.searchParams.get("mode") === "full"
|
||||
)
|
||||
return route.fulfill({
|
||||
|
||||
@@ -241,7 +241,7 @@ const server = createServer(async (req, res) => {
|
||||
}
|
||||
body = JSON.parse(Buffer.concat(chunks).toString() || "{}");
|
||||
}
|
||||
if (url.pathname === "/api/admin/studio/import-jobs") {
|
||||
if (url.pathname === "/cms_api/admin/studio/import-jobs") {
|
||||
if (req.method === "PATCH") {
|
||||
const job = jobs.get(body.id);
|
||||
if (job) job.state = "cancelled";
|
||||
@@ -253,7 +253,7 @@ const server = createServer(async (req, res) => {
|
||||
nextCursor: null,
|
||||
});
|
||||
}
|
||||
if (url.pathname === "/api/admin/import/official/sync-all") {
|
||||
if (url.pathname === "/cms_api/admin/import/official/sync-all") {
|
||||
if (!jobs.has(body.id))
|
||||
jobs.set(body.id, {
|
||||
id: body.id,
|
||||
@@ -279,7 +279,7 @@ const server = createServer(async (req, res) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 150));
|
||||
return json(res, { ok: true, job: jobs.get(body.id) });
|
||||
}
|
||||
if (url.pathname === "/api/media") return json(res, { files: [] });
|
||||
if (url.pathname === "/cms_api/media") return json(res, { files: [] });
|
||||
if (url.pathname.startsWith("/fixture/actions/")) {
|
||||
const name = url.pathname.split("/").at(-1);
|
||||
if (name === "load-recovery")
|
||||
|
||||
@@ -9,7 +9,7 @@ test("history hook deduplicates refreshes, pages and reports completion once", a
|
||||
}) => {
|
||||
let requests = 0;
|
||||
let completed = false;
|
||||
await page.route("**/api/admin/studio/import-jobs?*", async (route) => {
|
||||
await page.route("**/cms_api/admin/studio/import-jobs?*", async (route) => {
|
||||
requests++;
|
||||
const secondPage = new URL(route.request().url()).searchParams.has(
|
||||
"before",
|
||||
@@ -68,7 +68,7 @@ test("history polling pauses while hidden and refreshes on visibility return", a
|
||||
}) => {
|
||||
let requests = 0;
|
||||
await page.clock.install();
|
||||
await page.route("**/api/admin/studio/import-jobs?*", (route) => {
|
||||
await page.route("**/cms_api/admin/studio/import-jobs?*", (route) => {
|
||||
requests++;
|
||||
return route.fulfill({
|
||||
json: { ok: true, jobs: [furnitureJobFixture], nextCursor: null },
|
||||
@@ -102,7 +102,7 @@ test("history polling pauses while hidden and refreshes on visibility return", a
|
||||
test("history shows the current phase and validated recovery source", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.route("**/api/admin/studio/import-jobs?*", (route) =>
|
||||
await page.route("**/cms_api/admin/studio/import-jobs?*", (route) =>
|
||||
route.fulfill({
|
||||
json: {
|
||||
ok: true,
|
||||
@@ -148,10 +148,10 @@ test("uncertain import submissions keep their identity after a page reload", asy
|
||||
page,
|
||||
}) => {
|
||||
const ids: string[] = [];
|
||||
await page.route("**/api/admin/csrf", (route) =>
|
||||
await page.route("**/cms_api/admin/csrf", (route) =>
|
||||
route.fulfill({ json: { token: "a".repeat(64) } }),
|
||||
);
|
||||
await page.route("**/api/admin/studio/import-jobs**", async (route) => {
|
||||
await page.route("**/cms_api/admin/studio/import-jobs**", async (route) => {
|
||||
if (route.request().method() !== "POST") {
|
||||
await route.fulfill({ json: { ok: true, jobs: [], nextCursor: null } });
|
||||
return;
|
||||
|
||||
@@ -12,7 +12,7 @@ test("notification reads persist, new replies are unread and failed preferences
|
||||
let key = "support:42";
|
||||
const readKeys = new Set<string>();
|
||||
let fail = false;
|
||||
await page.route("**/api/notifications**", async (route) => {
|
||||
await page.route("**/cms_api/notifications**", async (route) => {
|
||||
if (route.request().method() === "POST") {
|
||||
if (fail)
|
||||
return route.fulfill({ status: 503, json: { error: "Unavailable" } });
|
||||
@@ -83,7 +83,7 @@ test("notification service failure offers a retry and recovers to empty state",
|
||||
page,
|
||||
}) => {
|
||||
let failing = true;
|
||||
await page.route("**/api/notifications**", (route) =>
|
||||
await page.route("**/cms_api/notifications**", (route) =>
|
||||
route.fulfill(
|
||||
failing
|
||||
? { status: 503, json: { error: "Unavailable" } }
|
||||
@@ -113,7 +113,7 @@ test("category changes persist and pagination recovers when filtering shrinks th
|
||||
page,
|
||||
}) => {
|
||||
let enabled = true;
|
||||
await page.route("**/api/notifications**", async (route) => {
|
||||
await page.route("**/cms_api/notifications**", async (route) => {
|
||||
if (route.request().method() === "POST") {
|
||||
enabled = route.request().postDataJSON().preferences.support;
|
||||
return route.fulfill({ json: { ok: true } });
|
||||
|
||||
@@ -49,11 +49,11 @@ test("the furniture pane is painted, not merely present in the DOM", async ({
|
||||
});
|
||||
const page = await context.newPage();
|
||||
|
||||
await page.route("**/api/**", async (route) => {
|
||||
await page.route("**/cms_api/**", async (route) => {
|
||||
const request = route.request();
|
||||
const url = new URL(request.url());
|
||||
|
||||
if (url.pathname === "/api/admin/import/furni") {
|
||||
if (url.pathname === "/cms_api/admin/import/furni") {
|
||||
return route.fulfill({
|
||||
json:
|
||||
url.searchParams.get("action") === "stats"
|
||||
@@ -64,11 +64,11 @@ test("the furniture pane is painted, not merely present in the DOM", async ({
|
||||
},
|
||||
});
|
||||
}
|
||||
if (url.pathname === "/api/admin/import/clone")
|
||||
if (url.pathname === "/cms_api/admin/import/clone")
|
||||
return route.fulfill({ json: { sources: [] } });
|
||||
if (url.pathname === "/api/admin/studio/import-jobs")
|
||||
if (url.pathname === "/cms_api/admin/studio/import-jobs")
|
||||
return route.fulfill({ json: { ok: true, jobs: [], nextCursor: null } });
|
||||
if (url.pathname === "/api/admin/studio/nitro-quality")
|
||||
if (url.pathname === "/cms_api/admin/studio/nitro-quality")
|
||||
return route.fulfill({
|
||||
json: {
|
||||
report: {
|
||||
|
||||
@@ -13,7 +13,7 @@ const items = Array.from({ length: 60 }, (_, index) => ({
|
||||
iconUrl: "/fixture/cover.svg",
|
||||
}));
|
||||
async function mockStudio(page: Page) {
|
||||
await page.route("**/api/**", async (route) => {
|
||||
await page.route("**/cms_api/**", async (route) => {
|
||||
const url = new URL(route.request().url());
|
||||
if (url.pathname.endsWith("/inspect"))
|
||||
return route.fulfill({
|
||||
@@ -147,7 +147,7 @@ test("an older search response cannot replace newer furniture", async ({
|
||||
page,
|
||||
}) => {
|
||||
await mockStudio(page);
|
||||
await page.route("**/api/admin/import/furni?*", async (route) => {
|
||||
await page.route("**/cms_api/admin/import/furni?*", async (route) => {
|
||||
const search = new URL(route.request().url()).searchParams.get("search");
|
||||
if (!search) return route.fallback();
|
||||
if (search === "old")
|
||||
|
||||
+13
-13
@@ -35,10 +35,10 @@ test("Studio opens and dismisses detail, Nitro editor and import review", async
|
||||
let metadataRequests = 0;
|
||||
let qualityRequests = 0;
|
||||
page.on("pageerror", (error) => errors.push(error.message));
|
||||
await page.route("**/api/**", async (route) => {
|
||||
await page.route("**/cms_api/**", async (route) => {
|
||||
const request = route.request();
|
||||
const url = new URL(request.url());
|
||||
if (url.pathname === "/api/admin/studio/nitro-quality") {
|
||||
if (url.pathname === "/cms_api/admin/studio/nitro-quality") {
|
||||
qualityRequests++;
|
||||
return route.fulfill({
|
||||
json: {
|
||||
@@ -55,7 +55,7 @@ test("Studio opens and dismisses detail, Nitro editor and import review", async
|
||||
},
|
||||
});
|
||||
}
|
||||
if (url.pathname === "/api/admin/studio/inspect") {
|
||||
if (url.pathname === "/cms_api/admin/studio/inspect") {
|
||||
const { classnames } = request.postDataJSON() as { classnames: string[] };
|
||||
return route.fulfill({
|
||||
json: {
|
||||
@@ -71,7 +71,7 @@ test("Studio opens and dismisses detail, Nitro editor and import review", async
|
||||
},
|
||||
});
|
||||
}
|
||||
if (url.pathname === "/api/admin/studio/source-assets") {
|
||||
if (url.pathname === "/cms_api/admin/studio/source-assets") {
|
||||
const body = request.postDataJSON() as {
|
||||
items: Array<{ classname: string }>;
|
||||
};
|
||||
@@ -107,7 +107,7 @@ test("Studio opens and dismisses detail, Nitro editor and import review", async
|
||||
},
|
||||
});
|
||||
}
|
||||
if (url.pathname === "/api/admin/import/furni") {
|
||||
if (url.pathname === "/cms_api/admin/import/furni") {
|
||||
return route.fulfill({
|
||||
json:
|
||||
url.searchParams.get("action") === "stats"
|
||||
@@ -118,9 +118,9 @@ test("Studio opens and dismisses detail, Nitro editor and import review", async
|
||||
},
|
||||
});
|
||||
}
|
||||
if (url.pathname === "/api/admin/import/clone")
|
||||
if (url.pathname === "/cms_api/admin/import/clone")
|
||||
return route.fulfill({ json: { sources: [] } });
|
||||
if (url.pathname === "/api/admin/studio/import-jobs")
|
||||
if (url.pathname === "/cms_api/admin/studio/import-jobs")
|
||||
return route.fulfill({ json: { ok: true, jobs: [], nextCursor: null } });
|
||||
return route.fulfill({
|
||||
status: 404,
|
||||
@@ -220,7 +220,7 @@ test("Studio loads organize imports on demand and preserves the dialog on reopen
|
||||
json: { error: "No mutations expected" },
|
||||
});
|
||||
});
|
||||
await page.route("**/api/**", async (route) => {
|
||||
await page.route("**/cms_api/**", async (route) => {
|
||||
const request = route.request();
|
||||
const url = new URL(request.url());
|
||||
if (request.method() !== "GET") {
|
||||
@@ -230,7 +230,7 @@ test("Studio loads organize imports on demand and preserves the dialog on reopen
|
||||
json: { error: "No mutations expected" },
|
||||
});
|
||||
}
|
||||
if (url.pathname === "/api/admin/import/organize") {
|
||||
if (url.pathname === "/cms_api/admin/import/organize") {
|
||||
organizeRequests++;
|
||||
return route.fulfill({
|
||||
json: {
|
||||
@@ -263,9 +263,9 @@ test("Studio loads organize imports on demand and preserves the dialog on reopen
|
||||
},
|
||||
});
|
||||
}
|
||||
if (url.pathname === "/api/admin/catalog/tree")
|
||||
if (url.pathname === "/cms_api/admin/catalog/tree")
|
||||
return route.fulfill({ json: { pages: [] } });
|
||||
if (url.pathname === "/api/admin/import/furni")
|
||||
if (url.pathname === "/cms_api/admin/import/furni")
|
||||
return route.fulfill({
|
||||
json:
|
||||
url.searchParams.get("action") === "stats"
|
||||
@@ -275,9 +275,9 @@ test("Studio loads organize imports on demand and preserves the dialog on reopen
|
||||
meta: { currentPage: 1, lastPage: 1, total: 0, perPage: 20 },
|
||||
},
|
||||
});
|
||||
if (url.pathname === "/api/admin/import/clone")
|
||||
if (url.pathname === "/cms_api/admin/import/clone")
|
||||
return route.fulfill({ json: { sources: [] } });
|
||||
if (url.pathname === "/api/admin/studio/import-jobs")
|
||||
if (url.pathname === "/cms_api/admin/studio/import-jobs")
|
||||
return route.fulfill({ json: { ok: true, jobs: [], nextCursor: null } });
|
||||
return route.fulfill({
|
||||
status: 404,
|
||||
|
||||
Reference in New Issue
Block a user