Skip to content

Commit 088a18a

Browse files
committed
add test cases
1 parent 3e066b1 commit 088a18a

File tree

4 files changed

+189
-2
lines changed

4 files changed

+189
-2
lines changed

__tests__/contentFolder.test.ts

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { expectTypeOf, test, assert, assertType } from "vitest";
2+
import {
3+
contentFolderName,
4+
instructionsFileName,
5+
} from "@/lib/contentVariables";
6+
import * as fs from "fs";
7+
import * as path from "path";
8+
import { contentManager } from "@/lib/contentManager";
9+
import { getCodeFileExports, parseLessonFolder } from "@/lib/server-functions";
10+
import { hyperjumpValidate } from "@/lib/validators";
11+
12+
// test the structure of the content folder
13+
// test if each of the code.ts files have valid exports
14+
15+
const metadataSchema = {
16+
type: "object",
17+
properties: {
18+
title: { type: "string" },
19+
description: { type: "string" },
20+
keywords: { type: "string" },
21+
},
22+
required: ["title", "description", "keywords"],
23+
};
24+
25+
const codeFileSchema = {
26+
type: "object",
27+
properties: {
28+
code: { type: "object" },
29+
testCases: {
30+
type: "array",
31+
items: {
32+
type: "object",
33+
properties: {
34+
input: { type: "object" },
35+
expected: { type: "boolean" },
36+
},
37+
required: ["input", "expected"],
38+
},
39+
},
40+
solution: { type: "object" },
41+
},
42+
required: ["code", "testCases", "solution"],
43+
};
44+
45+
const folderNameRegEx = /^[0-9]{2}-[^\s]*$/;
46+
47+
test("content folder structure", async () => {
48+
const contentFolder = path.join(process.cwd(), contentFolderName);
49+
const folderFiles = fs.readdirSync(contentFolder);
50+
51+
if (!folderFiles.includes("outline.json")) {
52+
assert.fail("Content folder does not contain an outline.json file");
53+
}
54+
55+
for (const file of folderFiles) {
56+
if (file === "outline.json") continue;
57+
58+
const regExResult = folderNameRegEx.exec(file);
59+
if (regExResult === null) {
60+
assert.fail(
61+
`Folder name ${file} does not match the expected pattern: ${folderNameRegEx.source}`
62+
);
63+
}
64+
65+
const chapterFolderFiles = fs.readdirSync(path.join(contentFolder, file));
66+
if (!chapterFolderFiles.includes("index.mdx")) {
67+
assert.fail(`Chapter ${file} does not contain an index.mdx file`);
68+
}
69+
70+
for (const chapterFile of chapterFolderFiles) {
71+
if (chapterFile === "index.mdx") continue;
72+
73+
if (!folderNameRegEx.exec(chapterFile)) {
74+
assert.fail(
75+
`Lesson folder name ${chapterFile} does not match the expected pattern: ${folderNameRegEx.source}`
76+
);
77+
}
78+
79+
const lessonFolderFiles = fs.readdirSync(
80+
path.join(contentFolder, file, chapterFile)
81+
);
82+
83+
if (!lessonFolderFiles.includes(instructionsFileName)) {
84+
assert.fail(
85+
`Lesson ${file}/${chapterFile} does not contain an ${instructionsFileName} file`
86+
);
87+
}
88+
if (!lessonFolderFiles.includes(contentManager.codeFileName)) {
89+
assert.fail(
90+
`Lesson ${file}/${chapterFile} does not contain a ${contentManager.codeFileName} file`
91+
);
92+
}
93+
94+
const { codeFile, metadata } = parseLessonFolder(
95+
path.join(contentFolder, file, chapterFile, instructionsFileName),
96+
path.join(contentFolder, file, chapterFile, contentManager.codeFileName)
97+
);
98+
99+
const metadataValidation = await hyperjumpValidate(
100+
metadata,
101+
metadataSchema
102+
);
103+
104+
const codeFileValidation = await hyperjumpValidate(
105+
codeFile,
106+
codeFileSchema
107+
);
108+
109+
if (!metadataValidation.valid) {
110+
console.log(metadata);
111+
assert.fail(
112+
`Metadata for ${file}/${chapterFile} is invalid: \n ${JSON.stringify(
113+
metadataValidation.errors![0],
114+
null,
115+
2
116+
)}`
117+
);
118+
}
119+
120+
if (!codeFileValidation.valid) {
121+
assert.fail(
122+
`Code file for ${file}/${chapterFile} is invalid: \n ${JSON.stringify(
123+
codeFileValidation.errors![0],
124+
null,
125+
2
126+
)}`
127+
);
128+
}
129+
}
130+
}
131+
});

__tests__/outlineFile.test.ts

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { expect, test } from "vitest";
2+
import { hyperjumpValidate } from "@/lib/validators";
3+
import outlineFile from "@/content/outline.json";
4+
5+
const outlineSchema = {
6+
$schema: "https://json-schema.org/draft/2020-12/schema",
7+
type: "array",
8+
minItems: 1,
9+
items: {
10+
type: "object",
11+
properties: {
12+
title: {
13+
type: "string",
14+
},
15+
folderName: {
16+
type: "string",
17+
},
18+
steps: {
19+
type: "array",
20+
minItems: 1,
21+
items: {
22+
type: "object",
23+
properties: {
24+
title: {
25+
type: "string",
26+
},
27+
fileName: {
28+
type: "string",
29+
},
30+
fullPath: {
31+
type: "string",
32+
},
33+
},
34+
required: ["title", "fileName", "fullPath"],
35+
},
36+
},
37+
},
38+
required: ["title", "folderName", "steps"],
39+
},
40+
};
41+
42+
test("outlineFile", async () => {
43+
const { valid, errors } = await hyperjumpValidate(outlineFile, outlineSchema);
44+
expect(valid).toBe(true);
45+
expect(errors).toBe(undefined);
46+
});

tsconfig.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"compilerOptions": {
3+
"types": ["vitest/globals"],
34
"lib": ["dom", "dom.iterable", "esnext"],
45
"allowJs": true,
56
"skipLibCheck": true,
@@ -28,7 +29,8 @@
2829
"**/*.ts",
2930
"**/*.tsx",
3031
".next/types/**/*.ts",
31-
"scripts/generateOutline.ts"
32+
"scripts/generateOutline.ts",
33+
"__tests__/*.test.ts"
3234
],
3335
"exclude": ["node_modules"]
3436
}

vitest.config.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
import { defineConfig } from "vitest/config";
22
import react from "@vitejs/plugin-react";
3-
3+
import path from "path";
44
export default defineConfig({
55
plugins: [react()],
66
test: {
77
environment: "jsdom",
8+
typecheck: {
9+
enabled: true,
10+
},
11+
},
12+
resolve: {
13+
alias: {
14+
"@": path.resolve(__dirname, "./"),
15+
},
816
},
917
});

0 commit comments

Comments
 (0)