@greensecurity/javascript-sdk 0.46.0-beta.10 → 0.46.0-beta.11
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/dist/commonjs/__tests__/apps/contract.test.js +288 -4
- package/dist/commonjs/__tests__/apps/contract.test.js.map +1 -1
- package/dist/commonjs/__tests__/apps/devpreview-routes.test.d.ts +2 -0
- package/dist/commonjs/__tests__/apps/devpreview-routes.test.d.ts.map +1 -0
- package/dist/commonjs/__tests__/apps/devpreview-routes.test.js +86 -0
- package/dist/commonjs/__tests__/apps/devpreview-routes.test.js.map +1 -0
- package/dist/commonjs/__tests__/apps/kit/example.test.js +84 -4
- package/dist/commonjs/__tests__/apps/kit/example.test.js.map +1 -1
- package/dist/commonjs/__tests__/apps/kit/pages.test.d.ts +2 -0
- package/dist/commonjs/__tests__/apps/kit/pages.test.d.ts.map +1 -0
- package/dist/commonjs/__tests__/apps/kit/pages.test.js +119 -0
- package/dist/commonjs/__tests__/apps/kit/pages.test.js.map +1 -0
- package/dist/commonjs/__tests__/apps/kit/render.test.js +24 -0
- package/dist/commonjs/__tests__/apps/kit/render.test.js.map +1 -1
- package/dist/commonjs/__tests__/apps/kit/store.test.d.ts +2 -0
- package/dist/commonjs/__tests__/apps/kit/store.test.d.ts.map +1 -0
- package/dist/commonjs/__tests__/apps/kit/store.test.js +123 -0
- package/dist/commonjs/__tests__/apps/kit/store.test.js.map +1 -0
- package/dist/commonjs/__tests__/apps/post-install-page.test.d.ts +2 -0
- package/dist/commonjs/__tests__/apps/post-install-page.test.d.ts.map +1 -0
- package/dist/commonjs/__tests__/apps/post-install-page.test.js +110 -0
- package/dist/commonjs/__tests__/apps/post-install-page.test.js.map +1 -0
- package/dist/commonjs/__tests__/apps/routes.test.d.ts +2 -0
- package/dist/commonjs/__tests__/apps/routes.test.d.ts.map +1 -0
- package/dist/commonjs/__tests__/apps/routes.test.js +238 -0
- package/dist/commonjs/__tests__/apps/routes.test.js.map +1 -0
- package/dist/commonjs/__tests__/vendors.test.js +1 -1
- package/dist/commonjs/__tests__/webhooks.test.js +1 -1
- package/dist/commonjs/__tests__/webhooks.test.js.map +1 -1
- package/dist/commonjs/__tests__/zones.test.js +2 -9
- package/dist/commonjs/__tests__/zones.test.js.map +1 -1
- package/dist/commonjs/apps/components.d.ts +321 -0
- package/dist/commonjs/apps/components.d.ts.map +1 -1
- package/dist/commonjs/apps/components.js +168 -2
- package/dist/commonjs/apps/components.js.map +1 -1
- package/dist/commonjs/apps/context.d.ts +24 -0
- package/dist/commonjs/apps/context.d.ts.map +1 -1
- package/dist/commonjs/apps/context.js.map +1 -1
- package/dist/commonjs/apps/devpreview.d.ts +20 -3
- package/dist/commonjs/apps/devpreview.d.ts.map +1 -1
- package/dist/commonjs/apps/devpreview.js +18 -7
- package/dist/commonjs/apps/devpreview.js.map +1 -1
- package/dist/commonjs/apps/hooks/index.d.ts +33 -2
- package/dist/commonjs/apps/hooks/index.d.ts.map +1 -1
- package/dist/commonjs/apps/hooks/index.js +41 -1
- package/dist/commonjs/apps/hooks/index.js.map +1 -1
- package/dist/commonjs/apps/hooks/store.d.ts +48 -0
- package/dist/commonjs/apps/hooks/store.d.ts.map +1 -0
- package/dist/commonjs/apps/hooks/store.js +87 -0
- package/dist/commonjs/apps/hooks/store.js.map +1 -0
- package/dist/commonjs/apps/manifest.d.ts +64 -3
- package/dist/commonjs/apps/manifest.d.ts.map +1 -1
- package/dist/commonjs/apps/manifest.js +128 -27
- package/dist/commonjs/apps/manifest.js.map +1 -1
- package/dist/commonjs/apps/protocol.d.ts +1 -1
- package/dist/commonjs/apps/protocol.d.ts.map +1 -1
- package/dist/commonjs/apps/route.d.ts +11 -1
- package/dist/commonjs/apps/route.d.ts.map +1 -1
- package/dist/commonjs/apps/route.js +13 -7
- package/dist/commonjs/apps/route.js.map +1 -1
- package/dist/commonjs/apps/routes.d.ts +65 -0
- package/dist/commonjs/apps/routes.d.ts.map +1 -0
- package/dist/commonjs/apps/routes.js +202 -0
- package/dist/commonjs/apps/routes.js.map +1 -0
- package/dist/commonjs/apps/surfaces.d.ts +20 -2
- package/dist/commonjs/apps/surfaces.d.ts.map +1 -1
- package/dist/commonjs/apps/surfaces.js +45 -7
- package/dist/commonjs/apps/surfaces.js.map +1 -1
- package/dist/commonjs/apps/testing/index.d.ts +17 -1
- package/dist/commonjs/apps/testing/index.d.ts.map +1 -1
- package/dist/commonjs/apps/testing/index.js +50 -1
- package/dist/commonjs/apps/testing/index.js.map +1 -1
- package/dist/commonjs/apps/ui/index.d.ts +13 -0
- package/dist/commonjs/apps/ui/index.d.ts.map +1 -1
- package/dist/commonjs/apps/ui/index.js +19 -2
- package/dist/commonjs/apps/ui/index.js.map +1 -1
- package/dist/commonjs/lib/config.d.ts +2 -2
- package/dist/commonjs/lib/config.js +2 -2
- package/dist/esm/__tests__/apps/contract.test.js +289 -5
- package/dist/esm/__tests__/apps/contract.test.js.map +1 -1
- package/dist/esm/__tests__/apps/devpreview-routes.test.d.ts +2 -0
- package/dist/esm/__tests__/apps/devpreview-routes.test.d.ts.map +1 -0
- package/dist/esm/__tests__/apps/devpreview-routes.test.js +84 -0
- package/dist/esm/__tests__/apps/devpreview-routes.test.js.map +1 -0
- package/dist/esm/__tests__/apps/kit/example.test.js +85 -5
- package/dist/esm/__tests__/apps/kit/example.test.js.map +1 -1
- package/dist/esm/__tests__/apps/kit/pages.test.d.ts +2 -0
- package/dist/esm/__tests__/apps/kit/pages.test.d.ts.map +1 -0
- package/dist/esm/__tests__/apps/kit/pages.test.js +117 -0
- package/dist/esm/__tests__/apps/kit/pages.test.js.map +1 -0
- package/dist/esm/__tests__/apps/kit/render.test.js +25 -1
- package/dist/esm/__tests__/apps/kit/render.test.js.map +1 -1
- package/dist/esm/__tests__/apps/kit/store.test.d.ts +2 -0
- package/dist/esm/__tests__/apps/kit/store.test.d.ts.map +1 -0
- package/dist/esm/__tests__/apps/kit/store.test.js +121 -0
- package/dist/esm/__tests__/apps/kit/store.test.js.map +1 -0
- package/dist/esm/__tests__/apps/post-install-page.test.d.ts +2 -0
- package/dist/esm/__tests__/apps/post-install-page.test.d.ts.map +1 -0
- package/dist/esm/__tests__/apps/post-install-page.test.js +108 -0
- package/dist/esm/__tests__/apps/post-install-page.test.js.map +1 -0
- package/dist/esm/__tests__/apps/routes.test.d.ts +2 -0
- package/dist/esm/__tests__/apps/routes.test.d.ts.map +1 -0
- package/dist/esm/__tests__/apps/routes.test.js +236 -0
- package/dist/esm/__tests__/apps/routes.test.js.map +1 -0
- package/dist/esm/__tests__/vendors.test.js +1 -1
- package/dist/esm/__tests__/webhooks.test.js +1 -1
- package/dist/esm/__tests__/webhooks.test.js.map +1 -1
- package/dist/esm/__tests__/zones.test.js +2 -9
- package/dist/esm/__tests__/zones.test.js.map +1 -1
- package/dist/esm/apps/components.d.ts +321 -0
- package/dist/esm/apps/components.d.ts.map +1 -1
- package/dist/esm/apps/components.js +163 -1
- package/dist/esm/apps/components.js.map +1 -1
- package/dist/esm/apps/context.d.ts +24 -0
- package/dist/esm/apps/context.d.ts.map +1 -1
- package/dist/esm/apps/context.js.map +1 -1
- package/dist/esm/apps/devpreview.d.ts +20 -3
- package/dist/esm/apps/devpreview.d.ts.map +1 -1
- package/dist/esm/apps/devpreview.js +19 -8
- package/dist/esm/apps/devpreview.js.map +1 -1
- package/dist/esm/apps/hooks/index.d.ts +33 -2
- package/dist/esm/apps/hooks/index.d.ts.map +1 -1
- package/dist/esm/apps/hooks/index.js +37 -1
- package/dist/esm/apps/hooks/index.js.map +1 -1
- package/dist/esm/apps/hooks/store.d.ts +48 -0
- package/dist/esm/apps/hooks/store.d.ts.map +1 -0
- package/dist/esm/apps/hooks/store.js +84 -0
- package/dist/esm/apps/hooks/store.js.map +1 -0
- package/dist/esm/apps/manifest.d.ts +64 -3
- package/dist/esm/apps/manifest.d.ts.map +1 -1
- package/dist/esm/apps/manifest.js +116 -26
- package/dist/esm/apps/manifest.js.map +1 -1
- package/dist/esm/apps/protocol.d.ts +1 -1
- package/dist/esm/apps/protocol.d.ts.map +1 -1
- package/dist/esm/apps/route.d.ts +11 -1
- package/dist/esm/apps/route.d.ts.map +1 -1
- package/dist/esm/apps/route.js +14 -8
- package/dist/esm/apps/route.js.map +1 -1
- package/dist/esm/apps/routes.d.ts +65 -0
- package/dist/esm/apps/routes.d.ts.map +1 -0
- package/dist/esm/apps/routes.js +194 -0
- package/dist/esm/apps/routes.js.map +1 -0
- package/dist/esm/apps/surfaces.d.ts +20 -2
- package/dist/esm/apps/surfaces.d.ts.map +1 -1
- package/dist/esm/apps/surfaces.js +39 -2
- package/dist/esm/apps/surfaces.js.map +1 -1
- package/dist/esm/apps/testing/index.d.ts +17 -1
- package/dist/esm/apps/testing/index.d.ts.map +1 -1
- package/dist/esm/apps/testing/index.js +49 -1
- package/dist/esm/apps/testing/index.js.map +1 -1
- package/dist/esm/apps/ui/index.d.ts +13 -0
- package/dist/esm/apps/ui/index.d.ts.map +1 -1
- package/dist/esm/apps/ui/index.js +17 -1
- package/dist/esm/apps/ui/index.js.map +1 -1
- package/dist/esm/lib/config.d.ts +2 -2
- package/dist/esm/lib/config.js +2 -2
- package/examples/apps/hello-green/src/store.ts +15 -0
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/__tests__/apps/contract.test.ts +305 -4
- package/src/__tests__/apps/devpreview-routes.test.ts +103 -0
- package/src/__tests__/apps/kit/example.test.ts +94 -5
- package/src/__tests__/apps/kit/pages.test.ts +137 -0
- package/src/__tests__/apps/kit/render.test.ts +35 -1
- package/src/__tests__/apps/kit/store.test.ts +149 -0
- package/src/__tests__/apps/post-install-page.test.ts +126 -0
- package/src/__tests__/apps/routes.test.ts +318 -0
- package/src/__tests__/vendors.test.ts +1 -1
- package/src/__tests__/webhooks.test.ts +1 -1
- package/src/__tests__/zones.test.ts +2 -9
- package/src/apps/components.ts +183 -1
- package/src/apps/context.ts +25 -0
- package/src/apps/devpreview.ts +20 -7
- package/src/apps/hooks/index.ts +42 -2
- package/src/apps/hooks/store.ts +115 -0
- package/src/apps/manifest.ts +151 -27
- package/src/apps/protocol.ts +1 -1
- package/src/apps/route.ts +22 -10
- package/src/apps/routes.ts +230 -0
- package/src/apps/surfaces.ts +45 -12
- package/src/apps/testing/index.ts +48 -2
- package/src/apps/ui/index.ts +18 -1
- package/src/lib/config.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/apps/ui/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,aAAa,EAAkB,MAAM,OAAO,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAgB,MAAM,cAAc,CAAC;AAI/D,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/apps/ui/index.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/lib/config.d.ts
CHANGED
|
@@ -35,8 +35,8 @@ export declare function serverURLFromOptions(options: SDKOptions): URL | null;
|
|
|
35
35
|
export declare const SDK_METADATA: {
|
|
36
36
|
readonly language: "typescript";
|
|
37
37
|
readonly openapiDocVersion: "0.45.0";
|
|
38
|
-
readonly sdkVersion: "0.46.0-beta.
|
|
38
|
+
readonly sdkVersion: "0.46.0-beta.11";
|
|
39
39
|
readonly genVersion: "2.943.0";
|
|
40
|
-
readonly userAgent: "speakeasy-sdk/typescript 0.46.0-beta.
|
|
40
|
+
readonly userAgent: "speakeasy-sdk/typescript 0.46.0-beta.11 2.943.0 0.45.0 @greensecurity/javascript-sdk";
|
|
41
41
|
};
|
|
42
42
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/esm/lib/config.js
CHANGED
|
@@ -39,8 +39,8 @@ export function serverURLFromOptions(options) {
|
|
|
39
39
|
export const SDK_METADATA = {
|
|
40
40
|
language: "typescript",
|
|
41
41
|
openapiDocVersion: "0.45.0",
|
|
42
|
-
sdkVersion: "0.46.0-beta.
|
|
42
|
+
sdkVersion: "0.46.0-beta.11",
|
|
43
43
|
genVersion: "2.943.0",
|
|
44
|
-
userAgent: "speakeasy-sdk/typescript 0.46.0-beta.
|
|
44
|
+
userAgent: "speakeasy-sdk/typescript 0.46.0-beta.11 2.943.0 0.45.0 @greensecurity/javascript-sdk",
|
|
45
45
|
};
|
|
46
46
|
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createAppStore } from "@greensecurity/javascript-sdk/apps/hooks";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* State the vendor panel and the report pages share. The host runs every view of this app in one
|
|
5
|
+
* sandbox, so this module-level store is the same object in each of them: a note saved in the
|
|
6
|
+
* panel shows up on the Reports page without a round trip. It lives in memory only and starts
|
|
7
|
+
* over whenever the sandbox restarts (a reload, sign-out, a dev rebuild), so it holds nothing
|
|
8
|
+
* that must last.
|
|
9
|
+
*/
|
|
10
|
+
export const notesStore = createAppStore<{
|
|
11
|
+
/** Notes saved in the vendor panel since the sandbox started. */
|
|
12
|
+
saved: number;
|
|
13
|
+
/** The latest one. */
|
|
14
|
+
last?: { vendorId: number; text: string };
|
|
15
|
+
}>({ saved: 0 });
|
package/jsr.json
CHANGED
package/package.json
CHANGED
|
@@ -12,6 +12,8 @@ import { describe, expect, test } from "vitest";
|
|
|
12
12
|
import {
|
|
13
13
|
canonicalBuildPayload,
|
|
14
14
|
APP_WEBHOOK_EVENTS,
|
|
15
|
+
CHART_DATA_LIMITS,
|
|
16
|
+
CHART_THEMES,
|
|
15
17
|
COMPONENTS,
|
|
16
18
|
componentsCatalogJson,
|
|
17
19
|
CSP_DENYLIST,
|
|
@@ -25,11 +27,18 @@ import {
|
|
|
25
27
|
getSurface,
|
|
26
28
|
isBootstrapToHost,
|
|
27
29
|
isCalendarDate,
|
|
30
|
+
isChartData,
|
|
31
|
+
isPieChartData,
|
|
32
|
+
CHART_OTHER_LABEL,
|
|
33
|
+
MAX_CHART_VALUE,
|
|
34
|
+
isComboChartData,
|
|
28
35
|
isPlatformPermission,
|
|
29
36
|
isRouteDescriptor,
|
|
30
37
|
isSensitivePermission,
|
|
38
|
+
isSeriesChartData,
|
|
31
39
|
isSurfaceId,
|
|
32
40
|
manifestJsonSchema,
|
|
41
|
+
MAX_CHART_SERIES,
|
|
33
42
|
mergeDevManifest,
|
|
34
43
|
permissionReviewIssues,
|
|
35
44
|
PLATFORM_PERMISSIONS,
|
|
@@ -41,6 +50,9 @@ import {
|
|
|
41
50
|
tokenNeedsRefresh,
|
|
42
51
|
validateManifest,
|
|
43
52
|
type AppManifestV2,
|
|
53
|
+
type ChartClickEvent,
|
|
54
|
+
type ComboChartData,
|
|
55
|
+
type SeriesChartData,
|
|
44
56
|
type ComponentProps,
|
|
45
57
|
type HostToBootstrap,
|
|
46
58
|
} from "../../apps/index.js";
|
|
@@ -86,7 +98,7 @@ describe("surfaces", () => {
|
|
|
86
98
|
expect(new Set(ids).size).toBe(ids.length);
|
|
87
99
|
|
|
88
100
|
for (const s of SURFACES) {
|
|
89
|
-
if (s.
|
|
101
|
+
if (s.portal === null) continue;
|
|
90
102
|
expect(s.id).toMatch(/^gs\.(vendor|company|facility|system)\.[a-z_]+(\.[a-z_]+)*$/);
|
|
91
103
|
expect(s.id.startsWith(`gs.${s.portal}.`)).toBe(true);
|
|
92
104
|
expect(s.id.endsWith(s.kind)).toBe(true);
|
|
@@ -98,6 +110,11 @@ describe("surfaces", () => {
|
|
|
98
110
|
expect(s.route.startsWith(s.portal === null ? "/[portal]/" : `/${s.portal}`)).toBe(true);
|
|
99
111
|
}
|
|
100
112
|
expect(getSurface("settings")?.route).toBe("/[portal]/apps/[appId]/settings");
|
|
113
|
+
expect(getSurface("page")?.route).toBe("/[portal]/apps/[appId]/pages/[...path]");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test("the only portal-less surfaces are the app's own settings page and pages", () => {
|
|
117
|
+
expect(SURFACES.filter((s) => s.portal === null).map((s) => s.id).sort()).toEqual(["page", "settings"]);
|
|
101
118
|
});
|
|
102
119
|
|
|
103
120
|
test("wave 1 is the vendor and company portals only", () => {
|
|
@@ -482,9 +499,18 @@ describe("components", () => {
|
|
|
482
499
|
expect(COMPONENTS.Text.children).toEqual(["ui-inline", "ui-link"]);
|
|
483
500
|
});
|
|
484
501
|
|
|
485
|
-
test("only ContextView and
|
|
502
|
+
test("only ContextView, SettingsView and PageView are roots", () => {
|
|
486
503
|
const roots = Object.entries(COMPONENTS).filter(([, c]) => "root" in c).map(([name]) => name);
|
|
487
|
-
expect(roots.sort()).toEqual(["ContextView", "SettingsView"]);
|
|
504
|
+
expect(roots.sort()).toEqual(["ContextView", "PageView", "SettingsView"]);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
test("PageView takes a required title, a description and the actions and banner slots", () => {
|
|
508
|
+
expect(COMPONENTS.PageView.tagName).toBe("ui-page-view");
|
|
509
|
+
expect(COMPONENTS.PageView.slots).toEqual(["actions", "banner"]);
|
|
510
|
+
expect(sanitizeProps("ui-page-view", { title: "Reports", description: "All of them" }).props).toEqual({ title: "Reports", description: "All of them" });
|
|
511
|
+
expect(sanitizeProps("ui-page-view", { title: "t".repeat(101) }).dropped).toEqual(["title"]);
|
|
512
|
+
expect(sanitizeProps("ui-page-view", { title: "Reports", description: "d".repeat(301) }).dropped).toEqual(["description"]);
|
|
513
|
+
expect(componentsCatalogJson().find((c) => c.name === "PageView")).toMatchObject({ tagName: "ui-page-view", root: true });
|
|
488
514
|
});
|
|
489
515
|
|
|
490
516
|
test("sanitizeProps keeps declared props of the right type and drops everything else", () => {
|
|
@@ -688,6 +714,281 @@ describe("components", () => {
|
|
|
688
714
|
});
|
|
689
715
|
});
|
|
690
716
|
|
|
717
|
+
describe("charts", () => {
|
|
718
|
+
const CHART_TAGS: Record<string, string> = {
|
|
719
|
+
BarChart: "ui-bar-chart",
|
|
720
|
+
HorizontalBarChart: "ui-horizontal-bar-chart",
|
|
721
|
+
StackedBarChart: "ui-stacked-bar-chart",
|
|
722
|
+
LineChart: "ui-line-chart",
|
|
723
|
+
AreaChart: "ui-area-chart",
|
|
724
|
+
ComboChart: "ui-combo-chart",
|
|
725
|
+
PieChart: "ui-pie-chart",
|
|
726
|
+
};
|
|
727
|
+
const labels = (n: number) => Array.from({ length: n }, (_, i) => `L${i}`);
|
|
728
|
+
const datums = (n: number) => labels(n).map((label, i) => ({ label, value: i }));
|
|
729
|
+
const seriesData = (nLabels: number, nSeries = 2): SeriesChartData => ({
|
|
730
|
+
labels: labels(nLabels),
|
|
731
|
+
series: Array.from({ length: nSeries }, (_, s) => ({ name: `S${s}`, values: labels(nLabels).map((_, i) => i + s) })),
|
|
732
|
+
});
|
|
733
|
+
const combo = (n: number): ComboChartData => ({
|
|
734
|
+
labels: labels(n),
|
|
735
|
+
bars: { name: "Visits", values: labels(n).map((_, i) => i) },
|
|
736
|
+
line: { name: "Average", values: labels(n).map((_, i) => i / 2) },
|
|
737
|
+
});
|
|
738
|
+
const BAD_VALUES: unknown[] = [-1, Number.NaN, Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, "3", null];
|
|
739
|
+
const BAD_LABELS: unknown[] = ["", " ", "x".repeat(61), 5, null];
|
|
740
|
+
class Datum { constructor(public label: string, public value: number) {} }
|
|
741
|
+
class DatumArray extends Array<unknown> {}
|
|
742
|
+
|
|
743
|
+
test("seven chart entries with the same data-only props, a click event and no children", () => {
|
|
744
|
+
for (const [name, tag] of Object.entries(CHART_TAGS)) {
|
|
745
|
+
const c = COMPONENTS[name as keyof typeof COMPONENTS];
|
|
746
|
+
expect(c.tagName, name).toBe(tag);
|
|
747
|
+
expect(Object.keys(c.props).sort(), name).toEqual(["data", "interactive", "theme"]);
|
|
748
|
+
expect(c.events, name).toEqual({ onClick: { event: "click" } });
|
|
749
|
+
expect(c.children, name).toEqual([]);
|
|
750
|
+
expect(c.text, name).toBe(false);
|
|
751
|
+
expect(c.slots, name).toEqual([]);
|
|
752
|
+
const json = componentsCatalogJson().find((j) => j.name === name)!;
|
|
753
|
+
expect(json.props["data"]).toEqual({ type: "json", required: true });
|
|
754
|
+
expect(json.props["theme"]).toEqual({ type: "enum", required: false, values: ["green", "grayscale", "vibrant"] });
|
|
755
|
+
expect(json.events).toEqual({ onClick: "click" });
|
|
756
|
+
}
|
|
757
|
+
expect(CHART_THEMES).toEqual(["green", "grayscale", "vibrant"]);
|
|
758
|
+
expect(MAX_CHART_SERIES).toBe(6);
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
test("sanitizeProps requires data, checks theme and drops styling props", () => {
|
|
762
|
+
expect(sanitizeProps("ui-bar-chart", { theme: "green" }).missing).toEqual(["data"]);
|
|
763
|
+
const result = sanitizeProps("ui-bar-chart", { data: datums(3), theme: "neon", interactive: true, color: "#f00", style: {} });
|
|
764
|
+
expect(result.props).toEqual({ data: datums(3), interactive: true });
|
|
765
|
+
expect(result.dropped.sort()).toEqual(["color", "style", "theme"]);
|
|
766
|
+
expect(result.missing).toEqual([]);
|
|
767
|
+
const bad = sanitizeProps("ui-line-chart", { data: seriesData(1) });
|
|
768
|
+
expect(bad.dropped).toEqual(["data"]);
|
|
769
|
+
expect(bad.missing).toEqual(["data"]);
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
describe("chart value bounds", () => {
|
|
773
|
+
test("accepts values up to MAX_CHART_VALUE and rejects larger ones", () => {
|
|
774
|
+
const bar = CHART_DATA_LIMITS.BarChart;
|
|
775
|
+
expect(isChartData([{ label: "a", value: MAX_CHART_VALUE }], bar)).toBe(true);
|
|
776
|
+
for (const value of [MAX_CHART_VALUE + 2, 1e308, Number.MAX_VALUE]) {
|
|
777
|
+
expect(isChartData([{ label: "a", value }], bar)).toBe(false);
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
|
|
781
|
+
test("keeps every accepted total finite", () => {
|
|
782
|
+
const pie = Array.from({ length: 50 }, (_, i) => ({ label: `s${i}`, value: MAX_CHART_VALUE }));
|
|
783
|
+
expect(isPieChartData(pie)).toBe(true);
|
|
784
|
+
expect(Number.isFinite(pie.reduce((sum, d) => sum + d.value, 0))).toBe(true);
|
|
785
|
+
const limits = CHART_DATA_LIMITS.StackedBarChart;
|
|
786
|
+
const series = Array.from({ length: 6 }, (_, i) => ({ name: `s${i}`, values: [MAX_CHART_VALUE] }));
|
|
787
|
+
expect(isSeriesChartData({ labels: ["a"], series }, limits)).toBe(true);
|
|
788
|
+
const huge = [{ name: "x", values: [1e308] }, { name: "y", values: [1e308] }];
|
|
789
|
+
expect(isSeriesChartData({ labels: ["a"], series: huge }, limits)).toBe(false);
|
|
790
|
+
});
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
describe("isPieChartData", () => {
|
|
794
|
+
const datums = (n: number, first?: string) =>
|
|
795
|
+
Array.from({ length: n }, (_, i) => ({ label: i === 0 && first !== undefined ? first : `s${i}`, value: i + 1 }));
|
|
796
|
+
|
|
797
|
+
test("allows an Other label when the pie will not combine slices", () => {
|
|
798
|
+
expect(isPieChartData(datums(6, CHART_OTHER_LABEL))).toBe(true);
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
test("rejects a caller Other label when extra items will be combined into Other", () => {
|
|
802
|
+
for (const label of [CHART_OTHER_LABEL, "other", " OTHER "]) expect(isPieChartData(datums(7, label))).toBe(false);
|
|
803
|
+
expect(isPieChartData(datums(7, "Other documents"))).toBe(true);
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
test("keeps the generic pie limits", () => {
|
|
807
|
+
expect(isPieChartData(datums(50))).toBe(true);
|
|
808
|
+
expect(isPieChartData(datums(51))).toBe(false);
|
|
809
|
+
expect(isPieChartData([])).toBe(false);
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
test("is the guard the PieChart catalog entry uses", () => {
|
|
813
|
+
expect(sanitizeProps("ui-pie-chart", { data: datums(7, "Other") }).missing).toContain("data");
|
|
814
|
+
expect(sanitizeProps("ui-pie-chart", { data: datums(7) }).missing).not.toContain("data");
|
|
815
|
+
});
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
describe("isChartData", () => {
|
|
819
|
+
const bar = CHART_DATA_LIMITS.BarChart;
|
|
820
|
+
test("accepts a valid sample, including zero values and 60-character labels", () => {
|
|
821
|
+
expect(isChartData([{ label: "Mon", value: 0 }, { label: "x".repeat(60), value: 12.5 }], bar)).toBe(true);
|
|
822
|
+
});
|
|
823
|
+
test.each(BAD_VALUES)("rejects value %s", (value) => {
|
|
824
|
+
expect(isChartData([{ label: "a", value }], bar)).toBe(false);
|
|
825
|
+
});
|
|
826
|
+
test.each(BAD_LABELS)("rejects label %j", (label) => {
|
|
827
|
+
expect(isChartData([{ label, value: 1 }], bar)).toBe(false);
|
|
828
|
+
});
|
|
829
|
+
test("rejects duplicate labels", () => {
|
|
830
|
+
expect(isChartData([{ label: "a", value: 1 }, { label: "a", value: 2 }], bar)).toBe(false);
|
|
831
|
+
});
|
|
832
|
+
test("enforces each component's item counts", () => {
|
|
833
|
+
expect(isChartData([], bar)).toBe(false);
|
|
834
|
+
expect(isChartData(datums(31), bar)).toBe(true);
|
|
835
|
+
expect(isChartData(datums(32), bar)).toBe(false);
|
|
836
|
+
expect(isChartData(datums(25), CHART_DATA_LIMITS.HorizontalBarChart)).toBe(true);
|
|
837
|
+
expect(isChartData(datums(26), CHART_DATA_LIMITS.HorizontalBarChart)).toBe(false);
|
|
838
|
+
expect(isChartData(datums(50), CHART_DATA_LIMITS.PieChart)).toBe(true);
|
|
839
|
+
expect(isChartData(datums(51), CHART_DATA_LIMITS.PieChart)).toBe(false);
|
|
840
|
+
expect(sanitizeProps("ui-bar-chart", { data: datums(32) }).dropped).toEqual(["data"]);
|
|
841
|
+
expect(sanitizeProps("ui-pie-chart", { data: datums(32) }).dropped).toEqual([]);
|
|
842
|
+
});
|
|
843
|
+
test("rejects non-arrays, class instances, sparse arrays and extra keys", () => {
|
|
844
|
+
for (const v of [undefined, null, "a", 1, { label: "a", value: 1 }, new Map()]) expect(isChartData(v, bar)).toBe(false);
|
|
845
|
+
expect(isChartData([new Datum("a", 1)], bar)).toBe(false);
|
|
846
|
+
expect(isChartData(DatumArray.from([{ label: "a", value: 1 }]), bar)).toBe(false);
|
|
847
|
+
// eslint-disable-next-line no-sparse-arrays
|
|
848
|
+
expect(isChartData([{ label: "a", value: 1 }, , { label: "b", value: 2 }], bar)).toBe(false);
|
|
849
|
+
expect(isChartData([{ label: "a", value: 1, color: "red" }], bar)).toBe(false);
|
|
850
|
+
expect(isChartData([Object.assign(Object.create(null) as object, { label: "a", value: 1 })], bar)).toBe(true);
|
|
851
|
+
});
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
describe("isSeriesChartData", () => {
|
|
855
|
+
const stacked = CHART_DATA_LIMITS.StackedBarChart;
|
|
856
|
+
const line = CHART_DATA_LIMITS.LineChart;
|
|
857
|
+
test("accepts a valid sample", () => {
|
|
858
|
+
expect(isSeriesChartData(seriesData(5, 3), stacked)).toBe(true);
|
|
859
|
+
expect(isSeriesChartData(seriesData(5, MAX_CHART_SERIES), line)).toBe(true);
|
|
860
|
+
});
|
|
861
|
+
test("rejects more than six series, and no series", () => {
|
|
862
|
+
expect(isSeriesChartData(seriesData(5, MAX_CHART_SERIES + 1), stacked)).toBe(false);
|
|
863
|
+
expect(isSeriesChartData(seriesData(5, MAX_CHART_SERIES + 1), line)).toBe(false);
|
|
864
|
+
expect(isSeriesChartData(seriesData(5, 0), stacked)).toBe(false);
|
|
865
|
+
});
|
|
866
|
+
test("rejects a series whose values length differs from the labels", () => {
|
|
867
|
+
const d = seriesData(4);
|
|
868
|
+
d.series[1]!.values.pop();
|
|
869
|
+
expect(isSeriesChartData(d, stacked)).toBe(false);
|
|
870
|
+
d.series[1]!.values.push(1, 2);
|
|
871
|
+
expect(isSeriesChartData(d, stacked)).toBe(false);
|
|
872
|
+
});
|
|
873
|
+
test.each(BAD_VALUES)("rejects value %s", (value) => {
|
|
874
|
+
const d = seriesData(3) as { series: Array<{ values: unknown[] }> };
|
|
875
|
+
d.series[0]!.values[1] = value;
|
|
876
|
+
expect(isSeriesChartData(d, stacked)).toBe(false);
|
|
877
|
+
});
|
|
878
|
+
test.each(BAD_LABELS)("rejects label or series name %j", (bad) => {
|
|
879
|
+
const withLabel = seriesData(3) as { labels: unknown[] };
|
|
880
|
+
withLabel.labels[0] = bad;
|
|
881
|
+
expect(isSeriesChartData(withLabel, stacked)).toBe(false);
|
|
882
|
+
const withName = seriesData(3) as { series: Array<{ name: unknown }> };
|
|
883
|
+
withName.series[0]!.name = bad;
|
|
884
|
+
expect(isSeriesChartData(withName, stacked)).toBe(false);
|
|
885
|
+
});
|
|
886
|
+
test("rejects duplicate labels and duplicate series names", () => {
|
|
887
|
+
const dupLabel = seriesData(3);
|
|
888
|
+
dupLabel.labels[2] = dupLabel.labels[0]!;
|
|
889
|
+
expect(isSeriesChartData(dupLabel, stacked)).toBe(false);
|
|
890
|
+
const dupName = seriesData(3);
|
|
891
|
+
dupName.series[1]!.name = dupName.series[0]!.name;
|
|
892
|
+
expect(isSeriesChartData(dupName, stacked)).toBe(false);
|
|
893
|
+
});
|
|
894
|
+
test("enforces each component's label counts", () => {
|
|
895
|
+
expect(isSeriesChartData(seriesData(1), stacked)).toBe(true);
|
|
896
|
+
expect(isSeriesChartData(seriesData(31), stacked)).toBe(true);
|
|
897
|
+
expect(isSeriesChartData(seriesData(32), stacked)).toBe(false);
|
|
898
|
+
expect(isSeriesChartData(seriesData(1), line)).toBe(false);
|
|
899
|
+
expect(isSeriesChartData(seriesData(60), line)).toBe(true);
|
|
900
|
+
expect(isSeriesChartData(seriesData(61), line)).toBe(false);
|
|
901
|
+
expect(isSeriesChartData(seriesData(61), CHART_DATA_LIMITS.AreaChart)).toBe(false);
|
|
902
|
+
expect(isSeriesChartData(seriesData(1), CHART_DATA_LIMITS.AreaChart)).toBe(false);
|
|
903
|
+
});
|
|
904
|
+
test("rejects non-objects, class instances and extra keys", () => {
|
|
905
|
+
for (const v of [undefined, null, [], "x", datums(3)]) expect(isSeriesChartData(v, stacked)).toBe(false);
|
|
906
|
+
const d = seriesData(2);
|
|
907
|
+
expect(isSeriesChartData({ labels: d.labels, series: DatumArray.from(d.series) }, stacked)).toBe(false);
|
|
908
|
+
expect(isSeriesChartData({ ...d, labels: DatumArray.from(d.labels) }, stacked)).toBe(false);
|
|
909
|
+
expect(isSeriesChartData(Object.assign(new (class Data {})(), d), stacked)).toBe(false);
|
|
910
|
+
expect(isSeriesChartData({ ...d, title: "x" }, stacked)).toBe(false);
|
|
911
|
+
expect(isSeriesChartData({ ...d, series: [{ ...d.series[0]!, color: "red" }] }, stacked)).toBe(false);
|
|
912
|
+
});
|
|
913
|
+
});
|
|
914
|
+
|
|
915
|
+
describe("isComboChartData", () => {
|
|
916
|
+
const limits = CHART_DATA_LIMITS.ComboChart;
|
|
917
|
+
test("accepts a valid sample", () => {
|
|
918
|
+
expect(isComboChartData(combo(1), limits)).toBe(true);
|
|
919
|
+
expect(isComboChartData(combo(31), limits)).toBe(true);
|
|
920
|
+
});
|
|
921
|
+
test("rejects over-cap and empty labels", () => {
|
|
922
|
+
expect(isComboChartData(combo(32), limits)).toBe(false);
|
|
923
|
+
expect(isComboChartData(combo(0), limits)).toBe(false);
|
|
924
|
+
});
|
|
925
|
+
test("rejects bars or line values whose length differs from the labels", () => {
|
|
926
|
+
const bars = combo(3);
|
|
927
|
+
bars.bars.values.pop();
|
|
928
|
+
expect(isComboChartData(bars, limits)).toBe(false);
|
|
929
|
+
const line = combo(3);
|
|
930
|
+
line.line.values.push(1);
|
|
931
|
+
expect(isComboChartData(line, limits)).toBe(false);
|
|
932
|
+
});
|
|
933
|
+
test.each(BAD_VALUES)("rejects value %s", (value) => {
|
|
934
|
+
for (const key of ["bars", "line"] as const) {
|
|
935
|
+
const d = combo(3) as unknown as Record<typeof key, { values: unknown[] }>;
|
|
936
|
+
d[key].values[0] = value;
|
|
937
|
+
expect(isComboChartData(d, limits)).toBe(false);
|
|
938
|
+
}
|
|
939
|
+
});
|
|
940
|
+
test.each(BAD_LABELS)("rejects label or series name %j", (bad) => {
|
|
941
|
+
const withLabel = combo(3) as unknown as { labels: unknown[] };
|
|
942
|
+
withLabel.labels[1] = bad;
|
|
943
|
+
expect(isComboChartData(withLabel, limits)).toBe(false);
|
|
944
|
+
const withName = combo(3) as unknown as { line: { name: unknown } };
|
|
945
|
+
withName.line.name = bad;
|
|
946
|
+
expect(isComboChartData(withName, limits)).toBe(false);
|
|
947
|
+
});
|
|
948
|
+
test("rejects duplicate labels and a line named like the bars", () => {
|
|
949
|
+
const dupLabel = combo(3);
|
|
950
|
+
dupLabel.labels[1] = dupLabel.labels[0]!;
|
|
951
|
+
expect(isComboChartData(dupLabel, limits)).toBe(false);
|
|
952
|
+
const dupName = combo(3);
|
|
953
|
+
dupName.line.name = dupName.bars.name;
|
|
954
|
+
expect(isComboChartData(dupName, limits)).toBe(false);
|
|
955
|
+
});
|
|
956
|
+
test("rejects non-objects, class instances, series arrays and extra keys", () => {
|
|
957
|
+
for (const v of [undefined, null, [], "x", seriesData(3)]) expect(isComboChartData(v, limits)).toBe(false);
|
|
958
|
+
const d = combo(2);
|
|
959
|
+
expect(isComboChartData({ ...d, bars: [d.bars] }, limits)).toBe(false);
|
|
960
|
+
expect(isComboChartData({ ...d, labels: DatumArray.from(d.labels) }, limits)).toBe(false);
|
|
961
|
+
expect(isComboChartData(Object.assign(new (class Data {})(), d), limits)).toBe(false);
|
|
962
|
+
expect(isComboChartData({ ...d, extra: 1 }, limits)).toBe(false);
|
|
963
|
+
});
|
|
964
|
+
});
|
|
965
|
+
|
|
966
|
+
test("ComponentProps types chart data and the click detail (compile-time)", () => {
|
|
967
|
+
const bar: ComponentProps<"BarChart"> = {
|
|
968
|
+
data: [{ label: "Mon", value: 3 }],
|
|
969
|
+
theme: "vibrant",
|
|
970
|
+
interactive: true,
|
|
971
|
+
onClick: (e: ChartClickEvent) => e.index + e.value + e.label.length,
|
|
972
|
+
};
|
|
973
|
+
const comboProps: ComponentProps<"ComboChart"> = {
|
|
974
|
+
data: combo(2),
|
|
975
|
+
onClick: (e: ChartClickEvent) => e.series ?? e.label,
|
|
976
|
+
};
|
|
977
|
+
const stacked: ComponentProps<"StackedBarChart"> = { data: seriesData(2) };
|
|
978
|
+
// @ts-expect-error data is required
|
|
979
|
+
const noData: ComponentProps<"BarChart"> = { theme: "green" };
|
|
980
|
+
// @ts-expect-error a bar chart takes ChartDatum[], not series data
|
|
981
|
+
const wrongShape: ComponentProps<"BarChart"> = { data: seriesData(2) };
|
|
982
|
+
// @ts-expect-error themes are a closed set
|
|
983
|
+
const neon: ComponentProps<"PieChart"> = { data: datums(2), theme: "neon" };
|
|
984
|
+
// @ts-expect-error there are no colour props
|
|
985
|
+
const colored: ComponentProps<"LineChart"> = { data: seriesData(2), colors: ["#f00"] };
|
|
986
|
+
// @ts-expect-error onClick receives a ChartClickEvent, not a string
|
|
987
|
+
const wrongDetail: ComponentProps<"ComboChart"> = { data: combo(2), onClick: (s: string) => s.length };
|
|
988
|
+
expect([bar, comboProps, stacked, noData, wrongShape, neon, colored, wrongDetail]).toHaveLength(8);
|
|
989
|
+
});
|
|
990
|
+
});
|
|
991
|
+
|
|
691
992
|
describe("protocol and helpers", () => {
|
|
692
993
|
test("isBootstrapToHost accepts known envelopes only", () => {
|
|
693
994
|
expect(isBootstrapToHost({ kind: "ready" })).toBe(true);
|
|
@@ -749,7 +1050,7 @@ describe("protocol and helpers", () => {
|
|
|
749
1050
|
describe("bundle hygiene", () => {
|
|
750
1051
|
// The host renderer imports these; a value import of zod (directly or via manifest.ts or
|
|
751
1052
|
// devpreview.ts) would pull zod into the host app bundle. Type-only imports are erased.
|
|
752
|
-
test.each(["surfaces.ts", "route.ts", "context.ts", "protocol.ts", "components.ts", "url.ts", "devsession.ts", "review.ts"])(
|
|
1053
|
+
test.each(["surfaces.ts", "route.ts", "routes.ts", "context.ts", "protocol.ts", "components.ts", "url.ts", "devsession.ts", "review.ts"])(
|
|
753
1054
|
"%s has no value import of zod, manifest.ts or devpreview.ts",
|
|
754
1055
|
(file) => {
|
|
755
1056
|
const source = readFileSync(resolve(process.cwd(), "src", "apps", file), "utf8");
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Hand-written. Dev manifests (`green-app.dev.json`) and app pages: a dev file may override
|
|
3
|
+
* `ui_extensions.routes` the way it overrides views, so `apps-cli dev` previews a page before it is
|
|
4
|
+
* published. The server mirrors these rules in `MarketplaceAppDevManifest`; see
|
|
5
|
+
* docs/third-party-apps/fullpageview-plan.md.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, expect, test } from "vitest";
|
|
9
|
+
import {
|
|
10
|
+
APP_ROUTES_MAX,
|
|
11
|
+
devManifestSchema,
|
|
12
|
+
DevManifestError,
|
|
13
|
+
mergeDevManifest,
|
|
14
|
+
validateManifest,
|
|
15
|
+
type AppManifestV2,
|
|
16
|
+
} from "../../apps/index.js";
|
|
17
|
+
|
|
18
|
+
function page(path: string, fields: Record<string, unknown> = {}): Record<string, unknown> {
|
|
19
|
+
return { path, component: "Page", title: "Page", ...fields };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function published(overrides: Record<string, unknown> = {}): AppManifestV2 {
|
|
23
|
+
const result = validateManifest({
|
|
24
|
+
id: 42,
|
|
25
|
+
name: "Acme Reports",
|
|
26
|
+
icon: "https://cdn.acme.com/icon.png",
|
|
27
|
+
short_description: "Reports about your vendors.",
|
|
28
|
+
version: "1.0.0",
|
|
29
|
+
configuration_instructions: "Install and sign in.",
|
|
30
|
+
support_instructions: "support@acme.com",
|
|
31
|
+
ui_extensions: {
|
|
32
|
+
bundle: {
|
|
33
|
+
url: "https://cdn.acme.com/gs-app/1.0.0/app.js",
|
|
34
|
+
integrity: "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC",
|
|
35
|
+
},
|
|
36
|
+
views: [{ viewport: "settings", component: "AppSettings" }],
|
|
37
|
+
routes: [page("/reports")],
|
|
38
|
+
},
|
|
39
|
+
...overrides,
|
|
40
|
+
});
|
|
41
|
+
if (!result.ok) throw new Error("fixture invalid");
|
|
42
|
+
return result.manifest;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function issuePaths(value: unknown): string[] {
|
|
46
|
+
const result = devManifestSchema.safeParse(value);
|
|
47
|
+
return result.success ? [] : result.error.issues.map((issue) => issue.path.join("."));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
describe("dev manifest routes", () => {
|
|
51
|
+
test("a dev file may declare routes, with the published route rules", () => {
|
|
52
|
+
const dev = {
|
|
53
|
+
extends: "green-app.json",
|
|
54
|
+
ui_extensions: { routes: [page("/", { navigation: { label: "Home" } }), page("/reports/:id", { portals: ["vendor"] })] },
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
expect(devManifestSchema.safeParse(dev).success).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("dev routes are held to the grammar, title and portals rules", () => {
|
|
61
|
+
expect(issuePaths({ extends: "x", ui_extensions: { routes: [page("/../settings")] } })).toEqual(["ui_extensions.routes.0.path"]);
|
|
62
|
+
expect(issuePaths({ extends: "x", ui_extensions: { routes: [{ path: "/reports", component: "Page" }] } })).toEqual(["ui_extensions.routes.0.title"]);
|
|
63
|
+
expect(issuePaths({ extends: "x", ui_extensions: { routes: [page("/reports", { portals: ["admin"] })] } })).toEqual(["ui_extensions.routes.0.portals.0"]);
|
|
64
|
+
const tooMany = Array.from({ length: APP_ROUTES_MAX + 1 }, (_, i) => page(`/p${i}`));
|
|
65
|
+
expect(issuePaths({ extends: "x", ui_extensions: { routes: tooMany } })).toEqual(["ui_extensions.routes"]);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("dev routes reject duplicate paths, repeated params and repeated portals, like published ones", () => {
|
|
69
|
+
expect(issuePaths({ extends: "x", ui_extensions: { routes: [page("/vendors/:id"), page("/vendors/:vendor_id")] } }))
|
|
70
|
+
.toEqual(["ui_extensions.routes.1.path"]);
|
|
71
|
+
expect(issuePaths({ extends: "x", ui_extensions: { routes: [page("/a/:id/b/:id")] } })).toEqual(["ui_extensions.routes.0.path"]);
|
|
72
|
+
expect(issuePaths({ extends: "x", ui_extensions: { routes: [page("/r", { portals: ["vendor", "vendor"] })] } }))
|
|
73
|
+
.toEqual(["ui_extensions.routes.0.portals"]);
|
|
74
|
+
expect(issuePaths({ extends: "x", ui_extensions: { routes: [page("/r/:id", { navigation: {} })] } }))
|
|
75
|
+
.toEqual(["ui_extensions.routes.0.navigation"]);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("mergeDevManifest replaces the published routes when the dev file declares them", () => {
|
|
79
|
+
const routes = [page("/"), page("/reports/:id")];
|
|
80
|
+
const merged = mergeDevManifest(published(), devManifestSchema.parse({ extends: "green-app.json", ui_extensions: { routes } }));
|
|
81
|
+
|
|
82
|
+
expect(merged.ui_extensions?.routes).toEqual(routes);
|
|
83
|
+
expect(merged.ui_extensions?.views).toEqual([{ viewport: "settings", component: "AppSettings" }]);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("mergeDevManifest keeps the published routes when the dev file leaves them out, and drops them for []", () => {
|
|
87
|
+
const base = published();
|
|
88
|
+
|
|
89
|
+
expect(mergeDevManifest(base, { extends: "green-app.json", ui_extensions: { views: [] } }).ui_extensions?.routes)
|
|
90
|
+
.toEqual([page("/reports")]);
|
|
91
|
+
expect(mergeDevManifest(base, { extends: "green-app.json" }).ui_extensions?.routes).toEqual([page("/reports")]);
|
|
92
|
+
expect(mergeDevManifest(base, { extends: "green-app.json", ui_extensions: { routes: [] } }).ui_extensions?.routes).toEqual([]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("a versionless (v1) base cannot be previewed with routes", () => {
|
|
96
|
+
const v1 = published({ version: undefined, ui_extensions: undefined });
|
|
97
|
+
const dev = devManifestSchema.parse({ extends: "green-app.json", ui_extensions: { routes: [page("/")] } });
|
|
98
|
+
|
|
99
|
+
expect(() => mergeDevManifest(v1, dev)).toThrow(DevManifestError);
|
|
100
|
+
expect(() => mergeDevManifest(v1, dev)).toThrow("the base manifest needs a version before its routes can be previewed");
|
|
101
|
+
expect(() => mergeDevManifest(v1, { extends: "green-app.json", ui_extensions: { routes: [] } })).not.toThrow();
|
|
102
|
+
});
|
|
103
|
+
});
|