Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add theme.json schema tests #44252

Merged
merged 10 commits into from
Sep 21, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ Border styles.
| radius | undefined | |
| style | string | |
| width | string | |
| top | undefined | |
| right | undefined | |
| bottom | undefined | |
| left | undefined | |
| top | object | color, style, width |
| right | object | color, style, width |
| bottom | object | color, style, width |
| left | object | color, style, width |

---

Expand Down
143 changes: 88 additions & 55 deletions schemas/json/theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"reference": "https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/"
},
"settingsPropertiesAppearanceTools": {
"type": "object",
"properties": {
"appearanceTools": {
"description": "Setting that enables the following UI tools:\n\n- border: color, radius, style, width\n- color: link\n- spacing: blockGap, margin, padding\n- typography: lineHeight",
Expand All @@ -26,6 +27,7 @@
}
},
"settingsPropertiesBorder": {
"type": "object",
"properties": {
"border": {
"description": "Settings related to borders.",
Expand Down Expand Up @@ -57,6 +59,7 @@
}
},
"settingsPropertiesColor": {
"type": "object",
"properties": {
"color": {
"description": "Settings related to colors.",
Expand Down Expand Up @@ -186,6 +189,7 @@
}
},
"settingsPropertiesLayout": {
"type": "object",
"properties": {
"layout": {
"description": "Settings related to layout.",
Expand All @@ -205,6 +209,7 @@
}
},
"settingsPropertiesSpacing": {
"type": "object",
"properties": {
"spacing": {
"description": "Settings related to spacing.",
Expand Down Expand Up @@ -305,6 +310,7 @@
}
},
"settingsPropertiesTypography": {
"type": "object",
"properties": {
"typography": {
"description": "Settings related to typography.",
Expand Down Expand Up @@ -374,18 +380,25 @@
},
"fluid": {
"description": "Specifics the minimum and maximum font size value of a fluid font size. Set to `false` to bypass fluid calculations and use the static `size` value.",
"type": [ "object", "boolean" ],
"properties": {
"min": {
"description": "A min font size for fluid font size calculations in px, rem or em.",
"type": "string"
"oneOf": [
{
"type": "object",
"properties": {
"min": {
"description": "A min font size for fluid font size calculations in px, rem or em.",
"type": "string"
},
"max": {
"description": "A max font size for fluid font size calculations in px, rem or em.",
"type": "string"
}
},
"additionalProperties": false
},
"max": {
"description": "A max font size for fluid font size calculations in px, rem or em.",
"type": "string"
{
"type": "boolean"
}
},
"additionalProperties": false
]
}
},
"additionalProperties": false
Expand Down Expand Up @@ -427,7 +440,6 @@
},
"fontWeight": {
"description": "List of available font weights, separated by a space.",
"type": "string",
"default": "400",
"oneOf": [
{
Expand Down Expand Up @@ -515,6 +527,7 @@
}
},
"settingsPropertiesCustom": {
"type": "object",
"properties": {
"custom": {
"description": "Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name.",
Expand Down Expand Up @@ -557,6 +570,7 @@
"type": "object",
"properties": {
"core/archives": {
"type": "object",
"description": "Archive block. Display a monthly archive of your posts. This block has no block-level settings",
"additionalProperties": false
},
Expand All @@ -570,11 +584,13 @@
"$ref": "#/definitions/settingsPropertiesComplete"
},
"core/button": {
"type": "object",
"allOf": [
{
"$ref": "#/definitions/settingsPropertiesAppearanceTools"
},
{
"type": "object",
"properties": {
"border": {
"description": "Settings related to borders.\nGutenberg plugin required.",
Expand Down Expand Up @@ -857,6 +873,7 @@
}
},
"stylesProperties": {
"type": "object",
"properties": {
"border": {
"description": "Border styles.",
Expand Down Expand Up @@ -904,60 +921,76 @@
"type": "string"
},
"top": {
"color": {
"description": "Sets the `border-top-color` CSS property.",
"type": "string"
},
"style": {
"description": "Sets the `border-top-style` CSS property.",
"type": "string"
"type": "object",
"properties": {
"color": {
"description": "Sets the `border-top-color` CSS property.",
"type": "string"
},
"style": {
"description": "Sets the `border-top-style` CSS property.",
"type": "string"
},
"width": {
"description": "Sets the `border-top-width` CSS property.",
"type": "string"
}
},
"width": {
"description": "Sets the `border-top-width` CSS property.",
"type": "string"
}
"additionalProperties": false
},
"right": {
"color": {
"description": "Sets the `border-right-color` CSS property.",
"type": "string"
},
"style": {
"description": "Sets the `border-right-style` CSS property.",
"type": "string"
"type": "object",
"properties": {
"color": {
"description": "Sets the `border-right-color` CSS property.",
"type": "string"
},
"style": {
"description": "Sets the `border-right-style` CSS property.",
"type": "string"
},
"width": {
"description": "Sets the `border-right-width` CSS property.",
"type": "string"
}
},
"width": {
"description": "Sets the `border-right-width` CSS property.",
"type": "string"
}
"additionalProperties": false
},
"bottom": {
"color": {
"description": "Sets the `border-bottom-color` CSS property.",
"type": "string"
},
"style": {
"description": "Sets the `border-bottom-style` CSS property.",
"type": "string"
"type": "object",
"properties": {
"color": {
"description": "Sets the `border-bottom-color` CSS property.",
"type": "string"
},
"style": {
"description": "Sets the `border-bottom-style` CSS property.",
"type": "string"
},
"width": {
"description": "Sets the `border-bottom-width` CSS property.",
"type": "string"
}
},
"width": {
"description": "Sets the `border-bottom-width` CSS property.",
"type": "string"
}
"additionalProperties": false
},
"left": {
"color": {
"description": "Sets the `border-left-color` CSS property.",
"type": "string"
},
"style": {
"description": "Sets the `border-left-style` CSS property.",
"type": "string"
"type": "object",
"properties": {
"color": {
"description": "Sets the `border-left-color` CSS property.",
"type": "string"
},
"style": {
"description": "Sets the `border-left-style` CSS property.",
"type": "string"
},
"width": {
"description": "Sets the `border-left-width` CSS property.",
"type": "string"
}
},
"width": {
"description": "Sets the `border-left-width` CSS property.",
"type": "string"
}
"additionalProperties": false
}
},
"additionalProperties": false
Expand Down
23 changes: 23 additions & 0 deletions test/integration/theme-schema.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* External dependencies
*/
import Ajv from 'ajv-draft-04';

/**
* Internal dependencies
*/
import themeSchema from '../../schemas/json/theme.json';

describe( 'theme.json schema', () => {
const ajv = new Ajv( {
// Used for matching unknown blocks without repeating core blocks names
// with patternProperties in settings.blocks and settings.styles
allowMatchingProperties: true,
} );

it( 'compiles in strict mode', async () => {
const result = ajv.compile( themeSchema );
Copy link
Contributor Author

@alecgeatches alecgeatches Sep 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See point 3 from this discussion about why compile() is being used here instead of validate():

  1. The validation code no longer uses an object to validate the schema. This ended up being trickier than expected. Your suggested code change using validate ran successfully, but did not report and strict errors on theme.json's schema. For example, I tried adding invalid properties like "test": "abc" to the schema which should fail Ajv's strictSchema, but no errors were reported. The only way I could get the meta-schema to be validated was by validating an actual data structure or using .compile():

    const result = ajv.compile( themeSchema );

    It's unclear from Ajv's documentation why .validate('.../draft-04#', $themeSchema) or .validate($themeSchema) weren't reporting errors. The best I could find was the documentation for compile() which mentions the meta-schema:

    The schema passed to this method will be validated against meta-schema unless validateSchema option is false. If schema is invalid, an error will be thrown. See options.

    It seems like the meta-schema is only validated during compilation, so the code has been changed to use compile() instead.

Copy link
Contributor

@ajlende ajlende Sep 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alecgeatches I found a couple notes about this in the Ajv docs and issues.

ajv.validateSchema(schema: object): boolean

Validates schema. This method should be used to validate schemas rather than validate due to the inconsistency of uri format in JSON Schema standard.

validateSchema only checks “syntax” (it validated schema as JSON against metaschema), it may still be semantically incorrect.

Looks like I was wrong about using validate for validating against a meta schema in the first place. And it's intentional that strict mode only applies to compile, so that's why we should be using it instead of validateSchema to validate our schema. 🙃


expect( result.errors ).toBe( null );
} );
} );