diff --git a/apps/server/src/share/content_renderer.spec.ts b/apps/server/src/share/content_renderer.spec.ts
index 80c754200..04f60bd71 100644
--- a/apps/server/src/share/content_renderer.spec.ts
+++ b/apps/server/src/share/content_renderer.spec.ts
@@ -1,12 +1,12 @@
import { describe, it, expect } from "vitest";
-import { renderCode, renderText, type Result } from "./content_renderer.js";
+import { getContent, renderCode, renderText, type Result } from "./content_renderer.js";
import { trimIndentation } from "@triliumnext/commons";
-import SNote from "./shaca/entities/snote.js";
+import { buildShareNote } from "../test/shaca_mocking.js";
describe("content_renderer", () => {
describe("renderText", () => {
it("parses simple note", () => {
- const input = trimIndentation`\
+ const content = trimIndentation`\
@@ -15,14 +15,12 @@ describe("content_renderer", () => {
Welcome to Trilium Notes!
`;
-
- const result = {
- content: input,
- header: "",
- isEmpty: false
- };
- renderText(result, new SNote([ "root", "Note", "text", "text/plain", "1234", "2025-09-28T00:00Z", false]));
- expect(result.content).toMatch(input);
+ const note = buildShareNote({
+ title: "Note",
+ content
+ });
+ const result = getContent(note);
+ expect(result.content).toStrictEqual(content);
});
});
diff --git a/apps/server/src/share/content_renderer.ts b/apps/server/src/share/content_renderer.ts
index c12e7887f..253c43b39 100644
--- a/apps/server/src/share/content_renderer.ts
+++ b/apps/server/src/share/content_renderer.ts
@@ -16,7 +16,7 @@ export interface Result {
isEmpty?: boolean;
}
-function getContent(note: SNote) {
+export function getContent(note: SNote) {
if (note.isProtected) {
return {
header: "",
@@ -65,7 +65,7 @@ function renderIndex(result: Result) {
result.content += "";
}
-function renderText(result: Result, note: SNote) {
+export function renderText(result: Result, note: SNote) {
const document = new JSDOM(result.content || "").window.document;
// Process include notes.
diff --git a/apps/server/src/test/shaca_mocking.ts b/apps/server/src/test/shaca_mocking.ts
new file mode 100644
index 000000000..e92411500
--- /dev/null
+++ b/apps/server/src/test/shaca_mocking.ts
@@ -0,0 +1,97 @@
+import utils from "../services/utils.js";
+import SAttribute from "../share/shaca/entities/sattribute.js";
+import SNote from "../share/shaca/entities/snote.js";
+import shaca from "../share/shaca/shaca.js";
+
+type AttributeDefinitions = { [key in `#${string}`]: string; };
+type RelationDefinitions = { [key in `~${string}`]: string; };
+
+interface NoteDefinition extends AttributeDefinitions, RelationDefinitions {
+ id?: string | undefined;
+ title: string;
+ content?: string | Buffer;
+}
+
+/**
+ * Creates the given notes with the given title and optionally one or more attributes.
+ *
+ * For a label to be created, simply pass on a key prefixed with `#` and any desired value.
+ *
+ * The notes and attributes will be injected in the froca.
+ *
+ * @param notes
+ * @returns an array containing the IDs of the created notes.
+ * @example
+ * buildShareNotes([
+ * { title: "A", "#startDate": "2025-05-05" },
+ * { title: "B", "#startDate": "2025-05-07" }
+ * ]);
+ */
+export function buildShareNotes(notes: NoteDefinition[]) {
+ const ids: string[] = [];
+
+ for (const noteDef of notes) {
+ ids.push(buildShareNote(noteDef).noteId);
+ }
+
+ return ids;
+}
+
+export function buildShareNote(noteDef: NoteDefinition) {
+ const blobId = "foo";
+ const note = new SNote([
+ noteDef.id ?? utils.randomString(12),
+ noteDef.title,
+ "text",
+ "text/html",
+ blobId,
+ new Date().toUTCString(), // utcDateModified
+ false // is protected
+ ]);
+ shaca.notes[note.noteId] = note;
+
+ // Handle content
+ if (noteDef.content) {
+ note.getContent = () => noteDef.content;
+ }
+
+ // Handle labels & relations
+ let position = 0;
+ for (const [ key, value ] of Object.entries(noteDef)) {
+ const attributeId = utils.randomString(12);
+ const name = key.substring(1);
+
+ let attribute: SAttribute | null = null;
+ if (key.startsWith("#")) {
+ attribute = new SAttribute([
+ attributeId,
+ note.noteId,
+ "label",
+ name,
+ value,
+ false, // isInheritable
+ position // position
+ ]);
+ }
+
+ if (key.startsWith("~")) {
+ attribute = new SAttribute([
+ attributeId,
+ note.noteId,
+ "relation",
+ name,
+ value,
+ false, // isInheritable
+ position // position
+ ]);
+ }
+
+ if (!attribute) {
+ continue;
+ }
+
+ shaca.attributes[attributeId] = attribute;
+ position++;
+ }
+ return note;
+}