@warpgogol/werkstatt-shared 0.14.0 → 0.14.1
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/README.md +26 -16
- package/README.uk.md +24 -14
- package/package.json +7 -1
- package/src/checks/result-helpers.ts +21 -4
- package/src/checks/tests/remediation-auto-populate.test.ts +83 -0
- package/src/integration/vitest.config.ts +7 -0
- package/src/ontology/manifest.ts +19 -0
- package/src/ontology/schemas/system/tests/growth.test.ts +22 -0
- package/src/ontology/schemas/system/tests/integrations.test.ts +12 -0
- package/src/ontology/schemas/system/tests/manifest.test.ts +22 -0
- package/src/ontology/schemas/system/tests/page-output.test.ts +13 -0
- package/src/ontology/schemas/system/tests/release.test.ts +22 -0
- package/src/ontology/schemas/system/tests/text.test.ts +18 -0
- package/src/ontology/schemas/system/tests/verification.test.ts +12 -0
- package/src/ontology/schemas/tests/biome.test.ts +19 -0
- package/src/ontology/schemas/tests/capability.test.ts +22 -0
- package/src/ontology/schemas/tests/constellation.test.ts +22 -0
- package/src/ontology/schemas/tests/dns-records.test.ts +13 -0
- package/src/ontology/schemas/tests/manifest-resolver.test.ts +13 -0
- package/src/ontology/schemas/tests/page-entry.test.ts +22 -0
- package/src/ontology/schemas/tests/section-archetype.test.ts +12 -0
- package/src/ontology/schemas/tests/site-family.test.ts +18 -0
- package/src/ontology/schemas/tests/system.test.ts +20 -0
- package/src/share/agent/tests/api-catalog.test.ts +8 -0
- package/src/share/agent/tests/ard-catalog.test.ts +8 -0
- package/src/share/agent/tests/capability.test.ts +14 -0
- package/src/share/agent/tests/fleet-catalog.test.ts +15 -0
- package/src/share/agent/tests/knowledge.test.ts +20 -0
- package/src/share/agent/tests/manifest.test.ts +9 -0
- package/src/share/agent/tests/mcp-card.test.ts +8 -0
- package/src/share/agent/tests/omit-empty.test.ts +33 -0
- package/src/share/agent/tests/openapi.test.ts +8 -0
- package/src/share/agent/tests/proof.test.ts +15 -0
- package/src/share/knowledge/tests/claim.test.ts +11 -0
- package/src/share/knowledge/tests/derivation.test.ts +30 -0
- package/src/share/knowledge/tests/freshness.test.ts +18 -0
- package/src/share/knowledge/tests/ledger.test.ts +35 -0
- package/src/share/knowledge/tests/plan.test.ts +19 -0
- package/src/share/knowledge/tests/source.test.ts +19 -0
- package/src/share/remediation/remediation-catalog.ts +196 -0
- package/src/share/schemas/tests/claim-records.test.ts +52 -0
- package/src/share/schemas/tests/claims.test.ts +23 -0
- package/src/share/schemas/tests/effects.test.ts +116 -0
- package/src/share/schemas/tests/features.test.ts +61 -0
- package/src/share/schemas/tests/horizontal-align.test.ts +16 -0
- package/src/share/schemas/tests/icon-color.test.ts +16 -0
- package/src/share/schemas/tests/live-photo.test.ts +40 -0
- package/src/share/schemas/tests/material-credit.test.ts +51 -0
- package/src/share/schemas/tests/media.test.ts +26 -0
- package/src/share/schemas/tests/navigation.test.ts +58 -0
- package/src/share/schemas/tests/page-base.test.ts +19 -0
- package/src/share/schemas/tests/participant.test.ts +26 -0
- package/src/share/schemas/tests/person.test.ts +12 -0
- package/src/share/schemas/tests/print.test.ts +30 -0
- package/src/share/schemas/tests/section-background.test.ts +31 -0
- package/src/share/schemas/tests/section-body.test.ts +16 -0
- package/src/share/schemas/tests/section-cards.test.ts +17 -0
- package/src/share/schemas/tests/section-cta.test.ts +41 -0
- package/src/share/schemas/tests/section-header.test.ts +31 -0
- package/src/share/schemas/tests/section-image.test.ts +24 -0
- package/src/share/schemas/tests/section-motion.test.ts +29 -0
- package/src/share/schemas/tests/section-shell.test.ts +42 -0
- package/src/share/schemas/tests/section-stats.test.ts +17 -0
- package/src/share/schemas/tests/site-background.test.ts +33 -0
- package/src/share/schemas/tests/standard-list-item.test.ts +16 -0
- package/src/share/scripts/tests/external-link-qr.test.ts +8 -0
- package/src/share/scripts/tests/external-links.test.ts +25 -0
- package/src/share/scripts/tests/gsap-counter.test.ts +8 -0
- package/src/share/scripts/tests/gsap-mountain-journey.test.ts +8 -0
- package/src/share/scripts/tests/gsap-parallax.test.ts +8 -0
- package/src/share/scripts/tests/gsap-reveal.test.ts +8 -0
- package/src/share/scripts/tests/gsap-stagger.test.ts +8 -0
- package/src/share/scripts/tests/inline-number-animation.test.ts +8 -0
- package/src/share/scripts/tests/lenis.test.ts +8 -0
- package/src/share/scripts/tests/live-photos.test.ts +8 -0
- package/src/share/scripts/tests/lordicon.test.ts +8 -0
- package/src/share/scripts/tests/orchestrator.test.ts +8 -0
- package/src/share/scripts/tests/scheduler.test.ts +23 -0
- package/src/share/semantic/jsonld/tests/article.test.ts +89 -0
- package/src/share/semantic/jsonld/tests/breadcrumb.test.ts +62 -0
- package/src/share/semantic/jsonld/tests/collection-list.test.ts +39 -0
- package/src/share/semantic/jsonld/tests/faq.test.ts +60 -0
- package/src/share/semantic/jsonld/tests/initiative.test.ts +56 -0
- package/src/share/semantic/jsonld/tests/organization.test.ts +123 -0
- package/src/share/semantic/jsonld/tests/person.test.ts +89 -0
- package/src/share/semantic/jsonld/tests/service.test.ts +65 -0
- package/src/share/semantic/jsonld/tests/shared.test.ts +41 -0
- package/src/share/semantic/jsonld/tests/video.test.ts +84 -0
- package/src/share/semantic/jsonld/tests/webpage.test.ts +93 -0
- package/src/share/semantic/jsonld/tests/website.test.ts +27 -0
- package/src/share/semantic/jsonld/types.ts +1 -0
- package/src/share/semantic/models.ts +1 -0
- package/src/share/semantic/tests/ai.test.ts +55 -0
- package/src/share/semantic/tests/block-extraction.test.ts +34 -0
- package/src/share/semantic/tests/breadcrumbs.test.ts +127 -0
- package/src/share/semantic/tests/build-page.test.ts +122 -0
- package/src/share/semantic/tests/business-projection.test.ts +188 -0
- package/src/share/semantic/tests/derived-prices-loader.test.ts +46 -0
- package/src/share/semantic/tests/extract.test.ts +126 -0
- package/src/share/semantic/tests/feed.test.ts +113 -0
- package/src/share/semantic/tests/helpers.ts +32 -0
- package/src/share/semantic/tests/ids.test.ts +118 -0
- package/src/share/semantic/tests/image-sitemap.test.ts +109 -0
- package/src/share/semantic/tests/jsonld.test.ts +61 -0
- package/src/share/semantic/tests/llms-policy.test.ts +60 -0
- package/src/share/semantic/tests/llms.test.ts +118 -0
- package/src/share/semantic/tests/markdown-hygiene.test.ts +72 -0
- package/src/share/semantic/tests/markdown-page.test.ts +97 -0
- package/src/share/semantic/tests/markdown-twin-provenance.test.ts +152 -0
- package/src/share/semantic/tests/organization-profile.test.ts +107 -0
- package/src/share/semantic/tests/output-projection.test.ts +77 -0
- package/src/share/semantic/tests/page-markdown.test.ts +98 -0
- package/src/share/semantic/tests/page-utils.test.ts +88 -0
- package/src/share/semantic/tests/price-marker-resolver.test.ts +88 -0
- package/src/share/semantic/tests/robots.test.ts +70 -0
- package/src/share/semantic/tests/update-stamp.test.ts +102 -0
- package/src/share/utility-registry.yaml +14 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
namedEffectTargetSchema,
|
|
4
|
+
effectTargetSchema,
|
|
5
|
+
glassEffectSchema,
|
|
6
|
+
effectSchema,
|
|
7
|
+
EFFECT_KIND_META,
|
|
8
|
+
allowedKindsForTarget,
|
|
9
|
+
resolveEffectsForTarget,
|
|
10
|
+
hasEnabledGlassEffect,
|
|
11
|
+
} from "../effects.ts";
|
|
12
|
+
import type { EffectAssignment } from "../effects.ts";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
15
|
+
type ParsedEffect = z.infer<typeof effectSchema>;
|
|
16
|
+
|
|
17
|
+
describe("namedEffectTargetSchema", () => {
|
|
18
|
+
it("accepts valid targets", () => {
|
|
19
|
+
expect(namedEffectTargetSchema.parse("section")).toBe("section");
|
|
20
|
+
expect(namedEffectTargetSchema.parse("heading")).toBe("heading");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("rejects invalid target", () => {
|
|
24
|
+
expect(() => namedEffectTargetSchema.parse("unknown")).toThrow();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("effectTargetSchema", () => {
|
|
29
|
+
it("accepts slot targets", () => {
|
|
30
|
+
expect(effectTargetSchema.parse("slot:my-slot")).toBe("slot:my-slot");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("rejects invalid slot format", () => {
|
|
34
|
+
expect(() => effectTargetSchema.parse("slot:")).toThrow();
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe("glassEffectSchema", () => {
|
|
39
|
+
it("accepts valid glass effect", () => {
|
|
40
|
+
const result = glassEffectSchema.safeParse({ kind: "glass", enabled: true });
|
|
41
|
+
expect(result.success).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("rejects missing required fields", () => {
|
|
45
|
+
expect(() => glassEffectSchema.parse({ kind: "glass" })).toThrow();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("rejects extra keys (strict)", () => {
|
|
49
|
+
expect(() => glassEffectSchema.parse({ kind: "glass", enabled: true, extra: true })).toThrow();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe("effectSchema (discriminated union)", () => {
|
|
54
|
+
it("accepts glass effect", () => {
|
|
55
|
+
const result = effectSchema.safeParse({ kind: "glass", enabled: true });
|
|
56
|
+
expect(result.success).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("accepts shadow effect", () => {
|
|
60
|
+
const result = effectSchema.safeParse({ kind: "shadow", enabled: true });
|
|
61
|
+
expect(result.success).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("rejects unknown kind", () => {
|
|
65
|
+
expect(() => effectSchema.parse({ kind: "unknown", enabled: true })).toThrow();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("EFFECT_KIND_META", () => {
|
|
70
|
+
it("has metadata for all effect kinds", () => {
|
|
71
|
+
expect(EFFECT_KIND_META.glass.strategy).toBe("surface");
|
|
72
|
+
expect(EFFECT_KIND_META.shadow.strategy).toBe("text");
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
describe("allowedKindsForTarget", () => {
|
|
77
|
+
it("returns text kinds for heading", () => {
|
|
78
|
+
const kinds = allowedKindsForTarget("heading");
|
|
79
|
+
expect(kinds).toContain("shadow");
|
|
80
|
+
expect(kinds).not.toContain("glass");
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("returns glass-only default for body", () => {
|
|
84
|
+
const kinds = allowedKindsForTarget("body");
|
|
85
|
+
expect(kinds).toEqual(["glass"]);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe("resolveEffectsForTarget", () => {
|
|
90
|
+
it("returns empty array when no assignments", () => {
|
|
91
|
+
expect(resolveEffectsForTarget(undefined, "section")).toEqual([]);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("returns effects for matching target", () => {
|
|
95
|
+
const glassEffect: ParsedEffect = effectSchema.parse({ kind: "glass", enabled: true });
|
|
96
|
+
const assignments: EffectAssignment[] = [{ target: "section", stack: [glassEffect] }];
|
|
97
|
+
const effects = resolveEffectsForTarget(assignments, "section");
|
|
98
|
+
expect(effects).toHaveLength(1);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("hasEnabledGlassEffect", () => {
|
|
103
|
+
it("returns true when glass effect is enabled", () => {
|
|
104
|
+
const e: ParsedEffect = effectSchema.parse({ kind: "glass", enabled: true });
|
|
105
|
+
expect(hasEnabledGlassEffect([e])).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("returns false when glass effect is disabled", () => {
|
|
109
|
+
const e: ParsedEffect = effectSchema.parse({ kind: "glass", enabled: false });
|
|
110
|
+
expect(hasEnabledGlassEffect([e])).toBe(false);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("returns false when no effects", () => {
|
|
114
|
+
expect(hasEnabledGlassEffect(undefined)).toBe(false);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
featurePolicyVisibilitySchema,
|
|
4
|
+
featurePolicyBehaviorValueSchema,
|
|
5
|
+
featurePolicySchema,
|
|
6
|
+
} from "../features.ts";
|
|
7
|
+
|
|
8
|
+
describe("featurePolicyVisibilitySchema", () => {
|
|
9
|
+
it("accepts valid visibility values", () => {
|
|
10
|
+
for (const v of ["enabled", "disabled", "hidden", "draft"]) {
|
|
11
|
+
expect(featurePolicyVisibilitySchema.parse(v)).toBe(v);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("rejects invalid values", () => {
|
|
16
|
+
expect(() => featurePolicyVisibilitySchema.parse("visible")).toThrow();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("featurePolicyBehaviorValueSchema", () => {
|
|
21
|
+
it("accepts string values", () => {
|
|
22
|
+
expect(featurePolicyBehaviorValueSchema.parse("hello")).toBe("hello");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("accepts number values", () => {
|
|
26
|
+
expect(featurePolicyBehaviorValueSchema.parse(42)).toBe(42);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("accepts boolean values", () => {
|
|
30
|
+
expect(featurePolicyBehaviorValueSchema.parse(true)).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("accepts null", () => {
|
|
34
|
+
expect(featurePolicyBehaviorValueSchema.parse(null)).toBeNull();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("rejects objects", () => {
|
|
38
|
+
expect(() => featurePolicyBehaviorValueSchema.parse({})).toThrow();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("featurePolicySchema", () => {
|
|
43
|
+
it("accepts empty object (all fields optional)", () => {
|
|
44
|
+
expect(featurePolicySchema.parse({})).toEqual({});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("accepts full policy", () => {
|
|
48
|
+
const policy = {
|
|
49
|
+
visibility: "enabled",
|
|
50
|
+
behavior: { key: "value" },
|
|
51
|
+
reason: "test",
|
|
52
|
+
expiresAt: "2026-12-31",
|
|
53
|
+
audience: "all",
|
|
54
|
+
};
|
|
55
|
+
expect(featurePolicySchema.parse(policy)).toEqual(policy);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("rejects invalid visibility", () => {
|
|
59
|
+
expect(() => featurePolicySchema.parse({ visibility: "invalid" })).toThrow();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { horizontalAlignSchema } from "../horizontal-align.ts";
|
|
3
|
+
|
|
4
|
+
describe("horizontalAlignSchema", () => {
|
|
5
|
+
it("accepts valid alignment values", () => {
|
|
6
|
+
expect(horizontalAlignSchema.parse("left")).toBe("left");
|
|
7
|
+
expect(horizontalAlignSchema.parse("center")).toBe("center");
|
|
8
|
+
expect(horizontalAlignSchema.parse("right")).toBe("right");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("rejects invalid alignment values", () => {
|
|
12
|
+
expect(() => horizontalAlignSchema.parse("top")).toThrow();
|
|
13
|
+
expect(() => horizontalAlignSchema.parse("")).toThrow();
|
|
14
|
+
expect(() => horizontalAlignSchema.parse(null)).toThrow();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { iconColorSchema } from "../icon-color.ts";
|
|
3
|
+
|
|
4
|
+
describe("iconColorSchema", () => {
|
|
5
|
+
it("accepts valid icon colors", () => {
|
|
6
|
+
for (const c of ["primary", "accent", "success", "warning", "error", "muted"]) {
|
|
7
|
+
expect(iconColorSchema.parse(c)).toBe(c);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("rejects invalid icon colors", () => {
|
|
12
|
+
expect(() => iconColorSchema.parse("blue")).toThrow();
|
|
13
|
+
expect(() => iconColorSchema.parse("")).toThrow();
|
|
14
|
+
expect(() => iconColorSchema.parse(123)).toThrow();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { livePhotoTriggerSchema, livePhotoSchema } from "../live-photo.ts";
|
|
3
|
+
|
|
4
|
+
describe("livePhotoTriggerSchema", () => {
|
|
5
|
+
it("accepts valid triggers", () => {
|
|
6
|
+
for (const t of ["in-viewport", "tap", "autoplay"]) {
|
|
7
|
+
expect(livePhotoTriggerSchema.parse(t)).toBe(t);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("rejects invalid trigger", () => {
|
|
12
|
+
expect(() => livePhotoTriggerSchema.parse("scroll")).toThrow();
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe("livePhotoSchema", () => {
|
|
17
|
+
it("accepts minimal valid object with defaults", () => {
|
|
18
|
+
const result = livePhotoSchema.parse({ enabled: true });
|
|
19
|
+
expect(result.enabled).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("accepts full config", () => {
|
|
23
|
+
const config = {
|
|
24
|
+
enabled: true,
|
|
25
|
+
trigger: "in-viewport",
|
|
26
|
+
loop: true,
|
|
27
|
+
tapBehavior: "toggle",
|
|
28
|
+
preload: "metadata",
|
|
29
|
+
};
|
|
30
|
+
expect(livePhotoSchema.parse(config)).toEqual(config);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("rejects unknown keys (strict)", () => {
|
|
34
|
+
expect(() => livePhotoSchema.parse({ enabled: true, unknown: true })).toThrow();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("rejects invalid trigger", () => {
|
|
38
|
+
expect(() => livePhotoSchema.parse({ enabled: true, trigger: "scroll" })).toThrow();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
materialKindSchema,
|
|
4
|
+
materialSourceTypeSchema,
|
|
5
|
+
creditPartyKindSchema,
|
|
6
|
+
creditRoleSchema,
|
|
7
|
+
} from "../material-credit.ts";
|
|
8
|
+
|
|
9
|
+
describe("materialKindSchema", () => {
|
|
10
|
+
it("accepts valid kinds", () => {
|
|
11
|
+
const result = materialKindSchema.safeParse("image");
|
|
12
|
+
expect(result.success).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("rejects invalid kind", () => {
|
|
16
|
+
expect(() => materialKindSchema.parse("3d-model")).toThrow();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("materialSourceTypeSchema", () => {
|
|
21
|
+
it("accepts valid source types", () => {
|
|
22
|
+
const result = materialSourceTypeSchema.safeParse("human-made");
|
|
23
|
+
expect(result.success).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("rejects invalid source type", () => {
|
|
27
|
+
expect(() => materialSourceTypeSchema.parse("unknown")).toThrow();
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe("creditPartyKindSchema", () => {
|
|
32
|
+
it("accepts valid party kinds", () => {
|
|
33
|
+
const result = creditPartyKindSchema.safeParse("Person");
|
|
34
|
+
expect(result.success).toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("rejects invalid party kind", () => {
|
|
38
|
+
expect(() => creditPartyKindSchema.parse("Robot")).toThrow();
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("creditRoleSchema", () => {
|
|
43
|
+
it("accepts valid roles", () => {
|
|
44
|
+
const result = creditRoleSchema.safeParse("creator");
|
|
45
|
+
expect(result.success).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("rejects invalid role", () => {
|
|
49
|
+
expect(() => creditRoleSchema.parse("owner")).toThrow();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { mediaProfileSchema, mediaTriggerSchema } from "../media.ts";
|
|
3
|
+
|
|
4
|
+
describe("mediaProfileSchema", () => {
|
|
5
|
+
it("accepts valid profiles", () => {
|
|
6
|
+
for (const p of ["feature", "background", "ambient"]) {
|
|
7
|
+
expect(mediaProfileSchema.parse(p)).toBe(p);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("rejects invalid profile", () => {
|
|
12
|
+
expect(() => mediaProfileSchema.parse("streaming")).toThrow();
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe("mediaTriggerSchema", () => {
|
|
17
|
+
it("accepts valid triggers", () => {
|
|
18
|
+
for (const t of ["in-viewport", "tap", "autoplay"]) {
|
|
19
|
+
expect(mediaTriggerSchema.parse(t)).toBe(t);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("rejects invalid trigger", () => {
|
|
24
|
+
expect(() => mediaTriggerSchema.parse("scroll")).toThrow();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
createNavigationGroupEnum,
|
|
4
|
+
defaultNavigationGroups,
|
|
5
|
+
navigationTargetSchema,
|
|
6
|
+
navigationSchema,
|
|
7
|
+
} from "../navigation.ts";
|
|
8
|
+
|
|
9
|
+
describe("defaultNavigationGroups", () => {
|
|
10
|
+
it("contains expected groups", () => {
|
|
11
|
+
expect(defaultNavigationGroups).toEqual(["navigation", "legal", "contact"]);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe("createNavigationGroupEnum", () => {
|
|
16
|
+
it("creates a Zod enum from group names", () => {
|
|
17
|
+
const enumSchema = createNavigationGroupEnum(["main", "footer"]);
|
|
18
|
+
expect(enumSchema.parse("main")).toBe("main");
|
|
19
|
+
expect(enumSchema.parse("footer")).toBe("footer");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("rejects values not in the enum", () => {
|
|
23
|
+
const enumSchema = createNavigationGroupEnum(["main"]);
|
|
24
|
+
expect(() => enumSchema.parse("footer")).toThrow();
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
describe("navigationTargetSchema", () => {
|
|
29
|
+
it("validates a target with valid group", () => {
|
|
30
|
+
const groupEnum = createNavigationGroupEnum(["navigation", "legal"]);
|
|
31
|
+
const schema = navigationTargetSchema(groupEnum);
|
|
32
|
+
const result = schema.safeParse({
|
|
33
|
+
id: "home",
|
|
34
|
+
label: "Home",
|
|
35
|
+
semanticTarget: { kind: "internal", pageId: "home" },
|
|
36
|
+
group: "navigation",
|
|
37
|
+
});
|
|
38
|
+
expect(result.success).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
describe("navigationSchema", () => {
|
|
43
|
+
it("validates a navigation object with targets", () => {
|
|
44
|
+
const groupEnum = createNavigationGroupEnum(["navigation"]);
|
|
45
|
+
const schema = navigationSchema(groupEnum);
|
|
46
|
+
const result = schema.safeParse({
|
|
47
|
+
targets: [
|
|
48
|
+
{
|
|
49
|
+
id: "home",
|
|
50
|
+
label: "Home",
|
|
51
|
+
semanticTarget: { kind: "internal", pageId: "home" },
|
|
52
|
+
group: "navigation",
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
});
|
|
56
|
+
expect(result.success).toBe(true);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { componentOverridesSchema } from "../page-base.ts";
|
|
3
|
+
|
|
4
|
+
describe("componentOverridesSchema", () => {
|
|
5
|
+
it("accepts undefined (optional)", () => {
|
|
6
|
+
expect(componentOverridesSchema.parse(undefined)).toBeUndefined();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("accepts empty record", () => {
|
|
10
|
+
expect(componentOverridesSchema.parse({})).toEqual({});
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("accepts a valid overrides map", () => {
|
|
14
|
+
const overrides = {
|
|
15
|
+
"components/Header": { title: "Custom" },
|
|
16
|
+
};
|
|
17
|
+
expect(componentOverridesSchema.parse(overrides)).toEqual(overrides);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
PARTICIPANT_TYPES,
|
|
4
|
+
PARTICIPANT_RELATIONSHIPS,
|
|
5
|
+
PARTICIPANT_STATUSES,
|
|
6
|
+
} from "../participant.ts";
|
|
7
|
+
|
|
8
|
+
describe("PARTICIPANT_TYPES", () => {
|
|
9
|
+
it("contains expected types", () => {
|
|
10
|
+
expect(PARTICIPANT_TYPES).toContain("human");
|
|
11
|
+
expect(PARTICIPANT_TYPES).toContain("ai-agent");
|
|
12
|
+
expect(PARTICIPANT_TYPES).toHaveLength(6);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe("PARTICIPANT_RELATIONSHIPS", () => {
|
|
17
|
+
it("is a non-empty array", () => {
|
|
18
|
+
expect(PARTICIPANT_RELATIONSHIPS.length).toBeGreaterThan(0);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe("PARTICIPANT_STATUSES", () => {
|
|
23
|
+
it("is a non-empty array", () => {
|
|
24
|
+
expect(PARTICIPANT_STATUSES.length).toBeGreaterThan(0);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { PERSON_AFFILIATIONS } from "../person.ts";
|
|
3
|
+
|
|
4
|
+
describe("PERSON_AFFILIATIONS", () => {
|
|
5
|
+
it("contains the expected affiliation values", () => {
|
|
6
|
+
expect(PERSON_AFFILIATIONS).toEqual(["founder", "board", "team", "patron", "author"]);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it("is a readonly tuple", () => {
|
|
10
|
+
expect(PERSON_AFFILIATIONS).toHaveLength(5);
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
PRINT_ORIENTATIONS,
|
|
4
|
+
PRINT_PAGE_SIZES,
|
|
5
|
+
PRINT_MARGINS,
|
|
6
|
+
PRINT_BACKGROUND_MODES,
|
|
7
|
+
PRINT_REGIONS,
|
|
8
|
+
} from "../print.ts";
|
|
9
|
+
|
|
10
|
+
describe("print constants", () => {
|
|
11
|
+
it("PRINT_ORIENTATIONS has expected values", () => {
|
|
12
|
+
expect(PRINT_ORIENTATIONS).toEqual(["portrait", "landscape", "auto"]);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("PRINT_PAGE_SIZES has expected values", () => {
|
|
16
|
+
expect(PRINT_PAGE_SIZES).toEqual(["a4", "letter", "legal"]);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("PRINT_MARGINS has expected values", () => {
|
|
20
|
+
expect(PRINT_MARGINS).toEqual(["normal", "narrow", "none"]);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("PRINT_BACKGROUND_MODES has expected values", () => {
|
|
24
|
+
expect(PRINT_BACKGROUND_MODES).toEqual(["preserve", "flatten"]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("PRINT_REGIONS is a non-empty array", () => {
|
|
28
|
+
expect(PRINT_REGIONS.length).toBeGreaterThan(0);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { sectionBackgroundSchema } from "../section-background.ts";
|
|
3
|
+
|
|
4
|
+
describe("sectionBackgroundSchema", () => {
|
|
5
|
+
it("accepts color kind", () => {
|
|
6
|
+
const result = sectionBackgroundSchema.safeParse({ kind: "color" });
|
|
7
|
+
expect(result.success).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("accepts image kind with imageName", () => {
|
|
11
|
+
const result = sectionBackgroundSchema.safeParse({
|
|
12
|
+
kind: "image",
|
|
13
|
+
imageName: "hero-bg",
|
|
14
|
+
});
|
|
15
|
+
expect(result.success).toBe(true);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("accepts transparent kind", () => {
|
|
19
|
+
const result = sectionBackgroundSchema.safeParse({ kind: "transparent" });
|
|
20
|
+
expect(result.success).toBe(true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("rejects invalid kind", () => {
|
|
24
|
+
expect(() => sectionBackgroundSchema.parse({ kind: "video" })).toThrow();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("rejects image kind without imageName", () => {
|
|
28
|
+
const result = sectionBackgroundSchema.safeParse({ kind: "image" });
|
|
29
|
+
expect(result.success).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { sectionBodyKindSchema } from "../section-body.ts";
|
|
3
|
+
|
|
4
|
+
describe("sectionBodyKindSchema", () => {
|
|
5
|
+
it("accepts valid body kinds", () => {
|
|
6
|
+
const validKinds = ["list", "split-list", "stats", "cards", "paragraphs", "comparison", "rich"];
|
|
7
|
+
for (const kind of validKinds) {
|
|
8
|
+
const result = sectionBodyKindSchema.safeParse(kind);
|
|
9
|
+
expect(result.success, `kind "${kind}" should be valid`).toBe(true);
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("rejects invalid body kind", () => {
|
|
14
|
+
expect(() => sectionBodyKindSchema.parse("accordion")).toThrow();
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { standardCardSchema } from "../section-cards.ts";
|
|
3
|
+
|
|
4
|
+
describe("standardCardSchema", () => {
|
|
5
|
+
it("accepts a valid card", () => {
|
|
6
|
+
const result = standardCardSchema.safeParse({
|
|
7
|
+
title: "Test Card",
|
|
8
|
+
description: "Card body text",
|
|
9
|
+
});
|
|
10
|
+
expect(result.success).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("rejects empty object", () => {
|
|
14
|
+
const result = standardCardSchema.safeParse({});
|
|
15
|
+
expect(result.success).toBe(false);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
ctaVariantSchema,
|
|
4
|
+
ctaSizeSchema,
|
|
5
|
+
ctaIconPositionSchema,
|
|
6
|
+
} from "../section-cta.ts";
|
|
7
|
+
|
|
8
|
+
describe("ctaVariantSchema", () => {
|
|
9
|
+
it("accepts valid variants", () => {
|
|
10
|
+
for (const v of ["primary", "secondary", "ghost", "danger"]) {
|
|
11
|
+
expect(ctaVariantSchema.parse(v)).toBe(v);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("rejects invalid variant", () => {
|
|
16
|
+
expect(() => ctaVariantSchema.parse("link")).toThrow();
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("ctaSizeSchema", () => {
|
|
21
|
+
it("accepts valid sizes", () => {
|
|
22
|
+
for (const s of ["sm", "md", "lg"]) {
|
|
23
|
+
expect(ctaSizeSchema.parse(s)).toBe(s);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("rejects invalid size", () => {
|
|
28
|
+
expect(() => ctaSizeSchema.parse("xl")).toThrow();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe("ctaIconPositionSchema", () => {
|
|
33
|
+
it("accepts valid positions", () => {
|
|
34
|
+
expect(ctaIconPositionSchema.parse("leading")).toBe("leading");
|
|
35
|
+
expect(ctaIconPositionSchema.parse("trailing")).toBe("trailing");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("rejects invalid position", () => {
|
|
39
|
+
expect(() => ctaIconPositionSchema.parse("top")).toThrow();
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
headingToneSchema,
|
|
4
|
+
sectionHeaderLevelSchema,
|
|
5
|
+
} from "../section-header.ts";
|
|
6
|
+
|
|
7
|
+
describe("headingToneSchema", () => {
|
|
8
|
+
it("accepts valid tones", () => {
|
|
9
|
+
for (const t of ["default", "primary", "accent", "muted", "inverse"]) {
|
|
10
|
+
expect(headingToneSchema.parse(t)).toBe(t);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("rejects invalid tone", () => {
|
|
15
|
+
expect(() => headingToneSchema.parse("bright")).toThrow();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("sectionHeaderLevelSchema", () => {
|
|
20
|
+
it("accepts level 1", () => {
|
|
21
|
+
expect(sectionHeaderLevelSchema.parse(1)).toBe(1);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("accepts level 2", () => {
|
|
25
|
+
expect(sectionHeaderLevelSchema.parse(2)).toBe(2);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it("rejects level 3", () => {
|
|
29
|
+
expect(() => sectionHeaderLevelSchema.parse(3)).toThrow();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { sectionImageParallaxPropSchema } from "../section-image.ts";
|
|
3
|
+
|
|
4
|
+
describe("sectionImageParallaxPropSchema", () => {
|
|
5
|
+
it("accepts boolean", () => {
|
|
6
|
+
expect(sectionImageParallaxPropSchema.parse(true)).toBe(true);
|
|
7
|
+
expect(sectionImageParallaxPropSchema.parse(false)).toBe(false);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("accepts number in range 0..2", () => {
|
|
11
|
+
expect(sectionImageParallaxPropSchema.parse(0)).toBe(0);
|
|
12
|
+
expect(sectionImageParallaxPropSchema.parse(1)).toBe(1);
|
|
13
|
+
expect(sectionImageParallaxPropSchema.parse(2)).toBe(2);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("rejects number out of range", () => {
|
|
17
|
+
expect(() => sectionImageParallaxPropSchema.parse(3)).toThrow();
|
|
18
|
+
expect(() => sectionImageParallaxPropSchema.parse(-1)).toThrow();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("rejects string", () => {
|
|
22
|
+
expect(() => sectionImageParallaxPropSchema.parse("subtle")).toThrow();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
revealVariantSchema,
|
|
4
|
+
parallaxVariantSchema,
|
|
5
|
+
} from "../section-motion.ts";
|
|
6
|
+
|
|
7
|
+
describe("revealVariantSchema", () => {
|
|
8
|
+
it("accepts valid variants", () => {
|
|
9
|
+
for (const v of ["fade", "fade-up", "fade-up-stagger"]) {
|
|
10
|
+
expect(revealVariantSchema.parse(v)).toBe(v);
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("rejects invalid variant", () => {
|
|
15
|
+
expect(() => revealVariantSchema.parse("slide")).toThrow();
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("parallaxVariantSchema", () => {
|
|
20
|
+
it("accepts valid variants", () => {
|
|
21
|
+
for (const v of ["subtle", "balanced", "dramatic"]) {
|
|
22
|
+
expect(parallaxVariantSchema.parse(v)).toBe(v);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("rejects invalid variant", () => {
|
|
27
|
+
expect(() => parallaxVariantSchema.parse("extreme")).toThrow();
|
|
28
|
+
});
|
|
29
|
+
});
|