@augeo/smelt 1.2.2
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/.claude/settings.json +11 -0
- package/.github/workflows/verify.yml +64 -0
- package/.gitmodules +3 -0
- package/.prettierignore +25 -0
- package/.prettierrc.cjs +9 -0
- package/.zed/settings.json +21 -0
- package/AGENTS.md +232 -0
- package/LICENSE +21 -0
- package/README.md +266 -0
- package/biome.json +58 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +350 -0
- package/dist/schema.d.mts +265 -0
- package/dist/schema.mjs +21 -0
- package/docs/TESTING.md +293 -0
- package/docs/assets-plan.md +197 -0
- package/docs/build-spec.md +466 -0
- package/docs/library-conversion-plan.md +419 -0
- package/example/.gitattributes +7 -0
- package/example/.shopifyignore +28 -0
- package/example/.theme-check.yml +7 -0
- package/example/blocks/_built--sections--hero--blocks--feature.liquid +52 -0
- package/example/config/settings_schema.json +10 -0
- package/example/layout/theme.liquid +25 -0
- package/example/locales/en.default.json +1 -0
- package/example/package-lock.json +51 -0
- package/example/package.json +20 -0
- package/example/sections/built--sections--hero.liquid +83 -0
- package/example/snippets/built--components--button.liquid +38 -0
- package/example/snippets/built--components--card.liquid +33 -0
- package/example/src/components/button/button.css +13 -0
- package/example/src/components/card/card.css +16 -0
- package/example/src/components/card/card.liquid +9 -0
- package/example/src/sections/hero/blocks/feature/feature.css +11 -0
- package/example/src/sections/hero/blocks/feature/feature.liquid +9 -0
- package/example/src/sections/hero/blocks/feature/feature.schema.ts +14 -0
- package/example/src/sections/hero/hero.css +15 -0
- package/example/src/sections/hero/hero.liquid +16 -0
- package/example/src/sections/hero/hero.schema.ts +26 -0
- package/example/src/sections/hero/hero.test.ts +43 -0
- package/example/src/utilities/labels.ts +5 -0
- package/example/templates/index.liquid +1 -0
- package/example/tsconfig.json +10 -0
- package/example/vitest.config.ts +6 -0
- package/lib/build/build.test.ts +475 -0
- package/lib/build/build.ts +314 -0
- package/lib/build/command.ts +27 -0
- package/lib/build/index.ts +1 -0
- package/lib/cli.ts +17 -0
- package/lib/dev/command.ts +25 -0
- package/lib/dev/index.ts +1 -0
- package/lib/dev/watch.ts +52 -0
- package/lib/resolver.test.ts +275 -0
- package/lib/resolver.ts +156 -0
- package/lib/schema.ts +37 -0
- package/package.json +59 -0
- package/scripts/codegen-schema.ts +66 -0
- package/src/components/button/button.css +13 -0
- package/src/components/button/button.liquid +5 -0
- package/src/components/button/button.ts +5 -0
- package/src/tsconfig.json +10 -0
- package/tests/example.test.ts +101 -0
- package/tsconfig.json +20 -0
- package/tsdown.config.ts +14 -0
- package/vendor/theme-liquid-docs/.gitattributes +10 -0
- package/vendor/theme-liquid-docs/.github/CODEOWNERS +1 -0
- package/vendor/theme-liquid-docs/.github/CODE_OF_CONDUCT.md +73 -0
- package/vendor/theme-liquid-docs/.github/ISSUE_TEMPLATE/bug_report.md +17 -0
- package/vendor/theme-liquid-docs/.github/ISSUE_TEMPLATE/feature_request.md +17 -0
- package/vendor/theme-liquid-docs/.github/dependabot.yaml +6 -0
- package/vendor/theme-liquid-docs/.github/workflows/ci.yml +33 -0
- package/vendor/theme-liquid-docs/.github/workflows/cla.yml +27 -0
- package/vendor/theme-liquid-docs/.github/workflows/shopify-dev-preview-automation.yml +86 -0
- package/vendor/theme-liquid-docs/.github/workflows/update-latest.yml +56 -0
- package/vendor/theme-liquid-docs/.prettierrc.json +16 -0
- package/vendor/theme-liquid-docs/.vscode/settings.json +28 -0
- package/vendor/theme-liquid-docs/LICENSE.md +7 -0
- package/vendor/theme-liquid-docs/README.md +48 -0
- package/vendor/theme-liquid-docs/ai/claude/CLAUDE.md +1485 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/assets.mdc +15 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/blocks.mdc +339 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/examples/block-example-group.mdc +103 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/examples/block-example-text.mdc +59 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/examples/section-example.mdc +61 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/examples/snippet-example.mdc +72 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/liquid.mdc +837 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/locales.mdc +100 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/localization.mdc +67 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/mcp.mdc +2 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/schemas.mdc +184 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/sections.mdc +84 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/settings-schema.mdc +51 -0
- package/vendor/theme-liquid-docs/ai/cursor/rules/snippets.mdc +119 -0
- package/vendor/theme-liquid-docs/ai/github/copilot-instructions.md +1485 -0
- package/vendor/theme-liquid-docs/ai/liquid.mdc +638 -0
- package/vendor/theme-liquid-docs/data/filters.json +6148 -0
- package/vendor/theme-liquid-docs/data/latest.json +2 -0
- package/vendor/theme-liquid-docs/data/objects.json +20594 -0
- package/vendor/theme-liquid-docs/data/shopify_system_translations.json +2586 -0
- package/vendor/theme-liquid-docs/data/tags.json +1276 -0
- package/vendor/theme-liquid-docs/package.json +20 -0
- package/vendor/theme-liquid-docs/schemas/manifest_schema.json +31 -0
- package/vendor/theme-liquid-docs/schemas/manifest_theme.json +19 -0
- package/vendor/theme-liquid-docs/schemas/manifest_theme_app_extension.json +10 -0
- package/vendor/theme-liquid-docs/schemas/theme/app_block_entry.json +13 -0
- package/vendor/theme-liquid-docs/schemas/theme/default_setting_values.json +24 -0
- package/vendor/theme-liquid-docs/schemas/theme/local_block_entry.json +25 -0
- package/vendor/theme-liquid-docs/schemas/theme/preset.json +72 -0
- package/vendor/theme-liquid-docs/schemas/theme/preset_blocks.json +91 -0
- package/vendor/theme-liquid-docs/schemas/theme/section.json +208 -0
- package/vendor/theme-liquid-docs/schemas/theme/setting.json +1413 -0
- package/vendor/theme-liquid-docs/schemas/theme/settings.json +10 -0
- package/vendor/theme-liquid-docs/schemas/theme/targetted_block_entry.json +15 -0
- package/vendor/theme-liquid-docs/schemas/theme/theme_block.json +91 -0
- package/vendor/theme-liquid-docs/schemas/theme/theme_block_entry.json +14 -0
- package/vendor/theme-liquid-docs/schemas/theme/theme_settings.json +83 -0
- package/vendor/theme-liquid-docs/schemas/theme/translations.json +63 -0
- package/vendor/theme-liquid-docs/schemas/update/update_extension_schema_v1.json +186 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-nested-blocks.json +18 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-schema-1.json +90 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-schema-2.json +201 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-schema-3.json +29 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-schema-4.json +315 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-schema-5.json +114 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-schema-6.json +63 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-schema-conditional-settings.json +145 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-schema-preset-blocks-as-hash.json +60 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-schema-static-block-preset.json +76 -0
- package/vendor/theme-liquid-docs/tests/fixtures/section-settings.json +34 -0
- package/vendor/theme-liquid-docs/tests/fixtures/theme-block-1.json +234 -0
- package/vendor/theme-liquid-docs/tests/fixtures/theme-block-2.json +253 -0
- package/vendor/theme-liquid-docs/tests/fixtures/theme-block-basics.json +48 -0
- package/vendor/theme-liquid-docs/tests/fixtures/theme-block-conditional-settings.json +202 -0
- package/vendor/theme-liquid-docs/tests/fixtures/theme-block-presets-as-hash.json +50 -0
- package/vendor/theme-liquid-docs/tests/fixtures/theme-block-settings.json +34 -0
- package/vendor/theme-liquid-docs/tests/fixtures/theme-settings-all-settings.json +313 -0
- package/vendor/theme-liquid-docs/tests/fixtures/theme-settings-dawn.json +1469 -0
- package/vendor/theme-liquid-docs/tests/fixtures/theme-settings-metadata.json +10 -0
- package/vendor/theme-liquid-docs/tests/fixtures/translations-1.json +14 -0
- package/vendor/theme-liquid-docs/tests/section.spec.ts +367 -0
- package/vendor/theme-liquid-docs/tests/test-constants.ts +58 -0
- package/vendor/theme-liquid-docs/tests/test-helpers.ts +104 -0
- package/vendor/theme-liquid-docs/tests/theme-settings/color_palette.spec.ts +184 -0
- package/vendor/theme-liquid-docs/tests/theme-settings/color_scheme_group.spec.ts +143 -0
- package/vendor/theme-liquid-docs/tests/theme-settings/general.spec.ts +192 -0
- package/vendor/theme-liquid-docs/tests/theme-settings/metaobject.spec.ts +94 -0
- package/vendor/theme-liquid-docs/tests/theme-settings/resource_list.spec.ts +58 -0
- package/vendor/theme-liquid-docs/tests/theme-settings/theme-metadata.spec.ts +59 -0
- package/vendor/theme-liquid-docs/tests/theme_block.spec.ts +266 -0
- package/vendor/theme-liquid-docs/tests/translations_schema.spec.ts +31 -0
- package/vendor/theme-liquid-docs/yarn.lock +543 -0
- package/vitest.config.ts +7 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { validateSchema } from '../test-helpers';
|
|
3
|
+
|
|
4
|
+
const validate = validateSchema();
|
|
5
|
+
|
|
6
|
+
describe('Module: theme settings validation (config/settings_schema.json)', () => {
|
|
7
|
+
describe('Unit: color_palette', () => {
|
|
8
|
+
const colorPaletteSetting = {
|
|
9
|
+
type: 'color_palette',
|
|
10
|
+
id: 'color_palette',
|
|
11
|
+
default: {
|
|
12
|
+
background: '#ffffff',
|
|
13
|
+
foreground: '#000000',
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const settings = (override: any) => `[
|
|
18
|
+
{
|
|
19
|
+
"name": "setting category",
|
|
20
|
+
"settings": [
|
|
21
|
+
${JSON.stringify(Object.assign({}, colorPaletteSetting, override), null, 2)}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
]`;
|
|
25
|
+
|
|
26
|
+
it('accepts a valid color_palette setting', async () => {
|
|
27
|
+
const diagnostics = await validate('config/settings_schema.json', settings({}));
|
|
28
|
+
expect(diagnostics).toHaveLength(0);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('refuses the label property', async () => {
|
|
32
|
+
const diagnostics = await validate(
|
|
33
|
+
'config/settings_schema.json',
|
|
34
|
+
settings({ label: 'uh oh' }),
|
|
35
|
+
);
|
|
36
|
+
expect(diagnostics).toStrictEqual([
|
|
37
|
+
expect.objectContaining({
|
|
38
|
+
message: 'Property label is not allowed.',
|
|
39
|
+
}),
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('refuses the info property', async () => {
|
|
44
|
+
const diagnostics = await validate(
|
|
45
|
+
'config/settings_schema.json',
|
|
46
|
+
settings({ info: 'uh oh' }),
|
|
47
|
+
);
|
|
48
|
+
expect(diagnostics).toStrictEqual([
|
|
49
|
+
expect.objectContaining({
|
|
50
|
+
message: 'Property info is not allowed.',
|
|
51
|
+
}),
|
|
52
|
+
]);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('refuses the visible_if property', async () => {
|
|
56
|
+
const diagnostics = await validate(
|
|
57
|
+
'config/settings_schema.json',
|
|
58
|
+
settings({ visible_if: '{{ section.settings.show_palette }}' }),
|
|
59
|
+
);
|
|
60
|
+
expect(diagnostics).toStrictEqual([
|
|
61
|
+
expect.objectContaining({
|
|
62
|
+
message: 'Property visible_if is not allowed.',
|
|
63
|
+
}),
|
|
64
|
+
]);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('requires the default property', async () => {
|
|
68
|
+
const { default: _, ...settingWithoutDefault } = colorPaletteSetting;
|
|
69
|
+
const json = `[
|
|
70
|
+
{
|
|
71
|
+
"name": "setting category",
|
|
72
|
+
"settings": [
|
|
73
|
+
${JSON.stringify(settingWithoutDefault, null, 2)}
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
]`;
|
|
77
|
+
|
|
78
|
+
const diagnostics = await validate('config/settings_schema.json', json);
|
|
79
|
+
|
|
80
|
+
expect(diagnostics).toStrictEqual([
|
|
81
|
+
expect.objectContaining({
|
|
82
|
+
message: 'Missing property "default".',
|
|
83
|
+
}),
|
|
84
|
+
]);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('requires the id property', async () => {
|
|
88
|
+
const { id: _, ...settingWithoutId } = colorPaletteSetting;
|
|
89
|
+
const json = `[
|
|
90
|
+
{
|
|
91
|
+
"name": "setting category",
|
|
92
|
+
"settings": [
|
|
93
|
+
${JSON.stringify(settingWithoutId, null, 2)}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
]`;
|
|
97
|
+
|
|
98
|
+
const diagnostics = await validate('config/settings_schema.json', json);
|
|
99
|
+
|
|
100
|
+
expect(diagnostics).toStrictEqual([
|
|
101
|
+
expect.objectContaining({
|
|
102
|
+
message: 'Missing property "id".',
|
|
103
|
+
}),
|
|
104
|
+
]);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('validates that default must be an object', async () => {
|
|
108
|
+
const diagnostics = await validate(
|
|
109
|
+
'config/settings_schema.json',
|
|
110
|
+
settings({ default: '#ffffff' }),
|
|
111
|
+
);
|
|
112
|
+
expect(diagnostics).toStrictEqual([
|
|
113
|
+
expect.objectContaining({
|
|
114
|
+
message: 'Incorrect type. Expected "object".',
|
|
115
|
+
}),
|
|
116
|
+
]);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('validates that default values must be strings', async () => {
|
|
120
|
+
const diagnostics = await validate(
|
|
121
|
+
'config/settings_schema.json',
|
|
122
|
+
settings({ default: { background: 123 } }),
|
|
123
|
+
);
|
|
124
|
+
expect(diagnostics).toStrictEqual([
|
|
125
|
+
expect.objectContaining({
|
|
126
|
+
message: 'Incorrect type. Expected "string".',
|
|
127
|
+
}),
|
|
128
|
+
]);
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('refuses an empty default', async () => {
|
|
132
|
+
const diagnostics = await validate(
|
|
133
|
+
'config/settings_schema.json',
|
|
134
|
+
settings({ default: {} }),
|
|
135
|
+
);
|
|
136
|
+
expect(diagnostics).toStrictEqual([
|
|
137
|
+
expect.objectContaining({
|
|
138
|
+
message: 'Object has fewer properties than the required number of 1',
|
|
139
|
+
}),
|
|
140
|
+
]);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('refuses a default with more than 20 entries', async () => {
|
|
144
|
+
const tooMany = Object.fromEntries(
|
|
145
|
+
Array.from({ length: 21 }, (_, i) => [`color${i}`, '#000000']),
|
|
146
|
+
);
|
|
147
|
+
const diagnostics = await validate(
|
|
148
|
+
'config/settings_schema.json',
|
|
149
|
+
settings({ default: tooMany }),
|
|
150
|
+
);
|
|
151
|
+
expect(diagnostics).toStrictEqual([
|
|
152
|
+
expect.objectContaining({
|
|
153
|
+
message: 'Object has more properties than limit of 20.',
|
|
154
|
+
}),
|
|
155
|
+
]);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it('refuses default keys with hyphens', async () => {
|
|
159
|
+
const diagnostics = await validate(
|
|
160
|
+
'config/settings_schema.json',
|
|
161
|
+
settings({ default: { 'primary-1': '#fff' } }),
|
|
162
|
+
);
|
|
163
|
+
expect(diagnostics).toStrictEqual([
|
|
164
|
+
expect.objectContaining({
|
|
165
|
+
message:
|
|
166
|
+
'Color palette names must start with a letter and contain only letters, digits, and underscores.',
|
|
167
|
+
}),
|
|
168
|
+
]);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('refuses default keys starting with a digit', async () => {
|
|
172
|
+
const diagnostics = await validate(
|
|
173
|
+
'config/settings_schema.json',
|
|
174
|
+
settings({ default: { '1bad': '#fff' } }),
|
|
175
|
+
);
|
|
176
|
+
expect(diagnostics).toStrictEqual([
|
|
177
|
+
expect.objectContaining({
|
|
178
|
+
message:
|
|
179
|
+
'Color palette names must start with a letter and contain only letters, digits, and underscores.',
|
|
180
|
+
}),
|
|
181
|
+
]);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
});
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { validateSchema } from '../test-helpers';
|
|
3
|
+
|
|
4
|
+
const validate = validateSchema();
|
|
5
|
+
|
|
6
|
+
describe('Module: theme settings validation (config/settings_schema.json)', () => {
|
|
7
|
+
describe('Unit: color_scheme_group', () => {
|
|
8
|
+
const colorSchemeSetting = {
|
|
9
|
+
type: 'color_scheme_group',
|
|
10
|
+
id: 'color_schemes',
|
|
11
|
+
definition: [],
|
|
12
|
+
role: {
|
|
13
|
+
text: 'text',
|
|
14
|
+
background: {
|
|
15
|
+
solid: 'background',
|
|
16
|
+
gradient: 'background_gradient',
|
|
17
|
+
},
|
|
18
|
+
links: 'secondary_button_label',
|
|
19
|
+
icons: 'text',
|
|
20
|
+
primary_button: 'button',
|
|
21
|
+
on_primary_button: 'button_label',
|
|
22
|
+
primary_button_border: 'button',
|
|
23
|
+
secondary_button: 'background',
|
|
24
|
+
on_secondary_button: 'secondary_button_label',
|
|
25
|
+
secondary_button_border: 'secondary_button_label',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const settings = (override: any) => `[
|
|
30
|
+
{
|
|
31
|
+
"name": "setting category",
|
|
32
|
+
"settings": [
|
|
33
|
+
${JSON.stringify(Object.assign({}, colorSchemeSetting, override), null, 2)}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
]`;
|
|
37
|
+
|
|
38
|
+
it('refuses the label property', async () => {
|
|
39
|
+
const diagnostics = await validate(
|
|
40
|
+
'config/settings_schema.json',
|
|
41
|
+
settings({ label: 'uh oh' }),
|
|
42
|
+
);
|
|
43
|
+
expect(diagnostics).toStrictEqual([
|
|
44
|
+
expect.objectContaining({
|
|
45
|
+
message: 'Property label is not allowed.',
|
|
46
|
+
}),
|
|
47
|
+
]);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('validates that the definition are of type header, color or color_background', async () => {
|
|
51
|
+
const diagnostics = await validate(
|
|
52
|
+
'config/settings_schema.json',
|
|
53
|
+
settings({ definition: [{ type: 'not good' }] }),
|
|
54
|
+
);
|
|
55
|
+
expect(diagnostics).toStrictEqual([
|
|
56
|
+
expect.objectContaining({
|
|
57
|
+
message: 'Value is not accepted. Valid values: "header", "color", "color_background".',
|
|
58
|
+
}),
|
|
59
|
+
]);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('validates that the definition are of type header, color or color_background (extra properties)', async () => {
|
|
63
|
+
const diagnostics = await validate(
|
|
64
|
+
'config/settings_schema.json',
|
|
65
|
+
settings({
|
|
66
|
+
definition: [
|
|
67
|
+
{ type: 'header', content: 'ok', headerExtra: 'not allowed' },
|
|
68
|
+
{
|
|
69
|
+
type: 'color',
|
|
70
|
+
id: 'color',
|
|
71
|
+
label: 'my color',
|
|
72
|
+
default: '#000',
|
|
73
|
+
colorExtra: 'not allowed',
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
type: 'color_background',
|
|
77
|
+
id: 'color_bg',
|
|
78
|
+
label: 'my color background',
|
|
79
|
+
default: '#000',
|
|
80
|
+
colorBackgroundExtra: 'not allowed',
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
expect(diagnostics).toStrictEqual([
|
|
86
|
+
expect.objectContaining({
|
|
87
|
+
message: 'Property headerExtra is not allowed.',
|
|
88
|
+
}),
|
|
89
|
+
expect.objectContaining({
|
|
90
|
+
message: 'Property colorExtra is not allowed.',
|
|
91
|
+
}),
|
|
92
|
+
expect.objectContaining({
|
|
93
|
+
message: 'Property colorBackgroundExtra is not allowed.',
|
|
94
|
+
}),
|
|
95
|
+
]);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("validates that conditional settings (visible_if) is not allowed in color_scheme_group", async () => {
|
|
99
|
+
const diagnostics = await validate(
|
|
100
|
+
'config/settings_schema.json',
|
|
101
|
+
settings({ visible_if: '{{ section.settings.show_color_scheme_group }}',
|
|
102
|
+
}),
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("validates that conditional settings (visible_if) is not allowed in any nested definitions within color_scheme_group", async () => {
|
|
107
|
+
const diagnostics = await validate(
|
|
108
|
+
'config/settings_schema.json',
|
|
109
|
+
settings({
|
|
110
|
+
definition: [
|
|
111
|
+
{ type: 'header', content: 'ok', visible_if: '{{ section.settings.show_color_scheme_group }}' },
|
|
112
|
+
{
|
|
113
|
+
type: 'color',
|
|
114
|
+
id: 'color',
|
|
115
|
+
label: 'my color',
|
|
116
|
+
default: '#000',
|
|
117
|
+
visible_if: '{{ section.settings.show_color_scheme_group }}',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
type: 'color_background',
|
|
121
|
+
id: 'color_bg',
|
|
122
|
+
label: 'my color background',
|
|
123
|
+
default: '#000',
|
|
124
|
+
visible_if: '{{ section.settings.show_color_scheme_group }}',
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
}),
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
expect(diagnostics).toStrictEqual([
|
|
131
|
+
expect.objectContaining({
|
|
132
|
+
message: 'The property visible_if is not allowed within color_scheme_group',
|
|
133
|
+
}),
|
|
134
|
+
expect.objectContaining({
|
|
135
|
+
message: 'The property visible_if is not allowed within color_scheme_group',
|
|
136
|
+
}),
|
|
137
|
+
expect.objectContaining({
|
|
138
|
+
message: 'The property visible_if is not allowed within color_scheme_group',
|
|
139
|
+
}),
|
|
140
|
+
]);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
});
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { assert, describe, expect, it } from 'vitest';
|
|
2
|
+
import { INPUT_SETTING_TYPES, SIDEBAR_SETTING_TYPES } from '../test-constants';
|
|
3
|
+
import { complete, getService, hover, loadFixture, validateSchema } from '../test-helpers';
|
|
4
|
+
|
|
5
|
+
const themeSettingsMetadata = loadFixture('theme-settings-metadata.json');
|
|
6
|
+
const themeSettingsAllSettings = loadFixture('theme-settings-all-settings.json');
|
|
7
|
+
const themeSettingsDawn = loadFixture('theme-settings-dawn.json');
|
|
8
|
+
|
|
9
|
+
const validate = validateSchema();
|
|
10
|
+
const service = getService();
|
|
11
|
+
|
|
12
|
+
describe('Module: theme settings validation (config/settings_schema.json)', () => {
|
|
13
|
+
it('validates valid theme settings files', async () => {
|
|
14
|
+
const fixtures = [themeSettingsMetadata, themeSettingsAllSettings, themeSettingsDawn];
|
|
15
|
+
for (const fixture of fixtures) {
|
|
16
|
+
const diagnostics = await validate('config/settings_schema.json', fixture);
|
|
17
|
+
expect(diagnostics).toStrictEqual([]);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('rejects objects at the top level', async () => {
|
|
22
|
+
const diagnostics = await validate('config/settings_schema.json', { invalid: 'value' });
|
|
23
|
+
expect(diagnostics).toStrictEqual([
|
|
24
|
+
{
|
|
25
|
+
message: 'Incorrect type. Expected "array".',
|
|
26
|
+
severity: 1,
|
|
27
|
+
range: expect.objectContaining({
|
|
28
|
+
start: expect.objectContaining({
|
|
29
|
+
character: expect.any(Number),
|
|
30
|
+
line: expect.any(Number),
|
|
31
|
+
}),
|
|
32
|
+
end: expect.objectContaining({
|
|
33
|
+
character: expect.any(Number),
|
|
34
|
+
line: expect.any(Number),
|
|
35
|
+
}),
|
|
36
|
+
}),
|
|
37
|
+
},
|
|
38
|
+
]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('Unit: Settings', () => {
|
|
42
|
+
it('should report invalid enum values', async () => {
|
|
43
|
+
// Using JSON to make a deep copy of one of the valid schemas to mutate safely.
|
|
44
|
+
const settings = `[
|
|
45
|
+
{
|
|
46
|
+
"name": "some category",
|
|
47
|
+
"settings": [
|
|
48
|
+
{
|
|
49
|
+
"type": "not good",
|
|
50
|
+
"id": "some_id",
|
|
51
|
+
"label": "Some Label"
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
]`;
|
|
56
|
+
|
|
57
|
+
const diagnostics = await validate('config/settings_schema.json', settings);
|
|
58
|
+
expect(diagnostics).toStrictEqual([
|
|
59
|
+
{
|
|
60
|
+
code: 1,
|
|
61
|
+
message: expect.stringContaining(
|
|
62
|
+
'Value is not accepted. Valid values: "article", "article_list", "blog"',
|
|
63
|
+
),
|
|
64
|
+
severity: 1,
|
|
65
|
+
range: expect.objectContaining({
|
|
66
|
+
start: expect.objectContaining({
|
|
67
|
+
character: expect.any(Number),
|
|
68
|
+
line: expect.any(Number),
|
|
69
|
+
}),
|
|
70
|
+
end: expect.objectContaining({
|
|
71
|
+
character: expect.any(Number),
|
|
72
|
+
line: expect.any(Number),
|
|
73
|
+
}),
|
|
74
|
+
}),
|
|
75
|
+
},
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('has documentation for all input setting types that point to the input settings documentation', async () => {
|
|
80
|
+
for (const inputSetting of INPUT_SETTING_TYPES) {
|
|
81
|
+
const settings = `
|
|
82
|
+
[
|
|
83
|
+
{
|
|
84
|
+
"name": "some category",
|
|
85
|
+
"settings": [
|
|
86
|
+
{
|
|
87
|
+
"type": "${inputSetting}█"
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
]`;
|
|
92
|
+
const result = await hover(service, 'config/settings_schema.json', settings);
|
|
93
|
+
assert(result);
|
|
94
|
+
expect(result.contents).toContainEqual(
|
|
95
|
+
expect.stringContaining(
|
|
96
|
+
'https://shopify.dev/docs/themes/architecture/settings/input-settings#' + inputSetting,
|
|
97
|
+
),
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('has documentation for all sidebar setting types that point to the sidebar settings documentation', async () => {
|
|
103
|
+
for (const sidebarSetting of SIDEBAR_SETTING_TYPES) {
|
|
104
|
+
const settings = `
|
|
105
|
+
[
|
|
106
|
+
{
|
|
107
|
+
"name": "some category",
|
|
108
|
+
"settings": [
|
|
109
|
+
{
|
|
110
|
+
"type": "${sidebarSetting}█"
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
]`;
|
|
115
|
+
const result = await hover(service, 'config/settings_schema.json', settings);
|
|
116
|
+
assert(result);
|
|
117
|
+
expect(result.contents).toContainEqual(
|
|
118
|
+
expect.stringContaining(
|
|
119
|
+
'https://shopify.dev/docs/themes/architecture/settings/sidebar-settings#' +
|
|
120
|
+
sidebarSetting,
|
|
121
|
+
),
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('has standardized documentation for all setting types', async () => {
|
|
127
|
+
for (const setting of [...INPUT_SETTING_TYPES, ...SIDEBAR_SETTING_TYPES]) {
|
|
128
|
+
const settings = `
|
|
129
|
+
[
|
|
130
|
+
{
|
|
131
|
+
"name": "some category",
|
|
132
|
+
"settings": [
|
|
133
|
+
{
|
|
134
|
+
"type": "${setting}█"
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
]`;
|
|
139
|
+
const result = await hover(service, 'config/settings_schema.json', settings);
|
|
140
|
+
assert(result);
|
|
141
|
+
expect(result.contents).toContainEqual(
|
|
142
|
+
expect.stringContaining('A setting of type `' + setting + '`'),
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('completes the type property with the generic documentation', async () => {
|
|
148
|
+
const settings = `[
|
|
149
|
+
{
|
|
150
|
+
"name": "some category",
|
|
151
|
+
"settings": [
|
|
152
|
+
{
|
|
153
|
+
"type█"
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
]`;
|
|
158
|
+
const result = await complete(service, 'config/settings_schema.json', settings);
|
|
159
|
+
assert(result);
|
|
160
|
+
expect(result.items).toContainEqual(
|
|
161
|
+
expect.objectContaining({
|
|
162
|
+
documentation: expect.stringContaining(
|
|
163
|
+
'This value determines the type of field that gets rendered into the editor.',
|
|
164
|
+
),
|
|
165
|
+
}),
|
|
166
|
+
);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('completes the type value with the setting type enums', async () => {
|
|
170
|
+
const settings = `[
|
|
171
|
+
{
|
|
172
|
+
"name": "some category",
|
|
173
|
+
"settings": [
|
|
174
|
+
{
|
|
175
|
+
"type": "█"
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
]`;
|
|
180
|
+
const result = await complete(service, 'config/settings_schema.json', settings);
|
|
181
|
+
assert(result);
|
|
182
|
+
expect(result.items).to.have.lengthOf(INPUT_SETTING_TYPES.length + SIDEBAR_SETTING_TYPES.length);
|
|
183
|
+
for (const setting of [...INPUT_SETTING_TYPES, ...SIDEBAR_SETTING_TYPES]) {
|
|
184
|
+
expect(result.items).toContainEqual(
|
|
185
|
+
expect.objectContaining({
|
|
186
|
+
label: `"${setting}"`,
|
|
187
|
+
}),
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { validateSchema } from '../test-helpers';
|
|
3
|
+
|
|
4
|
+
const validate = validateSchema();
|
|
5
|
+
|
|
6
|
+
describe('Module: theme settings validation (config/settings_schema.json)', () => {
|
|
7
|
+
describe('Unit: metaobject settings', () => {
|
|
8
|
+
it('metaobject setting requires a metaobject_type', async () => {
|
|
9
|
+
const settings = `[
|
|
10
|
+
{
|
|
11
|
+
"name": "some category",
|
|
12
|
+
"settings": [
|
|
13
|
+
{
|
|
14
|
+
"type": "metaobject",
|
|
15
|
+
"id": "metaobject",
|
|
16
|
+
"label": "Metaobject"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
]`;
|
|
21
|
+
|
|
22
|
+
const diagnostics = await validate('config/settings_schema.json', settings);
|
|
23
|
+
|
|
24
|
+
expect(diagnostics).toStrictEqual([
|
|
25
|
+
expect.objectContaining({
|
|
26
|
+
message: `Missing property "metaobject_type".`,
|
|
27
|
+
}),
|
|
28
|
+
]);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('metaobject_list setting requires a metaobject_type', async () => {
|
|
32
|
+
const settings = `[
|
|
33
|
+
{
|
|
34
|
+
"name": "some category",
|
|
35
|
+
"settings": [
|
|
36
|
+
{
|
|
37
|
+
"type": "metaobject_list",
|
|
38
|
+
"id": "metaobject_list",
|
|
39
|
+
"label": "metaobject list"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
]`;
|
|
44
|
+
|
|
45
|
+
const diagnostics = await validate('config/settings_schema.json', settings);
|
|
46
|
+
|
|
47
|
+
expect(diagnostics).toStrictEqual([
|
|
48
|
+
expect.objectContaining({
|
|
49
|
+
message: `Missing property "metaobject_type".`,
|
|
50
|
+
}),
|
|
51
|
+
]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('metaobject setting allows a valid metaobject_type', async () => {
|
|
55
|
+
const settings = `[
|
|
56
|
+
{
|
|
57
|
+
"name": "some category",
|
|
58
|
+
"settings": [
|
|
59
|
+
{
|
|
60
|
+
"type": "metaobject",
|
|
61
|
+
"id": "metaobject",
|
|
62
|
+
"label": "Metaobject",
|
|
63
|
+
"metaobject_type": "author"
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
]`;
|
|
68
|
+
|
|
69
|
+
const diagnostics = await validate('config/settings_schema.json', settings);
|
|
70
|
+
|
|
71
|
+
expect(diagnostics).toHaveLength(0);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('metaobject_list setting allows a valid metaobject_type', async () => {
|
|
75
|
+
const settings = `[
|
|
76
|
+
{
|
|
77
|
+
"name": "some category",
|
|
78
|
+
"settings": [
|
|
79
|
+
{
|
|
80
|
+
"type": "metaobject_list",
|
|
81
|
+
"id": "metaobject_list",
|
|
82
|
+
"label": "Metaobject list",
|
|
83
|
+
"metaobject_type": "author"
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
]`;
|
|
88
|
+
|
|
89
|
+
const diagnostics = await validate('config/settings_schema.json', settings);
|
|
90
|
+
|
|
91
|
+
expect(diagnostics).toHaveLength(0);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { validateSchema } from '../test-helpers';
|
|
3
|
+
import { RESOURCE_LIST_SETTING_TYPES } from '../test-constants';
|
|
4
|
+
|
|
5
|
+
const validate = validateSchema();
|
|
6
|
+
|
|
7
|
+
describe('Module: theme settings validation (config/settings_schema.json)', () => {
|
|
8
|
+
describe.each(RESOURCE_LIST_SETTING_TYPES)('Resource list setting: %s', (setting_type) => {
|
|
9
|
+
it(`${setting_type} does not require a limit`, async () => {
|
|
10
|
+
const metaobject_type =
|
|
11
|
+
setting_type === 'metaobject_list' ? `, "metaobject_type": "author"` : '';
|
|
12
|
+
const settings = `[
|
|
13
|
+
{
|
|
14
|
+
"name": "some category",
|
|
15
|
+
"settings": [
|
|
16
|
+
{
|
|
17
|
+
"type": "${setting_type}",
|
|
18
|
+
"id": "${setting_type}",
|
|
19
|
+
"label": "${setting_type}"
|
|
20
|
+
${metaobject_type}
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
]`;
|
|
25
|
+
|
|
26
|
+
const diagnostics = await validate('config/settings_schema.json', settings);
|
|
27
|
+
|
|
28
|
+
expect(diagnostics).toHaveLength(0);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it(`${setting_type} allows having a numeric limit`, async () => {
|
|
32
|
+
const metaobject_type =
|
|
33
|
+
setting_type === 'metaobject_list' ? `, "metaobject_type": "author"` : '';
|
|
34
|
+
const settings = `[
|
|
35
|
+
{
|
|
36
|
+
"name": "some category",
|
|
37
|
+
"settings": [
|
|
38
|
+
{
|
|
39
|
+
"type": "${setting_type}",
|
|
40
|
+
"id": "${setting_type}",
|
|
41
|
+
"label": "${setting_type}",
|
|
42
|
+
"limit": 10
|
|
43
|
+
${metaobject_type}
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
]`;
|
|
48
|
+
|
|
49
|
+
const diagnostics = await validate('config/settings_schema.json', settings);
|
|
50
|
+
|
|
51
|
+
expect(diagnostics).not.toContainEqual(
|
|
52
|
+
expect.objectContaining({
|
|
53
|
+
message: expect.stringContaining('limit'),
|
|
54
|
+
}),
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|