@adobe/spectrum-component-api-schemas 6.0.0 → 6.1.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/CHANGELOG.md +33 -0
- package/index.js +28 -12
- package/moon.yml +1 -4
- package/package.json +3 -2
- package/scripts/convert-to-spec-format.mjs +136 -0
- package/test/index.test.js +64 -34
- package/test/integration.test.js +4 -6
- package/test/performance.test.js +7 -7
- package/test/schema-validation.test.js +64 -105
- package/schemas/component.json +0 -32
- package/schemas/components/accordion.json +0 -74
- package/schemas/components/action-bar.json +0 -18
- package/schemas/components/action-button.json +0 -62
- package/schemas/components/action-group.json +0 -69
- package/schemas/components/alert-banner.json +0 -29
- package/schemas/components/alert-dialog.json +0 -42
- package/schemas/components/avatar-group.json +0 -22
- package/schemas/components/avatar.json +0 -45
- package/schemas/components/badge.json +0 -69
- package/schemas/components/body.json +0 -25
- package/schemas/components/bottom-navigation-android.json +0 -37
- package/schemas/components/breadcrumbs.json +0 -72
- package/schemas/components/button-group.json +0 -33
- package/schemas/components/button.json +0 -61
- package/schemas/components/calendar.json +0 -100
- package/schemas/components/cards.json +0 -238
- package/schemas/components/checkbox-group.json +0 -49
- package/schemas/components/checkbox.json +0 -49
- package/schemas/components/close-button.json +0 -35
- package/schemas/components/coach-indicator.json +0 -34
- package/schemas/components/coach-mark.json +0 -51
- package/schemas/components/code.json +0 -21
- package/schemas/components/color-area.json +0 -64
- package/schemas/components/color-handle.json +0 -31
- package/schemas/components/color-loupe.json +0 -21
- package/schemas/components/color-slider.json +0 -66
- package/schemas/components/color-wheel.json +0 -47
- package/schemas/components/combo-box.json +0 -80
- package/schemas/components/contextual-help.json +0 -67
- package/schemas/components/date-picker.json +0 -157
- package/schemas/components/detail.json +0 -26
- package/schemas/components/divider.json +0 -23
- package/schemas/components/drop-zone.json +0 -41
- package/schemas/components/field-label.json +0 -39
- package/schemas/components/heading.json +0 -29
- package/schemas/components/help-text.json +0 -36
- package/schemas/components/illustrated-message.json +0 -45
- package/schemas/components/in-field-progress-button.json +0 -31
- package/schemas/components/in-field-progress-circle.json +0 -22
- package/schemas/components/in-line-alert.json +0 -43
- package/schemas/components/link.json +0 -32
- package/schemas/components/list-view.json +0 -89
- package/schemas/components/menu.json +0 -63
- package/schemas/components/meter.json +0 -44
- package/schemas/components/number-field.json +0 -57
- package/schemas/components/opacity-checkerboard.json +0 -21
- package/schemas/components/picker.json +0 -81
- package/schemas/components/popover.json +0 -65
- package/schemas/components/progress-bar.json +0 -64
- package/schemas/components/progress-circle.json +0 -41
- package/schemas/components/radio-button.json +0 -30
- package/schemas/components/radio-group.json +0 -58
- package/schemas/components/rating.json +0 -34
- package/schemas/components/scroll-zoom-bar.json +0 -44
- package/schemas/components/search-field.json +0 -58
- package/schemas/components/segmented-control.json +0 -72
- package/schemas/components/select-box.json +0 -50
- package/schemas/components/side-navigation.json +0 -59
- package/schemas/components/slider.json +0 -79
- package/schemas/components/standard-dialog.json +0 -49
- package/schemas/components/standard-panel.json +0 -49
- package/schemas/components/status-light.json +0 -51
- package/schemas/components/steplist.json +0 -52
- package/schemas/components/swatch-group.json +0 -44
- package/schemas/components/swatch.json +0 -46
- package/schemas/components/switch.json +0 -42
- package/schemas/components/tab-bar-ios.json +0 -37
- package/schemas/components/table.json +0 -118
- package/schemas/components/tabs.json +0 -75
- package/schemas/components/tag-field.json +0 -42
- package/schemas/components/tag-group.json +0 -31
- package/schemas/components/tag.json +0 -41
- package/schemas/components/takeover-dialog.json +0 -54
- package/schemas/components/text-area.json +0 -92
- package/schemas/components/text-field.json +0 -80
- package/schemas/components/thumbnail.json +0 -22
- package/schemas/components/toast.json +0 -29
- package/schemas/components/tooltip.json +0 -50
- package/schemas/components/tray.json +0 -17
- package/schemas/components/tree-view.json +0 -50
- package/schemas/types/hex-color.json +0 -8
- package/schemas/types/typography-classification.json +0 -9
- package/schemas/types/typography-script.json +0 -9
- package/schemas/types/workflow-icon.json +0 -901
- package/test/componentSchemaValidator.test.js +0 -74
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# [**@adobe/spectrum-component-api-schemas**](https://github.com/adobe/spectrum-component-api-schemas)
|
|
2
2
|
|
|
3
|
+
## 6.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`38127f5`](https://github.com/adobe/spectrum-design-data/commit/38127f556435783f31ab54c11d1ec6c93da17813)]:
|
|
8
|
+
- @adobe/design-data-spec@0.5.0
|
|
9
|
+
|
|
10
|
+
## 6.1.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- [#855](https://github.com/adobe/spectrum-design-data/pull/855) [`c9002db`](https://github.com/adobe/spectrum-design-data/commit/c9002db2da1d1bb40446b4991648dc7809a55f33) Thanks [@GarthDB](https://github.com/GarthDB)! - feat(component-schemas): migrate source of truth to design-data-spec components
|
|
15
|
+
|
|
16
|
+
`@adobe/spectrum-component-api-schemas` is now a thin adapter over
|
|
17
|
+
`@adobe/design-data-spec/components/`. All 80 component declarations have been
|
|
18
|
+
converted to the new format and live in `packages/design-data-spec/components/`.
|
|
19
|
+
|
|
20
|
+
The API surface is unchanged: `getAllSchemas()`, `getAllSlugs()`,
|
|
21
|
+
`getSchemaBySlug()`, `getSchemaFile()`, and `schemaFileNames` all behave
|
|
22
|
+
identically. Returned objects now include new fields (`name`, `displayName`,
|
|
23
|
+
`options`, `states`, `lifecycle`) alongside the existing aliases (`title`,
|
|
24
|
+
`properties`, `slug`) — no consumer breakage.
|
|
25
|
+
|
|
26
|
+
`@adobe/design-data-spec` minor: 79 component declarations added to
|
|
27
|
+
`components/`. `optionDescriptor` in `component.schema.json` now allows
|
|
28
|
+
additional JSON Schema keywords (`pattern`, `minimum`, `items`, etc.)
|
|
29
|
+
to accommodate real-world component option descriptors.
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- Updated dependencies [[`c9002db`](https://github.com/adobe/spectrum-design-data/commit/c9002db2da1d1bb40446b4991648dc7809a55f33)]:
|
|
34
|
+
- @adobe/design-data-spec@0.4.0
|
|
35
|
+
|
|
3
36
|
## 6.0.0
|
|
4
37
|
|
|
5
38
|
### Major Changes
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright
|
|
2
|
+
Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
@@ -13,6 +13,7 @@ import { glob } from "glob";
|
|
|
13
13
|
import { isAbsolute, resolve } from "path";
|
|
14
14
|
import { readFile } from "fs/promises";
|
|
15
15
|
import * as url from "url";
|
|
16
|
+
import { createRequire } from "module";
|
|
16
17
|
|
|
17
18
|
export const getSlugFromDocumentationUrl = (documentationUrl) =>
|
|
18
19
|
documentationUrl
|
|
@@ -25,22 +26,37 @@ export const readJson = async (fileName) =>
|
|
|
25
26
|
|
|
26
27
|
export const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
// Locate the design-data-spec package's components directory
|
|
30
|
+
const specPkgPath = createRequire(import.meta.url).resolve(
|
|
31
|
+
"@adobe/design-data-spec/package.json",
|
|
30
32
|
);
|
|
33
|
+
export const componentsDir = resolve(specPkgPath, "..", "components");
|
|
34
|
+
|
|
35
|
+
export const schemaFileNames = await glob(`${componentsDir}/*.json`);
|
|
36
|
+
|
|
37
|
+
// Add backward-compat aliases (title, properties) to a new-format component object.
|
|
38
|
+
// Slug is NOT added here — only getAllSchemas adds it, matching original behavior.
|
|
39
|
+
function withAliases(data) {
|
|
40
|
+
if (!Object.hasOwn(data, "meta")) return data;
|
|
41
|
+
return {
|
|
42
|
+
...data,
|
|
43
|
+
title: data.displayName,
|
|
44
|
+
properties: data.options,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
31
47
|
|
|
32
48
|
/**
|
|
33
|
-
* Accepts either a
|
|
49
|
+
* Accepts either a component filename (relative to componentsDir) or an absolute path.
|
|
34
50
|
*
|
|
35
51
|
* @param schemaFileName
|
|
36
52
|
* @return {Promise<any>}
|
|
37
53
|
*/
|
|
38
54
|
export const getSchemaFile = async (schemaFileName) => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return
|
|
55
|
+
const filePath = isAbsolute(schemaFileName)
|
|
56
|
+
? schemaFileName
|
|
57
|
+
: resolve(componentsDir, schemaFileName);
|
|
58
|
+
const data = await readJson(filePath);
|
|
59
|
+
return withAliases(data);
|
|
44
60
|
};
|
|
45
61
|
|
|
46
62
|
export const getAllSlugs = async () => {
|
|
@@ -74,7 +90,7 @@ export const getAllSchemas = async () => {
|
|
|
74
90
|
) {
|
|
75
91
|
return {
|
|
76
92
|
...data,
|
|
77
|
-
|
|
93
|
+
slug: getSlugFromDocumentationUrl(data.meta.documentationUrl),
|
|
78
94
|
};
|
|
79
95
|
} else return data;
|
|
80
96
|
}),
|
|
@@ -90,6 +106,6 @@ export const getSchemaBySlug = async (slug) => {
|
|
|
90
106
|
if (schema === undefined) {
|
|
91
107
|
throw new Error(`Schema not found for slug: ${slug}`);
|
|
92
108
|
}
|
|
93
|
-
|
|
94
|
-
return
|
|
109
|
+
const { slug: _, ...rest } = schema;
|
|
110
|
+
return rest;
|
|
95
111
|
};
|
package/moon.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2026 Adobe. All rights reserved.
|
|
2
2
|
# This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
3
3
|
# you may not use this file except in compliance with the License. You may obtain a copy
|
|
4
4
|
# of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
@@ -10,8 +10,6 @@
|
|
|
10
10
|
$schema: "https://moonrepo.dev/schemas/project.json"
|
|
11
11
|
layer: library
|
|
12
12
|
fileGroups:
|
|
13
|
-
schemas:
|
|
14
|
-
- "schemas/**/*.{yaml,yml,json}"
|
|
15
13
|
tests:
|
|
16
14
|
- "test/**/*"
|
|
17
15
|
tasks:
|
|
@@ -20,7 +18,6 @@ tasks:
|
|
|
20
18
|
- pnpm
|
|
21
19
|
- ava
|
|
22
20
|
inputs:
|
|
23
|
-
- "@globs(schemas)"
|
|
24
21
|
- "@globs(tests)"
|
|
25
22
|
- "index.js"
|
|
26
23
|
- "ava.config.js"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/spectrum-component-api-schemas",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.1.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
"homepage": "https://github.com/adobe/spectrum-design-data/tree/main/packages/component-schemas#readme",
|
|
19
19
|
"license": "Apache-2.0",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"glob": "^10.3.12"
|
|
21
|
+
"glob": "^10.3.12",
|
|
22
|
+
"@adobe/design-data-spec": "0.5.0"
|
|
22
23
|
},
|
|
23
24
|
"devDependencies": {
|
|
24
25
|
"ajv": "^8.12.0",
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2026 Adobe. All rights reserved.
|
|
3
|
+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
|
|
7
|
+
Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* One-time conversion script: old component-schemas format → new design-data-spec format.
|
|
15
|
+
*
|
|
16
|
+
* Reads packages/component-schemas/schemas/components/*.json (old format)
|
|
17
|
+
* and writes packages/design-data-spec/components/{name}.json (new format).
|
|
18
|
+
*
|
|
19
|
+
* Skips button.json (hand-crafted in Phase 6.4).
|
|
20
|
+
* Run: node packages/component-schemas/scripts/convert-to-spec-format.mjs
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
24
|
+
import { glob } from "glob";
|
|
25
|
+
import { resolve, dirname } from "path";
|
|
26
|
+
import { fileURLToPath } from "url";
|
|
27
|
+
|
|
28
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
29
|
+
const repoRoot = resolve(__dirname, "../../..");
|
|
30
|
+
const sourceDir = resolve(repoRoot, "packages/component-schemas/schemas/components");
|
|
31
|
+
const destDir = resolve(repoRoot, "packages/design-data-spec/components");
|
|
32
|
+
|
|
33
|
+
const SKIP = new Set(["button.json"]);
|
|
34
|
+
|
|
35
|
+
// States that are driven by runtime interaction (vs persistent prop).
|
|
36
|
+
const INTERACTION_STATES = new Set([
|
|
37
|
+
"hover",
|
|
38
|
+
"focus",
|
|
39
|
+
"focus-visible",
|
|
40
|
+
"active",
|
|
41
|
+
"pressed",
|
|
42
|
+
"down",
|
|
43
|
+
"keyboard-focus",
|
|
44
|
+
"dragging",
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
function toKebabCase(str) {
|
|
48
|
+
return str.trim().toLowerCase().replace(/\s+/g, "-");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getSlugFromDocumentationUrl(url) {
|
|
52
|
+
return url
|
|
53
|
+
.split("/")
|
|
54
|
+
.filter((p) => p !== "")
|
|
55
|
+
.pop();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function convertStateEnum(stateEnum) {
|
|
59
|
+
if (!Array.isArray(stateEnum)) return [];
|
|
60
|
+
return stateEnum
|
|
61
|
+
.filter((v) => v !== "default")
|
|
62
|
+
.map((v) => {
|
|
63
|
+
const name = toKebabCase(v);
|
|
64
|
+
const trigger = INTERACTION_STATES.has(name) ? "interaction" : "prop";
|
|
65
|
+
return { name, trigger };
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function convertFile(srcPath, fileName) {
|
|
70
|
+
const raw = await readFile(srcPath, "utf8");
|
|
71
|
+
const old = JSON.parse(raw);
|
|
72
|
+
|
|
73
|
+
const name = getSlugFromDocumentationUrl(old.meta.documentationUrl);
|
|
74
|
+
const displayName = old.title;
|
|
75
|
+
|
|
76
|
+
// properties → options (remove state; keep everything else)
|
|
77
|
+
const { state: stateProperty, ...remainingProperties } = old.properties ?? {};
|
|
78
|
+
const options = Object.keys(remainingProperties).length > 0 ? remainingProperties : undefined;
|
|
79
|
+
|
|
80
|
+
// Derive states from old state.enum
|
|
81
|
+
const stateList = convertStateEnum(stateProperty?.enum);
|
|
82
|
+
const states = stateList.length > 0 ? stateList : undefined;
|
|
83
|
+
|
|
84
|
+
// Build new $id and $schema
|
|
85
|
+
const newId = (old.$id ?? "").replace(
|
|
86
|
+
"https://opensource.adobe.com/spectrum-design-data/schemas/components/",
|
|
87
|
+
"https://opensource.adobe.com/spectrum-design-data/schemas/v0/components/",
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const newDoc = {
|
|
91
|
+
$schema:
|
|
92
|
+
"https://opensource.adobe.com/spectrum-design-data/schemas/v0/component.schema.json",
|
|
93
|
+
$id: newId,
|
|
94
|
+
specVersion: "1.0.0-draft",
|
|
95
|
+
name,
|
|
96
|
+
displayName,
|
|
97
|
+
...(old.description ? { description: old.description } : {}),
|
|
98
|
+
meta: old.meta,
|
|
99
|
+
...(options ? { options } : {}),
|
|
100
|
+
...(states ? { states } : {}),
|
|
101
|
+
lifecycle: { introduced: "1.0.0-draft" },
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return newDoc;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function main() {
|
|
108
|
+
await mkdir(destDir, { recursive: true });
|
|
109
|
+
|
|
110
|
+
const srcFiles = (await glob(`${sourceDir}/*.json`)).sort();
|
|
111
|
+
let converted = 0;
|
|
112
|
+
let skipped = 0;
|
|
113
|
+
|
|
114
|
+
for (const srcPath of srcFiles) {
|
|
115
|
+
const fileName = srcPath.split("/").pop();
|
|
116
|
+
|
|
117
|
+
if (SKIP.has(fileName)) {
|
|
118
|
+
console.log(` skip ${fileName} (hand-crafted)`);
|
|
119
|
+
skipped++;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const newDoc = await convertFile(srcPath, fileName);
|
|
124
|
+
const destPath = resolve(destDir, fileName);
|
|
125
|
+
await writeFile(destPath, JSON.stringify(newDoc, null, 2) + "\n", "utf8");
|
|
126
|
+
console.log(` write ${fileName} → ${newDoc.name}`);
|
|
127
|
+
converted++;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log(`\nDone: ${converted} converted, ${skipped} skipped.`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
main().catch((err) => {
|
|
134
|
+
console.error(err);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
});
|
package/test/index.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright
|
|
2
|
+
Copyright 2026 Adobe. All rights reserved.
|
|
3
3
|
This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
5
|
of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
@@ -16,63 +16,93 @@ import {
|
|
|
16
16
|
getAllSchemas,
|
|
17
17
|
getSlugFromDocumentationUrl,
|
|
18
18
|
getAllSlugs,
|
|
19
|
-
|
|
19
|
+
componentsDir,
|
|
20
20
|
getSchemaBySlug,
|
|
21
21
|
} from "../index.js";
|
|
22
22
|
import test from "ava";
|
|
23
23
|
import { glob } from "glob";
|
|
24
24
|
import { resolve, parse } from "path";
|
|
25
25
|
|
|
26
|
-
test("the number of
|
|
26
|
+
test("the number of schemas returned by getAllSchemas should match the number of schemaFileNames", async (t) => {
|
|
27
27
|
const allSchemas = await getAllSchemas();
|
|
28
28
|
t.is(schemaFileNames.length, allSchemas.length);
|
|
29
29
|
});
|
|
30
|
-
test("getSchemaFile should fetch schema data", async (t) => {
|
|
31
|
-
const relativeSchemaComponent = await getSchemaFile("component.json");
|
|
32
|
-
t.is(relativeSchemaComponent.title, "Component");
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
t.is(
|
|
31
|
+
test("getSchemaFile should fetch schema data using a relative filename", async (t) => {
|
|
32
|
+
const schema = await getSchemaFile("action-bar.json");
|
|
33
|
+
// new-format field
|
|
34
|
+
t.is(schema.displayName, "Action bar");
|
|
35
|
+
// backward-compat alias
|
|
36
|
+
t.is(schema.title, "Action bar");
|
|
37
|
+
t.truthy(schema.name);
|
|
38
|
+
t.truthy(schema.meta?.documentationUrl);
|
|
39
|
+
});
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
);
|
|
42
|
-
t.is(
|
|
41
|
+
test("getSchemaFile should fetch schema data using an absolute path", async (t) => {
|
|
42
|
+
const schema = await getSchemaFile(resolve(componentsDir, "action-bar.json"));
|
|
43
|
+
t.is(schema.displayName, "Action bar");
|
|
44
|
+
t.is(schema.title, "Action bar");
|
|
45
|
+
});
|
|
43
46
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
t.
|
|
48
|
-
//
|
|
47
|
+
test("getSchemaFile returned objects include backward-compat properties alias", async (t) => {
|
|
48
|
+
const schema = await getSchemaFile("checkbox.json");
|
|
49
|
+
// options is the new-format field
|
|
50
|
+
t.truthy(schema.options);
|
|
51
|
+
// properties is the compat alias
|
|
52
|
+
t.is(schema.properties, schema.options);
|
|
49
53
|
});
|
|
54
|
+
|
|
50
55
|
test("getSlugFromDocumentationUrl should return last part of documentationUrl", (t) => {
|
|
51
56
|
t.is(
|
|
52
57
|
getSlugFromDocumentationUrl("https://spectrum.adobe.com/page/tooltip/"),
|
|
53
58
|
"tooltip",
|
|
54
59
|
);
|
|
55
60
|
});
|
|
61
|
+
|
|
56
62
|
test("getSlugFromDocumentationUrl should return last part of documentationUrl even without trailing slash", (t) => {
|
|
57
63
|
t.is(
|
|
58
64
|
getSlugFromDocumentationUrl("https://spectrum.adobe.com/page/tooltip"),
|
|
59
65
|
"tooltip",
|
|
60
66
|
);
|
|
61
67
|
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
);
|
|
68
|
+
|
|
69
|
+
test("getAllSlugs should return all component slugs sorted", async (t) => {
|
|
70
|
+
// getAllSlugs() extracts slugs from documentationUrl. This asserts that
|
|
71
|
+
// URL slugs match filename stems — a required invariant for all components.
|
|
72
|
+
const files = await glob(`${componentsDir}/*.json`);
|
|
73
|
+
const expected = files.map((f) => parse(f).name).sort();
|
|
74
|
+
t.deepEqual(await getAllSlugs(), expected);
|
|
70
75
|
});
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
|
|
77
|
+
test("getAllSchemas should include slug, title, displayName, properties, and options on each schema", async (t) => {
|
|
78
|
+
const schemas = await getAllSchemas();
|
|
79
|
+
for (const schema of schemas) {
|
|
80
|
+
if (
|
|
81
|
+
Object.hasOwn(schema, "meta") &&
|
|
82
|
+
Object.hasOwn(schema.meta, "documentationUrl")
|
|
83
|
+
) {
|
|
84
|
+
t.truthy(schema.slug, `${schema.name}: missing slug`);
|
|
85
|
+
t.truthy(schema.displayName, `${schema.name}: missing displayName`);
|
|
86
|
+
t.is(
|
|
87
|
+
schema.title,
|
|
88
|
+
schema.displayName,
|
|
89
|
+
`${schema.name}: title alias mismatch`,
|
|
90
|
+
);
|
|
91
|
+
t.truthy(schema.name, `${schema.name}: missing name`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("getSchemaBySlug should return a schema without a slug field", async (t) => {
|
|
97
|
+
const schema = await getSchemaBySlug("tooltip");
|
|
98
|
+
t.is(schema.displayName, "Tooltip");
|
|
99
|
+
t.is(schema.title, "Tooltip");
|
|
100
|
+
t.is(schema.name, "tooltip");
|
|
101
|
+
t.false(Object.hasOwn(schema, "slug"));
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test("getSchemaBySlug should throw for unknown slug", async (t) => {
|
|
105
|
+
await t.throwsAsync(async () => getSchemaBySlug("not-a-real-component"), {
|
|
106
|
+
message: /Schema not found for slug: not-a-real-component/,
|
|
107
|
+
});
|
|
78
108
|
});
|
package/test/integration.test.js
CHANGED
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
getAllSlugs,
|
|
6
6
|
getSlugFromDocumentationUrl,
|
|
7
7
|
schemaFileNames,
|
|
8
|
+
componentsDir,
|
|
8
9
|
} from "../index.js";
|
|
9
|
-
import {
|
|
10
|
-
import { relative } from "path";
|
|
10
|
+
import { glob } from "glob";
|
|
11
11
|
|
|
12
12
|
test("getAllSchemas should return all schemas with slugs", async (t) => {
|
|
13
13
|
const schemas = await getAllSchemas();
|
|
@@ -83,15 +83,13 @@ test("getSlugFromDocumentationUrl should handle various URL formats", (t) => {
|
|
|
83
83
|
});
|
|
84
84
|
|
|
85
85
|
test("schemaFileNames should match actual files on disk", async (t) => {
|
|
86
|
-
const actualFiles = await
|
|
86
|
+
const actualFiles = await glob(`${componentsDir}/*.json`);
|
|
87
87
|
|
|
88
88
|
t.is(schemaFileNames.length, actualFiles.length);
|
|
89
89
|
|
|
90
|
-
// Verify all files in schemaFileNames exist
|
|
91
90
|
for (const fileName of schemaFileNames) {
|
|
92
|
-
const relativePath = relative(process.cwd(), fileName);
|
|
93
91
|
t.true(
|
|
94
|
-
actualFiles.includes(
|
|
92
|
+
actualFiles.includes(fileName),
|
|
95
93
|
`File ${fileName} not found on disk`,
|
|
96
94
|
);
|
|
97
95
|
}
|
package/test/performance.test.js
CHANGED
|
@@ -59,14 +59,14 @@ test("getSchemaBySlug should complete within reasonable time", async (t) => {
|
|
|
59
59
|
|
|
60
60
|
test("getSchemaFile should complete within reasonable time", async (t) => {
|
|
61
61
|
const start = performance.now();
|
|
62
|
-
const schema = await getSchemaFile("
|
|
62
|
+
const schema = await getSchemaFile("button.json");
|
|
63
63
|
const end = performance.now();
|
|
64
64
|
const duration = end - start;
|
|
65
65
|
|
|
66
|
-
// Should complete within
|
|
66
|
+
// Should complete within 500ms (generous for CI runner variability)
|
|
67
67
|
t.true(
|
|
68
|
-
duration <
|
|
69
|
-
`getSchemaFile took ${duration.toFixed(2)}ms, expected <
|
|
68
|
+
duration < 500,
|
|
69
|
+
`getSchemaFile took ${duration.toFixed(2)}ms, expected < 500ms`,
|
|
70
70
|
);
|
|
71
71
|
t.truthy(schema);
|
|
72
72
|
});
|
|
@@ -89,10 +89,10 @@ test("multiple concurrent getSchemaBySlug calls should complete efficiently", as
|
|
|
89
89
|
const end = performance.now();
|
|
90
90
|
const duration = end - start;
|
|
91
91
|
|
|
92
|
-
// Should complete within
|
|
92
|
+
// Should complete within 500ms for 3 concurrent calls (generous for CI runner variability)
|
|
93
93
|
t.true(
|
|
94
|
-
duration <
|
|
95
|
-
`Concurrent getSchemaBySlug calls took ${duration.toFixed(2)}ms, expected <
|
|
94
|
+
duration < 500,
|
|
95
|
+
`Concurrent getSchemaBySlug calls took ${duration.toFixed(2)}ms, expected < 500ms`,
|
|
96
96
|
);
|
|
97
97
|
t.is(results.length, 3);
|
|
98
98
|
t.true(results.every((schema) => schema !== null));
|