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

[lib][xl]: Add tests for computed fields and document types, Fix duplicate tags issue #108

Merged
merged 12 commits into from
Jan 10, 2024
10 changes: 10 additions & 0 deletions .changeset/dirty-spies-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
"mddb": patch
---

- Add tests for document types
- Fix throwing an error when the document type is incorrect
- Fix linting error
- Fix a strange duplicated body tags issue
- Fix the library incorrectly stringifying strings
- Add tests for computed fields
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 8 additions & 5 deletions src/lib/indexFolder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@ export function indexFolder(
const error: ZodError = (result as any).error;

error.errors.forEach((err: any) => {
const errorMessage = `Error: In ${
fileObject.file_path
} for the ${documentType} schema. \n In "${err.path.join(
","
)}" field: ${err.message}`;
const errorMessage = `Error: In ${fileObject.file_path
} for the ${documentType} schema. \n In "${err.path.join(
","
)}" field: ${err.message}`;
console.error(errorMessage);
});

throw new Error(
"Validation Failed: Unable to validate files against the specified scheme. Ensure that the file formats and content adhere to the specified scheme."
);
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/lib/parseFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function parseFile(source: string, options?: ParsingOptions) {

// Links
const links = extractWikiLinks(ast, options);
metadata.tags = Array.from(new Set(metadata.tags));

const tasks = extractTasks(ast);
metadata.tasks = tasks;
Expand Down Expand Up @@ -78,7 +79,7 @@ export const extractTagsFromBody = (ast: Root) => {

function extractTags(text: string) {
let tags: any = [];
const textTags = text.match(/(?:^|\s+|\n+|\r+)#([a-zA-Z0-9_\-\/\p{L}]+)/gu);
const textTags = text.match(/(?:^|\s+|\n+|\r+)#([a-zA-Z0-9_\-/\p{L}]+)/gu);
if (textTags) {
tags = tags.concat(
textTags
Expand All @@ -94,9 +95,9 @@ function isValidTag(tag: string) {
// Check if the tag follows the specified rules
return (
tag.length > 1 &&
/[a-zA-Z_\-\/\p{L}]+/gu.test(tag) && // At least one non-numerical character
/[a-zA-Z_\-/\p{L}]+/gu.test(tag) && // At least one non-numerical character
!/\s/.test(tag) && // No blank spaces
/[a-zA-Z0-9_\-\/\p{L}]+/gu.test(tag) // Valid characters: alphabetical letters, numbers, underscore, hyphen, forward slash, and any letter in any language
/[a-zA-Z0-9_\-/\p{L}]+/gu.test(tag) // Valid characters: alphabetical letters, numbers, underscore, hyphen, forward slash, and any letter in any language
);
}

Expand Down
3 changes: 2 additions & 1 deletion src/lib/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ class MddbFile {
// If the value is undefined, default it to null
if (value !== undefined) {
const shouldStringify =
key === "metadata" || !MddbFile.defaultProperties.includes(key);
(key === "metadata" || !MddbFile.defaultProperties.includes(key)) &&
typeof value === "object";
// Stringify all user-defined fields and metadata
serializedFile[key] = shouldStringify ? JSON.stringify(value) : value;
} else {
Expand Down
286 changes: 286 additions & 0 deletions src/tests/computedField.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
import { FileInfo, processFile } from "../lib/process";
import Path from "path";
import { Root, Content } from "mdast";

type MyContent = Content & {
children?: { value: string }[];
};

describe("Can parse a file and get file info", () => {
const pathToContentFixture = "__mocks__/content";
const filePath = "index.mdx";
const fullPath = Path.join(pathToContentFixture, filePath);
test("Can get some values from AST and Add it to fileInfo", async () => {
const fileInfo = processFile(
pathToContentFixture,
fullPath,
(filePath) => filePath,
[],
[
(fileInfo: FileInfo, ast: Root) => {
const headingNode = ast.children.filter((child) => {
return child.type === "heading" && child.depth === 1;
}) as MyContent[];
fileInfo.title = headingNode[0]?.children[0]?.value;
},
]
);

expect(fileInfo.file_path).toBe(fullPath);
expect(fileInfo.url_path).toBe("index.mdx");
expect(fileInfo.title).toBe("Welcome");
expect(fileInfo.extension).toBe("mdx");

expect(fileInfo.tags).toEqual([
"tag1",
"tag2",
"tag3",
"日本語タグ",
"标签名",
"метка",
"태그이름",
"tag_فارسی",
"Tag_avec_éèç-_öäüßñ",
]);

expect(fileInfo.metadata).toEqual({
title: "Homepage",
tags: [
"tag1",
"tag2",
"tag3",
"日本語タグ",
"标签名",
"метка",
"태그이름",
"tag_فارسی",
"Tag_avec_éèç-_öäüßñ",
],
tasks: [
{
checked: false,
description: "uncompleted task 2",
},
{
checked: true,
description: "completed task 1",
},
{
checked: true,
description: "completed task 2",
},
],
});
expect(fileInfo.links).toEqual([
{
embed: false,
from: "index.mdx",
internal: true,
text: "link",
to: "blog0.mdx",
toRaw: "blog0.mdx",
},
]);
});
test("Can add array,object,null,undefined values throw the computed fields", () => {
const fileInfo = processFile(
pathToContentFixture,
fullPath,
(filePath) => filePath,
[],
[
// add homepage string to file info
(fileInfo: FileInfo, ast: Root) => {
fileInfo.public = {
title: "Title",
pageSize: 34,
isLocked: false,
};
},
// add pageNumber as number to fileInfo
(fileInfo: FileInfo, ast: Root) => {
fileInfo.Authors = ["Abdelrhiim", "Mohammed", "John"];
},
// add isLocked as boolean to fileInfo
(fileInfo: FileInfo, ast: Root) => {
fileInfo.matrix = null;
},
// add isLocked as boolean to fileInfo
(fileInfo: FileInfo, ast: Root) => {
fileInfo.building = undefined;
},
]
);
expect(fileInfo.file_path).toBe(fullPath);
expect(fileInfo.url_path).toBe("index.mdx");
expect(fileInfo.public).toEqual({
title: "Title",
pageSize: 34,
isLocked: false,
});
expect(fileInfo.Authors).toEqual(["Abdelrhiim", "Mohammed", "John"]);
expect(fileInfo.matrix).toBeNull();
expect(fileInfo.building).toBeUndefined();
});
test("Can add string,number,and boolean values throw the computed fields", () => {
const fileInfo = processFile(
pathToContentFixture,
fullPath,
(filePath) => filePath,
[],
[
// add homepage string to file info
(fileInfo: FileInfo, ast: Root) => {
fileInfo.homePage = "indexFile";
},
// add pageNumber as number to fileInfo
(fileInfo: FileInfo, ast: Root) => {
fileInfo.pageNumber = 23;
},
// add isLocked as boolean to fileInfo
(fileInfo: FileInfo, ast: Root) => {
fileInfo.isLocked = false;
},
]
);
expect(fileInfo.file_path).toBe(fullPath);
expect(fileInfo.url_path).toBe("index.mdx");
expect(fileInfo.homePage).toBe("indexFile");
expect(fileInfo.pageNumber).toBe(23);
expect(fileInfo.isLocked).toBe(false);
});
test("Can add metadata field threw the computed fields", async () => {
const fileInfo = processFile(
pathToContentFixture,
fullPath,
(filePath) => filePath,
[],
[
(fileInfo: FileInfo, ast: Root) => {
fileInfo.metadata.AuthorName = "John Smith";
},
]
);

expect(fileInfo.file_path).toBe(fullPath);
expect(fileInfo.url_path).toBe("index.mdx");
expect(fileInfo.extension).toBe("mdx");

expect(fileInfo.tags).toEqual([
"tag1",
"tag2",
"tag3",
"日本語タグ",
"标签名",
"метка",
"태그이름",
"tag_فارسی",
"Tag_avec_éèç-_öäüßñ",
]);
expect(fileInfo.metadata).toEqual({
AuthorName: "John Smith",
title: "Homepage",
tags: [
"tag1",
"tag2",
"tag3",
"日本語タグ",
"标签名",
"метка",
"태그이름",
"tag_فارسی",
"Tag_avec_éèç-_öäüßñ",
],
tasks: [
{
checked: false,
description: "uncompleted task 2",
},
{
checked: true,
description: "completed task 1",
},
{
checked: true,
description: "completed task 2",
},
],
});
expect(fileInfo.links).toEqual([
{
embed: false,
from: "index.mdx",
internal: true,
text: "link",
to: "blog0.mdx",
toRaw: "blog0.mdx",
},
]);
});
test("Can Edit and Delete Metadata Field threw the computed fields", () => {
const fileInfo = processFile(
pathToContentFixture,
fullPath,
(filePath) => filePath,
[],
[
(fileInfo: FileInfo, ast: Root) => {
fileInfo.metadata.title = "Second Page";
delete fileInfo.metadata.AuthorName;
},
]
);
expect(fileInfo.file_path).toBe(fullPath);
expect(fileInfo.url_path).toBe("index.mdx");
expect(fileInfo.extension).toBe("mdx");
expect(fileInfo.tags).toEqual([
"tag1",
"tag2",
"tag3",
"日本語タグ",
"标签名",
"метка",
"태그이름",
"tag_فارسی",
"Tag_avec_éèç-_öäüßñ",
]);
expect(fileInfo.metadata).toEqual({
title: "Second Page",
tags: [
"tag1",
"tag2",
"tag3",
"日本語タグ",
"标签名",
"метка",
"태그이름",
"tag_فارسی",
"Tag_avec_éèç-_öäüßñ",
],
tasks: [
{
checked: false,
description: "uncompleted task 2",
},
{
checked: true,
description: "completed task 1",
},
{
checked: true,
description: "completed task 2",
},
],
});
expect(fileInfo.links).toEqual([
{
embed: false,
from: "index.mdx",
internal: true,
text: "link",
to: "blog0.mdx",
toRaw: "blog0.mdx",
},
]);
});
});
Loading
Loading