minutework 0.1.32 → 0.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/claude-local/skills/README.md +2 -0
- package/assets/claude-local/skills/app-pack-authoring/SKILL.md +14 -1
- package/assets/claude-local/skills/contract-first-public-intake/SKILL.md +11 -3
- package/assets/claude-local/skills/generated-workspace-architecture/SKILL.md +10 -3
- package/assets/claude-local/skills/published-web-and-mw-core-site/SKILL.md +9 -6
- package/assets/claude-local/skills/standalone-mobile-client/SKILL.md +5 -4
- package/assets/templates/next-tenant-app/README.md +26 -138
- package/assets/templates/next-tenant-app/package.json +1 -0
- package/assets/templates/next-tenant-app/src/app/app/demo/page.tsx +15 -0
- package/assets/templates/next-tenant-app/src/app/app/layout.tsx +1 -4
- package/assets/templates/next-tenant-app/src/app/app/page.tsx +2 -17
- package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.tsx +9 -67
- package/assets/templates/next-tenant-app/src/app/blog/page.tsx +10 -46
- package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.tsx +9 -65
- package/assets/templates/next-tenant-app/src/app/docs/page.tsx +10 -46
- package/assets/templates/next-tenant-app/src/app/layout.tsx +8 -10
- package/assets/templates/next-tenant-app/src/app/login/page.tsx +3 -23
- package/assets/templates/next-tenant-app/src/app/page.tsx +11 -44
- package/assets/templates/next-tenant-app/src/app/pricing/page.tsx +10 -44
- package/assets/templates/next-tenant-app/src/app/providers.tsx +2 -1
- package/assets/templates/next-tenant-app/src/app/robots.ts +7 -18
- package/assets/templates/next-tenant-app/src/app/sitemap.ts +4 -39
- package/assets/templates/next-tenant-app/src/features/auth/components/login-screen.tsx +97 -98
- package/assets/templates/next-tenant-app/src/features/dashboard/components/tenant-dashboard.tsx +43 -78
- package/assets/templates/next-tenant-app/src/features/demo/components/manifest-demo.tsx +89 -0
- package/assets/templates/next-tenant-app/src/features/public-shell/components/static-public-page.tsx +58 -0
- package/assets/templates/next-tenant-app/src/features/shell/components/private-app-shell.tsx +48 -552
- package/assets/templates/next-tenant-app/src/lib/app-routes.ts +2 -2
- package/assets/templates/next-tenant-app/src/lib/public-site.ts +5 -30
- package/assets/templates/next-tenant-app/src/mw/client.ts +18 -0
- package/assets/templates/next-tenant-app/src/mw/mock.test.ts +21 -0
- package/assets/templates/next-tenant-app/src/mw/mock.ts +35 -0
- package/assets/templates/next-tenant-app/src/mw/provider.tsx +17 -0
- package/assets/templates/next-tenant-app/template.json +3 -3
- package/assets/templates/next-tenant-app/template.schema.json +1 -0
- package/assets/templates/next-tenant-app/tools/template/validate-route-contract.mjs +4 -5
- package/package.json +2 -2
- package/vendor/workspace-mcp/types.d.ts +4 -0
- package/assets/templates/next-tenant-app/src/app/(cms)/[...path]/page.tsx +0 -89
- package/assets/templates/next-tenant-app/src/app/api/auth/context/route.test.ts +0 -90
- package/assets/templates/next-tenant-app/src/app/api/auth/context/route.ts +0 -78
- package/assets/templates/next-tenant-app/src/app/api/auth/login/route.ts +0 -31
- package/assets/templates/next-tenant-app/src/app/api/auth/logout/route.ts +0 -16
- package/assets/templates/next-tenant-app/src/app/api/auth/password-change/route.test.ts +0 -79
- package/assets/templates/next-tenant-app/src/app/api/auth/password-change/route.ts +0 -40
- package/assets/templates/next-tenant-app/src/app/api/auth/password-status/route.test.ts +0 -42
- package/assets/templates/next-tenant-app/src/app/api/auth/password-status/route.ts +0 -29
- package/assets/templates/next-tenant-app/src/app/api/auth/session/route.ts +0 -26
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/[runId]/route.test.ts +0 -40
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/[runId]/route.ts +0 -47
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/route.test.ts +0 -43
- package/assets/templates/next-tenant-app/src/app/api/gateway/commands/route.ts +0 -45
- package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.test.ts +0 -83
- package/assets/templates/next-tenant-app/src/app/app/examples/runtime-commands/page.tsx +0 -30
- package/assets/templates/next-tenant-app/src/app/app/page.test.ts +0 -62
- package/assets/templates/next-tenant-app/src/app/app/private-content-source.test.ts +0 -88
- package/assets/templates/next-tenant-app/src/app/blog/[slug]/page.test.ts +0 -70
- package/assets/templates/next-tenant-app/src/app/blog/page.test.ts +0 -46
- package/assets/templates/next-tenant-app/src/app/docs/[...slug]/page.test.ts +0 -70
- package/assets/templates/next-tenant-app/src/app/docs/page.test.ts +0 -46
- package/assets/templates/next-tenant-app/src/app/login/page.test.ts +0 -55
- package/assets/templates/next-tenant-app/src/app/page.test.ts +0 -90
- package/assets/templates/next-tenant-app/src/app/pricing/page.test.ts +0 -59
- package/assets/templates/next-tenant-app/src/app/robots.test.ts +0 -40
- package/assets/templates/next-tenant-app/src/app/sitemap.test.ts +0 -63
- package/assets/templates/next-tenant-app/src/features/examples/runtime-command-demo/components/runtime-command-demo.tsx +0 -342
- package/assets/templates/next-tenant-app/src/features/public-shell/components/content-article.tsx +0 -66
- package/assets/templates/next-tenant-app/src/features/public-shell/components/content-collection.tsx +0 -108
- package/assets/templates/next-tenant-app/src/features/public-shell/components/marketing-page-canvas.tsx +0 -111
- package/assets/templates/next-tenant-app/src/features/public-shell/components/public-site-shell.tsx +0 -111
- package/assets/templates/next-tenant-app/src/features/public-shell/components/section-renderer.test.ts +0 -38
- package/assets/templates/next-tenant-app/src/features/public-shell/components/section-renderer.tsx +0 -145
- package/assets/templates/next-tenant-app/src/lib/content/__fixtures__/public-site-snapshot.ts +0 -189
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.test.ts +0 -444
- package/assets/templates/next-tenant-app/src/lib/content/adapter.server.ts +0 -383
- package/assets/templates/next-tenant-app/src/lib/content/contracts.test.ts +0 -138
- package/assets/templates/next-tenant-app/src/lib/content/contracts.ts +0 -399
- package/assets/templates/next-tenant-app/src/lib/content/custom-adapter.ts +0 -5
- package/assets/templates/next-tenant-app/src/lib/content/empty-state.ts +0 -96
- package/assets/templates/next-tenant-app/src/lib/content/release-manifest.test.ts +0 -93
- package/assets/templates/next-tenant-app/src/lib/content/release-manifest.ts +0 -123
- package/assets/templates/next-tenant-app/src/lib/platform/auth.server.test.ts +0 -75
- package/assets/templates/next-tenant-app/src/lib/platform/auth.server.ts +0 -25
- package/assets/templates/next-tenant-app/src/lib/platform/client.server.test.ts +0 -170
- package/assets/templates/next-tenant-app/src/lib/platform/client.server.ts +0 -661
- package/assets/templates/next-tenant-app/src/lib/platform/contracts.ts +0 -131
- package/assets/templates/next-tenant-app/src/lib/platform/endpoints.server.ts +0 -34
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.test.ts +0 -211
- package/assets/templates/next-tenant-app/src/lib/platform/env.server.ts +0 -151
- package/assets/templates/next-tenant-app/src/lib/platform/route-response.ts +0 -33
- package/assets/templates/next-tenant-app/src/lib/platform/session.server.ts +0 -108
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
const notFound = vi.fn(() => {
|
|
4
|
-
throw new Error("notFound");
|
|
5
|
-
});
|
|
6
|
-
const getEntry = vi.fn();
|
|
7
|
-
const getSiteConfig = vi.fn();
|
|
8
|
-
const listEntries = vi.fn();
|
|
9
|
-
|
|
10
|
-
vi.mock("next/navigation", () => ({
|
|
11
|
-
notFound,
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
vi.mock("@/features/public-shell/components/content-article", () => ({
|
|
15
|
-
ContentArticle: () => null,
|
|
16
|
-
}));
|
|
17
|
-
|
|
18
|
-
vi.mock("@/features/public-shell/components/public-site-shell", () => ({
|
|
19
|
-
PublicSiteShell: ({ children }: { children: unknown }) => children,
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
vi.mock("@/lib/content/adapter.server", () => ({
|
|
23
|
-
getEntry,
|
|
24
|
-
getSiteConfig,
|
|
25
|
-
listEntries,
|
|
26
|
-
}));
|
|
27
|
-
|
|
28
|
-
describe("docs article page", () => {
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
vi.clearAllMocks();
|
|
31
|
-
vi.resetModules();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("returns notFound for unknown docs slugs", async () => {
|
|
35
|
-
getSiteConfig.mockResolvedValue({
|
|
36
|
-
collections: {
|
|
37
|
-
docs: {
|
|
38
|
-
title: "Starter Docs",
|
|
39
|
-
description: "Docs",
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
siteName: "MinuteWork Combined Starter",
|
|
43
|
-
});
|
|
44
|
-
getEntry.mockResolvedValue(null);
|
|
45
|
-
|
|
46
|
-
const page = await import("./page");
|
|
47
|
-
|
|
48
|
-
await expect(
|
|
49
|
-
page.default({
|
|
50
|
-
params: Promise.resolve({ slug: ["missing-entry"] }),
|
|
51
|
-
}),
|
|
52
|
-
).rejects.toThrow("notFound");
|
|
53
|
-
expect(notFound).toHaveBeenCalledTimes(1);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("derives static params from published docs entries", async () => {
|
|
57
|
-
listEntries.mockResolvedValue([
|
|
58
|
-
{ slug: ["guides", "public-site-content"] },
|
|
59
|
-
{ slug: ["reference", "api"] },
|
|
60
|
-
]);
|
|
61
|
-
|
|
62
|
-
const page = await import("./page");
|
|
63
|
-
|
|
64
|
-
await expect(page.generateStaticParams()).resolves.toEqual([
|
|
65
|
-
{ slug: ["guides", "public-site-content"] },
|
|
66
|
-
{ slug: ["reference", "api"] },
|
|
67
|
-
]);
|
|
68
|
-
expect(page.dynamicParams).toBe(false);
|
|
69
|
-
});
|
|
70
|
-
});
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
const getSiteConfig = vi.fn();
|
|
4
|
-
const listEntries = vi.fn();
|
|
5
|
-
|
|
6
|
-
vi.mock("@/features/public-shell/components/content-collection", () => ({
|
|
7
|
-
ContentCollection: () => null,
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
|
-
vi.mock("@/features/public-shell/components/public-site-shell", () => ({
|
|
11
|
-
PublicSiteShell: ({ children }: { children: unknown }) => children,
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
vi.mock("@/lib/content/adapter.server", () => ({
|
|
15
|
-
getSiteConfig,
|
|
16
|
-
listEntries,
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
vi.mock("next/navigation", () => ({
|
|
20
|
-
notFound: vi.fn(),
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
describe("docs index page", () => {
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
vi.clearAllMocks();
|
|
26
|
-
vi.resetModules();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("renders the public docs collection", async () => {
|
|
30
|
-
getSiteConfig.mockResolvedValue({
|
|
31
|
-
collections: {
|
|
32
|
-
docs: {
|
|
33
|
-
eyebrow: "Docs",
|
|
34
|
-
title: "Starter Docs",
|
|
35
|
-
description: "Route content through the adapter seam.",
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
listEntries.mockResolvedValue([]);
|
|
40
|
-
|
|
41
|
-
const page = await import("./page");
|
|
42
|
-
|
|
43
|
-
await expect(page.default()).resolves.toBeDefined();
|
|
44
|
-
expect(listEntries).toHaveBeenCalledWith("docs");
|
|
45
|
-
});
|
|
46
|
-
});
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
const redirect = vi.fn((href: string) => {
|
|
4
|
-
throw new Error(`redirect:${href}`);
|
|
5
|
-
});
|
|
6
|
-
const resolveCurrentSession = vi.fn();
|
|
7
|
-
const readPlatformAuthState = vi.fn();
|
|
8
|
-
|
|
9
|
-
vi.mock("next/navigation", () => ({
|
|
10
|
-
redirect,
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
|
-
vi.mock("@/features/auth/components/login-screen", () => ({
|
|
14
|
-
LoginScreen: () => null,
|
|
15
|
-
}));
|
|
16
|
-
|
|
17
|
-
vi.mock("@/lib/platform/client.server", () => ({
|
|
18
|
-
resolveCurrentSession,
|
|
19
|
-
}));
|
|
20
|
-
|
|
21
|
-
vi.mock("@/lib/platform/endpoints.server", () => ({
|
|
22
|
-
platformAuthEndpoints: {
|
|
23
|
-
operatorConsole: "http://127.0.0.1:8000/ops/login/",
|
|
24
|
-
},
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
vi.mock("@/lib/platform/env.server", () => ({
|
|
28
|
-
env: {
|
|
29
|
-
MW_TEMPLATE_APP_NAME: "MinuteWork Combined Starter",
|
|
30
|
-
},
|
|
31
|
-
}));
|
|
32
|
-
|
|
33
|
-
vi.mock("@/lib/platform/session.server", () => ({
|
|
34
|
-
readPlatformAuthState,
|
|
35
|
-
}));
|
|
36
|
-
|
|
37
|
-
describe("login page", () => {
|
|
38
|
-
beforeEach(() => {
|
|
39
|
-
vi.clearAllMocks();
|
|
40
|
-
vi.resetModules();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("redirects authenticated users back to the home shell", async () => {
|
|
44
|
-
readPlatformAuthState.mockResolvedValue({
|
|
45
|
-
sessionId: "session-1",
|
|
46
|
-
csrfToken: "csrf-1",
|
|
47
|
-
});
|
|
48
|
-
resolveCurrentSession.mockResolvedValue({ authenticated: true });
|
|
49
|
-
|
|
50
|
-
const page = await import("./page");
|
|
51
|
-
|
|
52
|
-
await expect(page.default()).rejects.toThrow("redirect:/app");
|
|
53
|
-
expect(redirect).toHaveBeenCalledWith("/app");
|
|
54
|
-
});
|
|
55
|
-
});
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
const getMarketingPage = vi.fn();
|
|
4
|
-
const getSiteConfig = vi.fn();
|
|
5
|
-
const redirect = vi.fn();
|
|
6
|
-
const originalPublicContentSource = process.env.MW_PUBLIC_CONTENT_SOURCE;
|
|
7
|
-
|
|
8
|
-
vi.mock("@/features/public-shell/components/marketing-page-canvas", () => ({
|
|
9
|
-
MarketingPageCanvas: () => null,
|
|
10
|
-
}));
|
|
11
|
-
|
|
12
|
-
vi.mock("@/features/public-shell/components/public-site-shell", () => ({
|
|
13
|
-
PublicSiteShell: ({ children }: { children: unknown }) => children,
|
|
14
|
-
}));
|
|
15
|
-
|
|
16
|
-
vi.mock("@/lib/content/adapter.server", () => ({
|
|
17
|
-
getMarketingPage,
|
|
18
|
-
getSiteConfig,
|
|
19
|
-
}));
|
|
20
|
-
|
|
21
|
-
vi.mock("next/navigation", () => ({
|
|
22
|
-
redirect,
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
describe("home page", () => {
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
if (originalPublicContentSource === undefined) {
|
|
28
|
-
delete process.env.MW_PUBLIC_CONTENT_SOURCE;
|
|
29
|
-
} else {
|
|
30
|
-
process.env.MW_PUBLIC_CONTENT_SOURCE = originalPublicContentSource;
|
|
31
|
-
}
|
|
32
|
-
vi.clearAllMocks();
|
|
33
|
-
vi.resetModules();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
afterEach(() => {
|
|
37
|
-
if (originalPublicContentSource === undefined) {
|
|
38
|
-
delete process.env.MW_PUBLIC_CONTENT_SOURCE;
|
|
39
|
-
} else {
|
|
40
|
-
process.env.MW_PUBLIC_CONTENT_SOURCE = originalPublicContentSource;
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it("renders public home content without auth redirects", async () => {
|
|
45
|
-
getSiteConfig.mockResolvedValue({
|
|
46
|
-
siteName: "MinuteWork Combined Starter",
|
|
47
|
-
siteDescription: "Combined starter",
|
|
48
|
-
primaryCta: { label: "Sign In", href: "/login" },
|
|
49
|
-
secondaryCta: { label: "Docs", href: "/docs" },
|
|
50
|
-
});
|
|
51
|
-
getMarketingPage.mockResolvedValue({
|
|
52
|
-
pageKey: "home",
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const page = await import("./page");
|
|
56
|
-
|
|
57
|
-
await expect(page.default()).resolves.toBeDefined();
|
|
58
|
-
expect(getSiteConfig).toHaveBeenCalledTimes(1);
|
|
59
|
-
expect(getMarketingPage).toHaveBeenCalledWith("home");
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it("renders the built-in empty home shell when no home page has been published", async () => {
|
|
63
|
-
getSiteConfig.mockResolvedValue({
|
|
64
|
-
siteName: "MinuteWork Combined Starter",
|
|
65
|
-
siteDescription: "Combined starter",
|
|
66
|
-
primaryCta: { label: "Sign In", href: "/login" },
|
|
67
|
-
secondaryCta: { label: "Docs", href: "/docs" },
|
|
68
|
-
});
|
|
69
|
-
getMarketingPage.mockResolvedValue(null);
|
|
70
|
-
|
|
71
|
-
const page = await import("./page");
|
|
72
|
-
|
|
73
|
-
await expect(page.default()).resolves.toBeDefined();
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it("redirects the private-only root route to /app", async () => {
|
|
77
|
-
vi.resetModules();
|
|
78
|
-
process.env.MW_PUBLIC_CONTENT_SOURCE = "none";
|
|
79
|
-
redirect.mockImplementation(() => {
|
|
80
|
-
throw new Error("NEXT_REDIRECT");
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
const page = await import("./page");
|
|
84
|
-
|
|
85
|
-
await expect(page.default()).rejects.toThrow("NEXT_REDIRECT");
|
|
86
|
-
expect(redirect).toHaveBeenCalledWith("/app");
|
|
87
|
-
expect(getSiteConfig).not.toHaveBeenCalled();
|
|
88
|
-
expect(getMarketingPage).not.toHaveBeenCalled();
|
|
89
|
-
});
|
|
90
|
-
});
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
const getMarketingPage = vi.fn();
|
|
4
|
-
const getSiteConfig = vi.fn();
|
|
5
|
-
|
|
6
|
-
vi.mock("@/features/public-shell/components/marketing-page-canvas", () => ({
|
|
7
|
-
MarketingPageCanvas: () => null,
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
|
-
vi.mock("@/features/public-shell/components/public-site-shell", () => ({
|
|
11
|
-
PublicSiteShell: ({ children }: { children: unknown }) => children,
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
vi.mock("@/lib/content/adapter.server", () => ({
|
|
15
|
-
getMarketingPage,
|
|
16
|
-
getSiteConfig,
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
vi.mock("next/navigation", () => ({
|
|
20
|
-
notFound: vi.fn(),
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
describe("pricing page", () => {
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
vi.clearAllMocks();
|
|
26
|
-
vi.resetModules();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("renders seeded pricing content", async () => {
|
|
30
|
-
getSiteConfig.mockResolvedValue({
|
|
31
|
-
siteName: "MinuteWork Combined Starter",
|
|
32
|
-
siteDescription: "Combined starter",
|
|
33
|
-
primaryCta: { label: "Sign In", href: "/login" },
|
|
34
|
-
secondaryCta: { label: "Docs", href: "/docs" },
|
|
35
|
-
});
|
|
36
|
-
getMarketingPage.mockResolvedValue({
|
|
37
|
-
pageKey: "pricing",
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const page = await import("./page");
|
|
41
|
-
|
|
42
|
-
await expect(page.default()).resolves.toBeDefined();
|
|
43
|
-
expect(getMarketingPage).toHaveBeenCalledWith("pricing");
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("renders the built-in empty pricing shell when no pricing page has been published", async () => {
|
|
47
|
-
getSiteConfig.mockResolvedValue({
|
|
48
|
-
siteName: "MinuteWork Combined Starter",
|
|
49
|
-
siteDescription: "Combined starter",
|
|
50
|
-
primaryCta: { label: "Sign In", href: "/login" },
|
|
51
|
-
secondaryCta: { label: "Docs", href: "/docs" },
|
|
52
|
-
});
|
|
53
|
-
getMarketingPage.mockResolvedValue(null);
|
|
54
|
-
|
|
55
|
-
const page = await import("./page");
|
|
56
|
-
|
|
57
|
-
await expect(page.default()).resolves.toBeDefined();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
describe("robots route", () => {
|
|
4
|
-
beforeEach(() => {
|
|
5
|
-
vi.resetModules();
|
|
6
|
-
vi.doUnmock("@/lib/public-site");
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
it("returns a public robots policy and sitemap url", async () => {
|
|
10
|
-
expect(process.env.MW_PUBLIC_BASE_URL).toBe("http://127.0.0.1:3000");
|
|
11
|
-
|
|
12
|
-
const { default: robots } = await import("./robots");
|
|
13
|
-
const metadata = robots();
|
|
14
|
-
|
|
15
|
-
expect(metadata.host).toBe("127.0.0.1:3000");
|
|
16
|
-
expect(metadata.sitemap).toBe("http://127.0.0.1:3000/sitemap.xml");
|
|
17
|
-
expect(metadata.rules).toEqual([
|
|
18
|
-
{
|
|
19
|
-
userAgent: "*",
|
|
20
|
-
allow: "/",
|
|
21
|
-
},
|
|
22
|
-
]);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("disallows indexing when public content is disabled", async () => {
|
|
26
|
-
vi.doMock("@/lib/public-site", () => ({
|
|
27
|
-
isPublicContentDisabled: () => true,
|
|
28
|
-
resolvePublicMetadataBase: () => null,
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
|
-
const { default: robots } = await import("./robots");
|
|
32
|
-
|
|
33
|
-
expect(robots().rules).toEqual([
|
|
34
|
-
{
|
|
35
|
-
userAgent: "*",
|
|
36
|
-
disallow: "/",
|
|
37
|
-
},
|
|
38
|
-
]);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
const { listEntries } = vi.hoisted(() => ({
|
|
4
|
-
listEntries: vi.fn(),
|
|
5
|
-
}));
|
|
6
|
-
|
|
7
|
-
vi.mock("@/lib/content/adapter.server", () => ({
|
|
8
|
-
listEntries,
|
|
9
|
-
}));
|
|
10
|
-
|
|
11
|
-
describe("sitemap route", () => {
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
vi.clearAllMocks();
|
|
14
|
-
vi.resetModules();
|
|
15
|
-
vi.doUnmock("@/lib/public-site");
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it("includes the public route surface and published content entries", async () => {
|
|
19
|
-
listEntries.mockImplementation(async (kind: string) =>
|
|
20
|
-
kind === "docs"
|
|
21
|
-
? [{ slug: ["guides", "public-site-content"] }]
|
|
22
|
-
: [{ slug: ["public-site-api-default"], publishedAt: "2026-03-26T10:00:00.000Z" }],
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
expect(process.env.MW_PUBLIC_BASE_URL).toBe("http://127.0.0.1:3000");
|
|
26
|
-
|
|
27
|
-
const { default: sitemap } = await import("./sitemap");
|
|
28
|
-
const entries = await sitemap();
|
|
29
|
-
const urls = entries.map((entry) => entry.url);
|
|
30
|
-
|
|
31
|
-
expect(urls).toContain("http://127.0.0.1:3000/");
|
|
32
|
-
expect(urls).toContain("http://127.0.0.1:3000/pricing");
|
|
33
|
-
expect(urls).toContain("http://127.0.0.1:3000/docs");
|
|
34
|
-
expect(urls).toContain("http://127.0.0.1:3000/docs/guides/public-site-content");
|
|
35
|
-
expect(urls).toContain("http://127.0.0.1:3000/blog");
|
|
36
|
-
expect(urls).toContain("http://127.0.0.1:3000/blog/public-site-api-default");
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("keeps home and pricing in the sitemap even when the snapshot has no marketing pages", async () => {
|
|
40
|
-
listEntries.mockResolvedValue([]);
|
|
41
|
-
|
|
42
|
-
const { default: sitemap } = await import("./sitemap");
|
|
43
|
-
const entries = await sitemap();
|
|
44
|
-
const urls = entries.map((entry) => entry.url);
|
|
45
|
-
|
|
46
|
-
expect(urls).toContain("http://127.0.0.1:3000/");
|
|
47
|
-
expect(urls).toContain("http://127.0.0.1:3000/pricing");
|
|
48
|
-
expect(urls).toContain("http://127.0.0.1:3000/docs");
|
|
49
|
-
expect(urls).toContain("http://127.0.0.1:3000/blog");
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("returns an empty sitemap when public content is disabled", async () => {
|
|
53
|
-
vi.doMock("@/lib/public-site", () => ({
|
|
54
|
-
isPublicContentDisabled: () => true,
|
|
55
|
-
resolvePublicSiteUrl: vi.fn(),
|
|
56
|
-
}));
|
|
57
|
-
|
|
58
|
-
const { default: sitemap } = await import("./sitemap");
|
|
59
|
-
|
|
60
|
-
await expect(sitemap()).resolves.toEqual([]);
|
|
61
|
-
expect(listEntries).not.toHaveBeenCalled();
|
|
62
|
-
});
|
|
63
|
-
});
|