test: added obsidian test
This commit is contained in:
@@ -0,0 +1,162 @@
|
|||||||
|
import test from "node:test";
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
|
const pluginPath = path.resolve("/home/venus/Documents/Notes/.obsidian/plugins/blog-publisher/main.js");
|
||||||
|
|
||||||
|
// Pure helper function to be tested and exported/used by plugin
|
||||||
|
export function insertOrUpdateFrontmatterProperty(content, key, value) {
|
||||||
|
if (typeof content !== "string") return "";
|
||||||
|
|
||||||
|
const fmRegex = /^---\r?\n([\s\S]*?)\r?\n---/;
|
||||||
|
const match = content.match(fmRegex);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
let fmBlock = match[1];
|
||||||
|
const keyRegex = new RegExp(`^${key}:.*$`, "m");
|
||||||
|
|
||||||
|
if (value === null || value === undefined) {
|
||||||
|
// Remove property if value is null
|
||||||
|
fmBlock = fmBlock.replace(new RegExp(`^${key}:.*\\r?\\n?`, "m"), "");
|
||||||
|
} else if (keyRegex.test(fmBlock)) {
|
||||||
|
// Replace existing property
|
||||||
|
fmBlock = fmBlock.replace(keyRegex, `${key}: "${value}"`);
|
||||||
|
} else {
|
||||||
|
// Append property to frontmatter
|
||||||
|
fmBlock = `${fmBlock}\n${key}: "${value}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return content.replace(fmRegex, `---\n${fmBlock.trim()}\n---`);
|
||||||
|
} else if (value) {
|
||||||
|
return `---\n${key}: "${value}"\n---\n\n${content}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function computePublicUrl(serverUrl, postPath) {
|
||||||
|
const base = (serverUrl || "").replace(/\/+$/, "");
|
||||||
|
const p = (postPath || "").startsWith("/") ? postPath : `/${postPath || ""}`;
|
||||||
|
return `${base}${p}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
test("Obsidian Plugin: computePublicUrl normalizes slashes correctly", () => {
|
||||||
|
assert.equal(
|
||||||
|
computePublicUrl("https://riverrooks.dev", "/posts/test-note/"),
|
||||||
|
"https://riverrooks.dev/posts/test-note/"
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
computePublicUrl("https://riverrooks.dev/", "/posts/test-note/"),
|
||||||
|
"https://riverrooks.dev/posts/test-note/"
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
computePublicUrl("https://riverrooks.dev///", "posts/test-note/"),
|
||||||
|
"https://riverrooks.dev/posts/test-note/"
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
computePublicUrl("http://localhost:8080", "/posts/test-note/"),
|
||||||
|
"http://localhost:8080/posts/test-note/"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Obsidian Plugin: insertOrUpdateFrontmatterProperty adds public-url when missing", () => {
|
||||||
|
const original = `---
|
||||||
|
title: "Sample Note"
|
||||||
|
date: 2026-09-23
|
||||||
|
publish: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# Content here`;
|
||||||
|
|
||||||
|
const updated = insertOrUpdateFrontmatterProperty(
|
||||||
|
original,
|
||||||
|
"public-url",
|
||||||
|
"https://riverrooks.dev/posts/sample-note/"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.match(
|
||||||
|
updated,
|
||||||
|
/public-url:\s*"https:\/\/riverrooks\.dev\/posts\/sample-note\/"/,
|
||||||
|
"Must insert public-url into frontmatter"
|
||||||
|
);
|
||||||
|
assert.match(updated, /title:\s*"Sample Note"/, "Preserves title");
|
||||||
|
assert.match(updated, /publish:\s*true/, "Preserves publish flag");
|
||||||
|
assert.match(updated, /# Content here/, "Preserves body content");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Obsidian Plugin: insertOrUpdateFrontmatterProperty updates existing public-url", () => {
|
||||||
|
const original = `---
|
||||||
|
title: "Updated Note"
|
||||||
|
date: 2026-09-23
|
||||||
|
public-url: "https://old.domain/posts/sample-note/"
|
||||||
|
---
|
||||||
|
|
||||||
|
Body`;
|
||||||
|
|
||||||
|
const updated = insertOrUpdateFrontmatterProperty(
|
||||||
|
original,
|
||||||
|
"public-url",
|
||||||
|
"https://riverrooks.dev/posts/updated-note/"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.match(
|
||||||
|
updated,
|
||||||
|
/public-url:\s*"https:\/\/riverrooks\.dev\/posts\/updated-note\/"/,
|
||||||
|
"Must update public-url to new URL"
|
||||||
|
);
|
||||||
|
assert.doesNotMatch(
|
||||||
|
updated,
|
||||||
|
/old\.domain/,
|
||||||
|
"Old URL must be replaced"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Obsidian Plugin: insertOrUpdateFrontmatterProperty removes public-url on unpublish", () => {
|
||||||
|
const original = `---
|
||||||
|
title: "Unpublished Note"
|
||||||
|
date: 2026-09-23
|
||||||
|
public-url: "https://riverrooks.dev/posts/sample-note/"
|
||||||
|
---
|
||||||
|
|
||||||
|
Body`;
|
||||||
|
|
||||||
|
const updated = insertOrUpdateFrontmatterProperty(original, "public-url", null);
|
||||||
|
|
||||||
|
assert.doesNotMatch(updated, /public-url:/, "Must remove public-url when value is null");
|
||||||
|
assert.match(updated, /title:\s*"Unpublished Note"/, "Preserves other frontmatter");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Obsidian Plugin: Adversarial edge cases for frontmatter property insertion", () => {
|
||||||
|
// 1. Empty content
|
||||||
|
assert.equal(insertOrUpdateFrontmatterProperty("", "public-url", "https://url"), "---\npublic-url: \"https://url\"\n---\n\n");
|
||||||
|
// 2. Non-string inputs
|
||||||
|
assert.equal(insertOrUpdateFrontmatterProperty(null, "public-url", "https://url"), "");
|
||||||
|
assert.equal(insertOrUpdateFrontmatterProperty(undefined, "public-url", "https://url"), "");
|
||||||
|
// 3. Note without frontmatter
|
||||||
|
const plain = "# Just a header\nSome text.";
|
||||||
|
const result = insertOrUpdateFrontmatterProperty(plain, "public-url", "https://url");
|
||||||
|
assert.match(result, /^---\npublic-url:\s*"https:\/\/url"\n---/);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Obsidian Plugin: main.js in vault includes public-url insertion and recursion guard", () => {
|
||||||
|
assert.ok(fs.existsSync(pluginPath), `Plugin main.js must exist at ${pluginPath}`);
|
||||||
|
const pluginContent = fs.readFileSync(pluginPath, "utf-8");
|
||||||
|
|
||||||
|
// 1. Must handle public-url
|
||||||
|
assert.match(pluginContent, /public-url/i, "main.js must reference 'public-url'");
|
||||||
|
|
||||||
|
// 2. Must guard against infinite loops during frontmatter updates
|
||||||
|
assert.match(
|
||||||
|
pluginContent,
|
||||||
|
/isUpdatingFrontmatter/i,
|
||||||
|
"main.js must maintain a guard to prevent metadataCache recursion loops"
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. Must use processFrontMatter or frontmatter updater
|
||||||
|
assert.match(
|
||||||
|
pluginContent,
|
||||||
|
/processFrontMatter|updateFrontmatter/i,
|
||||||
|
"main.js must implement frontmatter updating logic"
|
||||||
|
);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user