use ajv for learning tracks schema tests (#35443)

This commit is contained in:
Robert Sese 2023-03-10 11:16:29 -06:00 коммит произвёл GitHub
Родитель 49a2bc6751
Коммит c3d82a65e5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 58 добавлений и 24 удалений

Просмотреть файл

@ -17,8 +17,16 @@ export const formatAjvErrors = (errors = []) => {
const split = errorObj.instancePath.split('/')
split.shift()
// handle additional properties error specifically since we can call out
// which property shouldn't be there
let additionalProperties = ''
if (errorObj.keyword === 'additionalProperties') {
additionalProperties = `: additional property is '${errorObj.params.additionalProperty}'`
}
if (split.length === 0) {
return `at '/' (top-level): ${errorObj.message}`
return `at '/' (top-level): ${errorObj.message}${additionalProperties}`
}
const schemaErrorPath = split
@ -31,14 +39,6 @@ export const formatAjvErrors = (errors = []) => {
})
.join(' > ')
// handle additional properties error specifically since we can call out
// which property shouldn't be there
let additionalProperties = ''
if (errorObj.keyword === 'additionalProperties') {
additionalProperties = `: additional property is '${errorObj.params.additionalProperty}'`
}
return `at '${schemaErrorPath}': ${errorObj.message}${additionalProperties}`
})
.join('\n ')

Просмотреть файл

@ -3,6 +3,28 @@ import { schema } from '../../../lib/frontmatter.js'
// Some learning tracks have `versions` blocks that match `versions` frontmatter,
// so we can import that part of the FM schema.
const versionsProps = Object.assign({}, schema.properties.versions)
// Tweak the imported versions schema so it works with AJV.
// *** TODO: We can drop the following once the frontmatter.js schema has been updated to work with AJV. ***
const properties = {}
Object.keys(versionsProps.properties).forEach((key) => {
const value = Object.assign({}, versionsProps.properties[key])
// AJV supports errorMessage, not message.
value.errorMessage = value.message
delete value.message
// AJV doesn't support conform, so we'll add semver validation in the lint-files test.
if (value.conform) {
value.format = 'semver'
delete value.conform
}
properties[key] = value
})
versionsProps.properties = properties
// *** End TODO ***
// `versions` are not required in learning tracks the way they are in FM.
delete versionsProps.required
@ -12,20 +34,18 @@ export default {
patternProperties: {
'^[a-zA-Z-_]+$': {
type: 'object',
required: ['title', 'description', 'guides'],
additionalProperties: false,
properties: {
title: {
type: 'string',
required: true,
},
description: {
type: 'string',
required: true,
},
guides: {
type: 'array',
items: { type: 'string' },
required: true,
},
featured_track: {
type: ['boolean', 'string'],

Просмотреть файл

@ -4,12 +4,13 @@ import slash from 'slash'
import walk from 'walk-sync'
import { zip } from 'lodash-es'
import yaml from 'js-yaml'
import revalidator from 'revalidator'
import Ajv from 'ajv'
import addErrors from 'ajv-errors'
import addFormats from 'ajv-formats'
import { fromMarkdown } from 'mdast-util-from-markdown'
import { visit } from 'unist-util-visit'
import fs from 'fs/promises'
import semver from 'semver'
import { frontmatter, deprecatedProperties } from '../../lib/frontmatter.js'
import languages from '../../lib/languages.js'
import { tags } from '../../lib/liquid-tags/extended-markdown.js'
@ -349,9 +350,16 @@ if (
}
// ajv for schema validation tests
const ajv = new Ajv({ allErrors: true })
const ajv = new Ajv({ allErrors: true, allowUnionTypes: true })
addFormats(ajv)
addErrors(ajv)
// *** TODO: We can drop this override once the frontmatter schema has been updated to work with AJV. ***
ajv.addFormat('semver', {
validate: (x) => semver.validRange(x),
})
// *** End TODO ***
const ghesValidate = ajv.compile(releaseNotesSchema)
const learningTracksValidate = ajv.compile(learningTracksSchema)
describe('lint markdown content', () => {
if (mdToLint.length < 1) return
@ -945,11 +953,14 @@ describe('lint GHAE release notes', () => {
})
it('matches the schema', () => {
const { errors } = revalidator.validate(dictionary, releaseNotesSchema)
const errorMessage = errors
.map((error) => `- [${error.property}]: ${error.actual}, ${error.message}`)
.join('\n')
expect(errors.length, errorMessage).toBe(0)
const valid = ghesValidate(dictionary)
let errors
if (!valid) {
errors = formatAjvErrors(ghesValidate.errors)
}
expect(valid, errors).toBe(true)
})
it('does not have more than one yaml file with currentWeek set to true', () => {
@ -1009,11 +1020,14 @@ describe('lint learning tracks', () => {
})
it('matches the schema', () => {
const { errors } = revalidator.validate(dictionary, learningTracksSchema)
const errorMessage = errors
.map((error) => `- [${error.property}]: ${error.actual}, ${error.message}`)
.join('\n')
expect(errors.length, errorMessage).toBe(0)
const valid = learningTracksValidate(dictionary)
let errors
if (!valid) {
errors = formatAjvErrors(learningTracksValidate.errors)
}
expect(valid, errors).toBe(true)
})
it('has one and only one featured track per supported version', async () => {