minutework 0.1.31 → 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/EXTERNAL_ALPHA.md +33 -33
- package/README.md +34 -34
- package/assets/claude-local/CLAUDE.md.template +12 -12
- package/assets/claude-local/skills/README.md +3 -1
- package/assets/claude-local/skills/app-pack-authoring/SKILL.md +17 -4
- package/assets/claude-local/skills/capability-gap-reporting/SKILL.md +3 -3
- package/assets/claude-local/skills/contract-first-public-intake/SKILL.md +11 -3
- package/assets/claude-local/skills/generated-workspace-architecture/SKILL.md +12 -5
- package/assets/claude-local/skills/layering-and-import-modes/SKILL.md +2 -2
- package/assets/claude-local/skills/openclaw-skill-importer/SKILL.md +2 -2
- package/assets/claude-local/skills/project-overview-and-strategy/SKILL.md +8 -8
- package/assets/claude-local/skills/published-web-and-mw-core-site/SKILL.md +11 -8
- package/assets/claude-local/skills/standalone-mobile-client/SKILL.md +6 -5
- package/assets/claude-local/skills/vuilder-discovery-output-contract/SKILL.md +6 -6
- package/assets/claude-local/skills/workspace-guidance-refresh/SKILL.md +4 -4
- package/assets/templates/fastapi-sidecar/pyproject.toml +1 -1
- package/assets/templates/fastapi-sidecar/src/fastapi_sidecar/main.py +1 -1
- package/assets/templates/mobile-app/.env.example +4 -4
- package/assets/templates/mobile-app/AGENTS.md +3 -3
- package/assets/templates/mobile-app/README.md +10 -10
- package/assets/templates/mobile-app/app/(app)/_layout.tsx +2 -2
- package/assets/templates/mobile-app/app/(app)/index.tsx +2 -2
- package/assets/templates/mobile-app/app/(auth)/login.tsx +3 -3
- package/assets/templates/mobile-app/app/_layout.tsx +1 -1
- package/assets/templates/mobile-app/babel.config.js +1 -1
- package/assets/templates/mobile-app/eas.json +1 -1
- package/assets/templates/mobile-app/expo-env.d.ts +1 -1
- package/assets/templates/mobile-app/metro.config.js +2 -2
- package/assets/templates/mobile-app/package.json +1 -1
- package/assets/templates/mobile-app/src/mw/client.ts +3 -3
- package/assets/templates/mobile-app/src/mw/contracts.ts +2 -2
- package/assets/templates/mobile-app/src/mw/endpoints.ts +2 -2
- package/assets/templates/mobile-app/src/mw/env.ts +4 -4
- package/assets/templates/mobile-app/src/mw/session.ts +1 -1
- package/assets/templates/mobile-app/template.json +1 -1
- package/assets/templates/mobile-app/tools/template/validate-template.mjs +2 -2
- package/assets/templates/mobile-app/tsconfig.json +1 -1
- package/assets/templates/next-tenant-app/.env.example +1 -1
- 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.test.ts +1 -1
- 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/assets/templates/next-tenant-app/tools/template/with-public-site-fixture.mjs +2 -2
- package/bin/minutework.js +1 -1
- package/dist/agent.js +7 -7
- package/dist/agent.js.map +1 -1
- package/dist/auth.js +7 -7
- package/dist/auth.js.map +1 -1
- package/dist/compile.js +5 -5
- package/dist/config.js +6 -6
- package/dist/config.js.map +1 -1
- package/dist/deploy.js +7 -7
- package/dist/deploy.js.map +1 -1
- package/dist/developer-client.js +2 -2
- package/dist/developer-client.js.map +1 -1
- package/dist/index.js +30 -30
- package/dist/index.js.map +1 -1
- package/dist/init.js +10 -10
- package/dist/init.js.map +1 -1
- package/dist/launcher.js +1 -1
- package/dist/launcher.js.map +1 -1
- package/dist/managed-engine.js +6 -6
- package/dist/managed-engine.js.map +1 -1
- package/dist/orchestrator-context.js +1 -1
- package/dist/orchestrator-context.js.map +1 -1
- package/dist/orchestrator.js +15 -15
- package/dist/orchestrator.js.map +1 -1
- package/dist/paths.js +1 -1
- package/dist/paths.js.map +1 -1
- package/dist/publish.js +3 -3
- package/dist/publish.js.map +1 -1
- package/dist/reporting.js +8 -8
- package/dist/reporting.js.map +1 -1
- package/dist/sandbox.js +5 -5
- package/dist/sandbox.js.map +1 -1
- package/dist/state.js +1 -1
- package/dist/state.js.map +1 -1
- package/dist/tokens.js +9 -9
- package/dist/tokens.js.map +1 -1
- package/dist/workspace-assets.js +6 -6
- package/dist/workspace-assets.js.map +1 -1
- package/dist/workspace.js +3 -3
- package/dist/workspace.js.map +1 -1
- package/package.json +3 -3
- package/vendor/workspace-mcp/context.d.ts +6 -6
- package/vendor/workspace-mcp/context.js +56 -56
- package/vendor/workspace-mcp/context.js.map +1 -1
- 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("blog article page", () => {
|
|
29
|
-
beforeEach(() => {
|
|
30
|
-
vi.clearAllMocks();
|
|
31
|
-
vi.resetModules();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it("returns notFound for unknown blog slugs", async () => {
|
|
35
|
-
getSiteConfig.mockResolvedValue({
|
|
36
|
-
collections: {
|
|
37
|
-
blog: {
|
|
38
|
-
title: "Starter Blog",
|
|
39
|
-
description: "Blog",
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
siteName: "PandaWork 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 blog entries", async () => {
|
|
57
|
-
listEntries.mockResolvedValue([
|
|
58
|
-
{ slug: ["public-site-api-default"] },
|
|
59
|
-
{ slug: ["launch-note"] },
|
|
60
|
-
]);
|
|
61
|
-
|
|
62
|
-
const page = await import("./page");
|
|
63
|
-
|
|
64
|
-
await expect(page.generateStaticParams()).resolves.toEqual([
|
|
65
|
-
{ slug: "public-site-api-default" },
|
|
66
|
-
{ slug: "launch-note" },
|
|
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("blog index page", () => {
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
vi.clearAllMocks();
|
|
26
|
-
vi.resetModules();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("renders the public blog collection", async () => {
|
|
30
|
-
getSiteConfig.mockResolvedValue({
|
|
31
|
-
collections: {
|
|
32
|
-
blog: {
|
|
33
|
-
eyebrow: "Blog",
|
|
34
|
-
title: "Starter Blog",
|
|
35
|
-
description: "Combined starter notes.",
|
|
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("blog");
|
|
45
|
-
});
|
|
46
|
-
});
|
|
@@ -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: "PandaWork 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: "PandaWork 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: "PandaWork 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: "PandaWork 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: "PandaWork 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: "PandaWork 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
|
-
});
|