panatgithub_AnkiHeadingSync/src/application/services/NoteFieldMappingService.test.ts
Dusk fbb289850a 清理 legacy sync 链与旧 syncRegistry 残留,保留 current manual-sync 主链 / Remove legacy sync chain and old syncRegistry remnants while preserving the current manual-sync path
删除已失效的 legacy sync use case、syncRegistry 持久化与旧 card pipeline,运行入口保持 ManualSyncService 主链。

Remove the obsolete legacy sync use cases, syncRegistry persistence, and old card pipeline while keeping the runtime on ManualSyncService.
2026-04-21 11:23:27 +08:00

132 lines
No EOL
3.5 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { createNoteFieldMappingKey } from "@/application/config/NoteModelFieldMapping";
import type { CardType } from "@/domain/card/entities/RenderedFields";
import { NoteFieldMappingService } from "./NoteFieldMappingService";
interface RenderedCardInput {
type: CardType;
noteModel: string;
renderedFields: {
title: string;
body: string;
};
}
function createCard(overrides: Partial<RenderedCardInput>): RenderedCardInput {
return {
type: "basic",
noteModel: "Basic",
renderedFields: {
title: "Prompt",
body: "Answer",
},
...overrides,
};
}
describe("NoteFieldMappingService", () => {
it("maps a basic card using a saved title/body mapping", () => {
const service = new NoteFieldMappingService();
const card = createCard({});
const fields = service.map(
card,
{
fieldNames: ["Title", "Body"],
isCloze: false,
},
{
[createNoteFieldMappingKey("basic", "Basic")]: {
cardType: "basic",
modelName: "Basic",
loadedFieldNames: ["Title", "Body"],
titleField: "Title",
bodyField: "Body",
loadedAt: 1,
},
},
);
expect(fields).toEqual({ Title: "Prompt", Body: "Answer" });
});
it("maps a cloze card into the configured main field using title and body fragments", () => {
const service = new NoteFieldMappingService();
const fields = service.map(
createCard({
type: "cloze",
noteModel: "Cloze",
renderedFields: {
title: "Context",
body: "{{c1::answer}}",
},
}),
{
fieldNames: ["Text", "Extra"],
isCloze: true,
},
{
[createNoteFieldMappingKey("cloze", "Cloze")]: {
cardType: "cloze",
modelName: "Cloze",
loadedFieldNames: ["Text", "Extra"],
mainField: "Text",
loadedAt: 1,
},
},
);
expect(fields).toEqual({ Text: "Context<br><br>{{c1::answer}}" });
});
it("throws when a mapping is missing", () => {
const service = new NoteFieldMappingService();
expect(() =>
service.map(createCard({}), { fieldNames: ["Front", "Back"], isCloze: false }, {}),
).toThrow("Open plugin settings and read fields from Anki first");
});
it("throws when a saved mapping is stale", () => {
const service = new NoteFieldMappingService();
expect(() =>
service.map(
createCard({}),
{ fieldNames: ["Front", "Body"], isCloze: false },
{
[createNoteFieldMappingKey("basic", "Basic")]: {
cardType: "basic",
modelName: "Basic",
loadedFieldNames: ["Front", "Back"],
titleField: "Front",
bodyField: "Back",
loadedAt: 1,
},
},
),
).toThrow("is stale because these fields no longer exist in Anki");
});
it("throws when a basic mapping reuses the same field for title and body", () => {
const service = new NoteFieldMappingService();
expect(() =>
service.map(
createCard({}),
{ fieldNames: ["Front", "Back"], isCloze: false },
{
[createNoteFieldMappingKey("basic", "Basic")]: {
cardType: "basic",
modelName: "Basic",
loadedFieldNames: ["Front", "Back"],
titleField: "Front",
bodyField: "Front",
loadedAt: 1,
},
},
),
).toThrow('must use different title and body fields');
});
});