зеркало из https://github.com/github/docs.git
use ajv for learning tracks schema tests (#35443)
This commit is contained in:
Родитель
49a2bc6751
Коммит
c3d82a65e5
|
@ -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 () => {
|
||||
|
|
Загрузка…
Ссылка в новой задаче