Skip to content

Commit

Permalink
chore: add unit test to ensure that all types in the README are in th…
Browse files Browse the repository at this point in the history
…e schema
  • Loading branch information
nytamin committed Oct 20, 2023
1 parent e7ea0c5 commit 2b62572
Show file tree
Hide file tree
Showing 14 changed files with 131 additions and 24 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.vscode/settings.json
lib/unit-tests/cache/
16 changes: 8 additions & 8 deletions lib/unit-tests/__tests__/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('Schema - Basic types', () => {
30 * 1000
)
test('Basic', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

// Basic
expect(
Expand Down Expand Up @@ -102,7 +102,7 @@ describe('Schema - Basic types', () => {
).toBe(null)
})
test('Bad property', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand All @@ -121,7 +121,7 @@ describe('Schema - Basic types', () => {
// "object"

test('Property: boolean', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand All @@ -147,7 +147,7 @@ describe('Schema - Basic types', () => {
).toMatch(/not.*boolean/)
})
test('Property: string', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down Expand Up @@ -177,7 +177,7 @@ describe('Schema - Basic types', () => {
// "pattern": Regular Expression,
})
test('Property: number', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down Expand Up @@ -209,7 +209,7 @@ describe('Schema - Basic types', () => {
// "exclusiveMinimum": number,
})
test('Property: integer', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down Expand Up @@ -241,7 +241,7 @@ describe('Schema - Basic types', () => {
// "exclusiveMinimum": number,
})
test('Property: array', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down Expand Up @@ -320,7 +320,7 @@ describe('Schema - Basic types', () => {
// "minContains": number
})
test('Property: object', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
99 changes: 99 additions & 0 deletions lib/unit-tests/__tests__/gddTypes/_ensure-all-gddTypes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { promises as fs } from 'fs'
import { setupValidator } from '../lib/validator'

test('Ensure that all GDDTypes in README exist and passes validation', async () => {
let validatedTypeCount = 0
let validatedExampleCount = 0

// Gather all GDDTypes from README:
const readme = await fs.readFile('../../README.md', 'utf8')

const iStart = readme.indexOf('## GDD Types')
if (iStart === -1) throw new Error('Could not find "## GDD Types" in README.md')
const iEnd = readme.indexOf('\n## ', iStart + 1)
if (iEnd === -1) throw new Error('Could not find next heading after "## GDD Types" in README.md')

/** String containing the GDD Types */
const readmeGDDTypes = readme.slice(iStart + 13, iEnd)

/** Array of headers */
const mentionedGDDTypes = readmeGDDTypes.match(/\n### (.*)\n/g)
if (!mentionedGDDTypes) throw new Error('Could not find any GDDTypes in README.md')

const definitions: { name: string; index: number; ignore: boolean }[] = []
for (const mentionedGDDType of mentionedGDDTypes) {
const m = mentionedGDDType.match(/\n### (.*)\n/)
if (!m) throw new Error(`Error regexing "${mentionedGDDType}"`)

const name = m[1]
let ignore = false

if (name.includes('Private GDD Types')) ignore = true

const iType = readmeGDDTypes.indexOf(mentionedGDDType)
if (iType === -1) throw new Error(`Error finding "${mentionedGDDType}"`)

definitions.push({ name, index: iType, ignore })
}

const { validate: validateSchema, cache } = await setupValidator()
if (!cache) throw new Error('cache object is null')
const cacheStr = JSON.stringify(cache)

for (let i = 0; i < definitions.length; i++) {
const definition = definitions[i]

if (definition.ignore) continue

const iType = definition.index
const iNext = definitions[i + 1]?.index || readmeGDDTypes.length

const typeStr = readmeGDDTypes.slice(iType, iNext)

// Gather schema examples:
const typeExamples = typeStr.match(/```(typescript|json)([\w\W]*?)```/gm)
if (!typeExamples) throw new Error(`Could not find any examples for "${definition.name}"`)

let hasExamples = false
for (const typeExample of typeExamples) {
let str = typeExample.replace(/^.+?\n/, '') // remove first line "```typescript"
str = str.replace(/```$/, '') // remove last line "```"
str = str.replace(/[Optional] \/\/.*/g, '') // Remove inline comments
str = str.replace(/\/\/.*/g, '') // Remove inline comments

const gddTypeNameMatch = str.match(/"gddType": "(.*)"/)
if (!gddTypeNameMatch) throw new Error(`Could not find "gddType" in "${str}"`)
const gddTypeName = gddTypeNameMatch[1]

// Ensure that gddTypeName exists in schema:
if (!cacheStr.includes(`{"gddType":{"const":"${gddTypeName}"}}`)) {
throw new Error(`Could not find "${gddTypeName}" in schema`)
}

try {
const json = JSON.parse(str)

expect(
validateSchema({
type: 'object',
properties: {
f0: json,
},
})
).toBe(null)
validatedExampleCount++
hasExamples = true
} catch (e) {
if (e instanceof Error) {
e.message = `Error parsing example for "${str}": ${e.message}`
}
console.log(typeStr)
throw e
}
}
if (hasExamples) validatedTypeCount++
}

expect(validatedExampleCount).toBeGreaterThanOrEqual(10)
expect(validatedTypeCount).toBeGreaterThanOrEqual(8)
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from '../lib/validator'

test('gddType: non-standard', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
2 changes: 1 addition & 1 deletion lib/unit-tests/__tests__/gddTypes/color-rrggbb.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from '../lib/validator'

test('gddType: color-rrggbb', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
2 changes: 1 addition & 1 deletion lib/unit-tests/__tests__/gddTypes/duration-ms.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from '../lib/validator'

test('gddType: duration-ms', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
2 changes: 1 addition & 1 deletion lib/unit-tests/__tests__/gddTypes/file-path.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from '../lib/validator'

test('gddType: file-path', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
2 changes: 1 addition & 1 deletion lib/unit-tests/__tests__/gddTypes/image-path.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from '../lib/validator'

test('gddType: image-file-path', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
2 changes: 1 addition & 1 deletion lib/unit-tests/__tests__/gddTypes/multi-line.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from '../lib/validator'

test('gddType: multi-line', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
2 changes: 1 addition & 1 deletion lib/unit-tests/__tests__/gddTypes/percentage.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from '../lib/validator'

test('gddType: percentage', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
2 changes: 1 addition & 1 deletion lib/unit-tests/__tests__/gddTypes/select.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from '../lib/validator'

test('gddType: select', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
2 changes: 1 addition & 1 deletion lib/unit-tests/__tests__/gddTypes/single-line.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from '../lib/validator'

test('gddType: single-line', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

expect(
validateSchema({
Expand Down
17 changes: 12 additions & 5 deletions lib/unit-tests/__tests__/lib/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import * as path from 'path'
import * as fs from 'fs'
import fetch from 'node-fetch'
/* eslint-disable node/no-unpublished-import */
import { SchemaValidator, setupSchemaValidator } from '../../../javascript-library'

export async function setupValidator(): Promise<SchemaValidator> {
const cachePath = path.resolve('./__cache.json')
import { SchemaValidator, ValidatorCache, setupSchemaValidator } from '../../../javascript-library'

export async function setupValidator(): Promise<{ validate: SchemaValidator; cache: ValidatorCache | null }> {
const cachePath = getCachePath()
const { validate, cache } = await setupSchemaValidator({
getCache: async () => {
if (await fileExists(cachePath)) {
Expand Down Expand Up @@ -39,7 +38,15 @@ export async function setupValidator(): Promise<SchemaValidator> {
await fs.promises.writeFile(cachePath, JSON.stringify(cache), 'utf-8')
}

return validate
return { validate, cache }
}

export async function clearValidatorCache(): Promise<void> {
await fs.promises.unlink(getCachePath())
}

function getCachePath(): string {
return path.resolve('./__cache.json')
}

async function fileExists(filePath: string): Promise<boolean> {
Expand Down
4 changes: 2 additions & 2 deletions lib/unit-tests/__tests__/playout-options.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupValidator } from './lib/validator'

test('gddPlayoutOptions.client', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

// Minimal object:
expect(
Expand Down Expand Up @@ -110,7 +110,7 @@ test('gddPlayoutOptions.client', async () => {
).toMatch(/is not.*json/)
})
test('gddPlayoutOptions.playout', async () => {
const validateSchema = await setupValidator()
const validateSchema = (await setupValidator()).validate

// Minimal object:
expect(
Expand Down

0 comments on commit 2b62572

Please sign in to comment.