Skip to content

Commit 54e07d3

Browse files
committed
Validate section setting keys in JSON templates
1 parent c0a6504 commit 54e07d3

4 files changed

Lines changed: 400 additions & 18 deletions

File tree

.changeset/bright-keys-check.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@shopify/theme-check-common': minor
3+
---
4+
5+
Validate section setting keys in JSON templates.

packages/theme-check-common/src/checks/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ import { ValidRenderSnippetArgumentTypes } from './valid-render-snippet-argument
6262
import { ValidSchema } from './valid-schema';
6363
import { ValidSchemaName } from './valid-schema-name';
6464
import { ValidSchemaTranslations } from './valid-schema-translations';
65-
import { ValidSettingsKey } from './valid-settings-key';
65+
import { ValidSettingsKey, ValidSettingsKeyJSON } from './valid-settings-key';
6666
import { ValidStaticBlockType } from './valid-static-block-type';
6767
import { ValidVisibleIf, ValidVisibleIfSettingsSchema } from './valid-visible-if';
6868
import { VariableName } from './variable-name';
@@ -133,6 +133,7 @@ export const allChecks: (LiquidCheckDefinition | JSONCheckDefinition)[] = [
133133
ValidRenderSnippetArgumentTypes,
134134
ValidSchema,
135135
ValidSettingsKey,
136+
ValidSettingsKeyJSON,
136137
ValidStaticBlockType,
137138
ValidVisibleIf,
138139
ValidVisibleIfSettingsSchema,

packages/theme-check-common/src/checks/valid-settings-key/index.spec.ts

Lines changed: 251 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect, describe, it } from 'vitest';
22
import { check } from '../../test';
3-
import { ValidSettingsKey } from './index';
3+
import { ValidSettingsKey, ValidSettingsKeyJSON } from './index';
44

55
describe('Module: ValidSettingsKey', () => {
66
const schemaTemplate = {
@@ -116,6 +116,256 @@ describe('Module: ValidSettingsKey', () => {
116116
});
117117
});
118118

119+
describe('template JSON section settings', () => {
120+
it('does not report an error when a template JSON section setting exists in the section schema', async () => {
121+
const theme = {
122+
'templates/page.json': JSON.stringify({
123+
sections: {
124+
'main-page': {
125+
type: 'main-page',
126+
settings: {
127+
heading_tag: 'h1',
128+
},
129+
},
130+
},
131+
order: ['main-page'],
132+
}),
133+
'sections/main-page.liquid': toLiquidFile({
134+
name: 'Main page',
135+
settings: [
136+
{
137+
id: 'heading_tag',
138+
type: 'select',
139+
label: 'Heading tag',
140+
options: [
141+
{ value: 'h1', label: 'H1' },
142+
{ value: 'h2', label: 'H2' },
143+
],
144+
},
145+
],
146+
}),
147+
};
148+
149+
const offenses = await check(theme, [ValidSettingsKey, ValidSettingsKeyJSON]);
150+
expect(offenses).to.have.length(0);
151+
});
152+
153+
it('reports an error when a template JSON section setting does not exist in the section schema', async () => {
154+
const theme = {
155+
'templates/page.json': JSON.stringify({
156+
sections: {
157+
'main-page': {
158+
type: 'main-page',
159+
settings: {
160+
heading_tagg: 'h1',
161+
},
162+
},
163+
},
164+
order: ['main-page'],
165+
}),
166+
'sections/main-page.liquid': toLiquidFile({
167+
name: 'Main page',
168+
settings: [
169+
{
170+
id: 'heading_tag',
171+
type: 'select',
172+
label: 'Heading tag',
173+
options: [
174+
{ value: 'h1', label: 'H1' },
175+
{ value: 'h2', label: 'H2' },
176+
],
177+
},
178+
],
179+
}),
180+
};
181+
182+
const offenses = await check(theme, [ValidSettingsKey, ValidSettingsKeyJSON]);
183+
expect(offenses).to.have.length(1);
184+
expect(offenses[0].message).to.equal(
185+
`Setting 'heading_tagg' does not exist in 'sections/main-page.liquid'.`,
186+
);
187+
});
188+
});
189+
190+
describe('template JSON block settings', () => {
191+
it('does not report an error when a template JSON block setting exists in the block schema', async () => {
192+
const theme = {
193+
'templates/page.json': JSON.stringify({
194+
sections: {
195+
'main-page': {
196+
type: 'main-page',
197+
blocks: {
198+
text: {
199+
type: 'text',
200+
settings: {
201+
heading: 'Hello',
202+
},
203+
},
204+
},
205+
block_order: ['text'],
206+
},
207+
},
208+
order: ['main-page'],
209+
}),
210+
'sections/main-page.liquid': toLiquidFile({
211+
name: 'Main page',
212+
blocks: [{ type: 'text' }],
213+
}),
214+
'blocks/text.liquid': toLiquidFile({
215+
name: 'Text',
216+
settings: [
217+
{
218+
id: 'heading',
219+
type: 'text',
220+
label: 'Heading',
221+
},
222+
],
223+
}),
224+
};
225+
226+
const offenses = await check(theme, [ValidSettingsKey, ValidSettingsKeyJSON]);
227+
expect(offenses).to.have.length(0);
228+
});
229+
230+
it('reports an error when a template JSON block setting does not exist in the block schema', async () => {
231+
const theme = {
232+
'templates/page.json': JSON.stringify({
233+
sections: {
234+
'main-page': {
235+
type: 'main-page',
236+
blocks: {
237+
text: {
238+
type: 'text',
239+
settings: {
240+
headingg: 'Hello',
241+
},
242+
},
243+
},
244+
block_order: ['text'],
245+
},
246+
},
247+
order: ['main-page'],
248+
}),
249+
'sections/main-page.liquid': toLiquidFile({
250+
name: 'Main page',
251+
blocks: [{ type: 'text' }],
252+
}),
253+
'blocks/text.liquid': toLiquidFile({
254+
name: 'Text',
255+
settings: [
256+
{
257+
id: 'heading',
258+
type: 'text',
259+
label: 'Heading',
260+
},
261+
],
262+
}),
263+
};
264+
265+
const offenses = await check(theme, [ValidSettingsKey, ValidSettingsKeyJSON]);
266+
expect(offenses).to.have.length(1);
267+
expect(offenses[0].message).to.equal(
268+
`Setting 'headingg' does not exist in 'blocks/text.liquid'.`,
269+
);
270+
});
271+
272+
it('reports an error when a template JSON local block setting does not exist in the section schema', async () => {
273+
const theme = {
274+
'templates/page.json': JSON.stringify({
275+
sections: {
276+
'main-page': {
277+
type: 'main-page',
278+
blocks: {
279+
foo: {
280+
type: 'foo',
281+
settings: {
282+
headingg: 'Hello',
283+
},
284+
},
285+
},
286+
block_order: ['foo'],
287+
},
288+
},
289+
order: ['main-page'],
290+
}),
291+
'sections/main-page.liquid': toLiquidFile({
292+
name: 'Main page',
293+
blocks: [
294+
{
295+
type: 'foo',
296+
name: 'Foo',
297+
settings: [
298+
{
299+
id: 'heading',
300+
type: 'text',
301+
label: 'Heading',
302+
},
303+
],
304+
},
305+
],
306+
}),
307+
};
308+
309+
const offenses = await check(theme, [ValidSettingsKey, ValidSettingsKeyJSON]);
310+
expect(offenses).to.have.length(1);
311+
expect(offenses[0].message).to.equal(
312+
`Setting 'headingg' does not exist in 'sections/main-page.liquid'.`,
313+
);
314+
});
315+
316+
it('reports an error when a nested template JSON block setting does not exist in the nested block schema', async () => {
317+
const theme = {
318+
'templates/page.json': JSON.stringify({
319+
sections: {
320+
'main-page': {
321+
type: 'main-page',
322+
blocks: {
323+
parent: {
324+
type: 'parent',
325+
blocks: {
326+
text: {
327+
type: 'text',
328+
settings: {
329+
headingg: 'Hello',
330+
},
331+
},
332+
},
333+
block_order: ['text'],
334+
},
335+
},
336+
block_order: ['parent'],
337+
},
338+
},
339+
order: ['main-page'],
340+
}),
341+
'sections/main-page.liquid': toLiquidFile({
342+
name: 'Main page',
343+
blocks: [{ type: 'parent' }],
344+
}),
345+
'blocks/parent.liquid': toLiquidFile({
346+
name: 'Parent',
347+
blocks: [{ type: 'text' }],
348+
}),
349+
'blocks/text.liquid': toLiquidFile({
350+
name: 'Text',
351+
settings: [
352+
{
353+
id: 'heading',
354+
type: 'text',
355+
label: 'Heading',
356+
},
357+
],
358+
}),
359+
};
360+
361+
const offenses = await check(theme, [ValidSettingsKey, ValidSettingsKeyJSON]);
362+
expect(offenses).to.have.length(1);
363+
expect(offenses[0].message).to.equal(
364+
`Setting 'headingg' does not exist in 'blocks/text.liquid'.`,
365+
);
366+
});
367+
});
368+
119369
const tests = [
120370
{
121371
label: 'default',

0 commit comments

Comments
 (0)