dependabot[bot] 04691473d4
chore(deps): bump zod from 3.25.76 to 4.6.6 in /frontend (#7392)
* chore(deps): bump zod from 3.25.76 to 4.6.6 in /frontend

Bumps [zod](https://github.com/colinhacks/zod) from 3.25.76 to 4.6.6.
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](https://github.com/colinhacks/zod/compare/v3.25.76...v4.6.6)

---
updated-dependencies:
- dependency-name: zod
  dependency-version: 4.6.6
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix(frontend): complete Zod 4 migration

Use explicit string keys for extension setting records so the discovery
schema remains assignable to the extension loader contract under Zod 4.
Cover accepted primitives, rejected non-primitive settings and inferred
public types through the discovery API.

Keep Nextra 4.6.1 and its docs theme on their previous Zod 4.3.6 dependency
until upstream fixes required children validation. The app remains on Zod
4.6.6. Document and lock the targeted compatibility overrides.

* docs: keep frontend guidance within hard budget

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-10-24 22:36:41 +08:00

73 lines
2.1 KiB
TypeScript

import { afterEach, expect, rs, test } from "@rstest/core";
import { fetchFrontendExtensions } from "@/core/extensions/api";
import type { FrontendContribution } from "@/core/extensions/contracts";
rs.mock("@/core/config", () => ({ getBackendBaseURL: () => "" }));
rs.mock("@/core/static-mode", () => ({ isStaticWebsiteOnly: () => false }));
rs.mock("@/core/api/static-response", () => ({ staticApiResponse: rs.fn() }));
const entry = {
namespace: "community.bookmarks",
module: "bookmarks.v1",
entry: `/api/plugins/modules/bookmarks.v1/${"a".repeat(64)}.mjs`,
title: "Bookmarks",
description: "",
};
afterEach(() => {
rs.restoreAllMocks();
});
for (const [label, settings] of [
["empty", {}],
[
"mixed primitive",
{
enabled: true,
disabled: false,
limit: 3,
zero: 0,
label: "Bookmarks",
empty: "",
},
],
] as const) {
test(`discovery preserves ${label} settings for the extension loader`, async () => {
const request = rs
.spyOn(globalThis, "fetch")
.mockResolvedValue(
new Response(JSON.stringify([{ ...entry, settings }])),
);
// pnpm typecheck verifies the discovery schema's inferred public contract.
const discovered: FrontendContribution[] = await fetchFrontendExtensions();
expect(discovered).toEqual([{ ...entry, settings }]);
expect(request).toHaveBeenCalledWith(
"/api/plugins",
expect.objectContaining({ credentials: "include", cache: "no-store" }),
);
});
}
for (const [label, settings] of [
["null value", { enabled: null }],
["nested object", { options: { enabled: true } }],
["array value", { options: ["bookmarks"] }],
["null record", null],
["array record", []],
["string record", "enabled"],
["missing record", undefined],
] as const) {
test(`discovery rejects settings with a ${label}`, async () => {
rs.spyOn(globalThis, "fetch").mockResolvedValue(
new Response(JSON.stringify([{ ...entry, settings }])),
);
await expect(fetchFrontendExtensions()).rejects.toMatchObject({
name: "ZodError",
});
});
}