/**
* Tests for processSelectedTextContexts in ContextProcessor
*
* Verifies that note and web selected text contexts are correctly
* formatted with appropriate XML tags.
*/
import { SELECTED_TEXT_TAG, WEB_SELECTED_TEXT_TAG } from "@/constants";
import { NoteSelectedTextContext, WebSelectedTextContext } from "@/types/message";
// Mock the aiParams module
const mockSelectedTextContexts: (NoteSelectedTextContext | WebSelectedTextContext)[] = [];
jest.mock("@/aiParams", () => ({
getSelectedTextContexts: () => mockSelectedTextContexts,
}));
// Import after mocking
import { ContextProcessor } from "@/contextProcessor";
describe("ContextProcessor.processSelectedTextContexts", () => {
let processor: ContextProcessor;
beforeEach(() => {
// Clear mock data
mockSelectedTextContexts.length = 0;
// Get singleton instance
processor = ContextProcessor.getInstance();
});
it("should return empty string when no selected text contexts", () => {
const result = processor.processSelectedTextContexts();
expect(result).toBe("");
});
it("should format note selected text with proper XML tags", () => {
const noteContext: NoteSelectedTextContext = {
id: "note-1",
sourceType: "note",
content: "function fibonacci(n) {\n return n <= 1 ? n : fibonacci(n-1) + fibonacci(n-2);\n}",
noteTitle: "Algorithms",
notePath: "dev/algorithms.md",
startLine: 10,
endLine: 12,
};
mockSelectedTextContexts.push(noteContext);
const result = processor.processSelectedTextContexts();
expect(result).toContain(`<${SELECTED_TEXT_TAG}>`);
expect(result).toContain(`${SELECTED_TEXT_TAG}>`);
expect(result).toContain("
Algorithms");
expect(result).toContain("dev/algorithms.md");
expect(result).toContain("10");
expect(result).toContain("12");
expect(result).toContain("");
expect(result).toContain("function fibonacci");
expect(result).toContain("");
// Should NOT contain web-specific tags
expect(result).not.toContain(`<${WEB_SELECTED_TEXT_TAG}>`);
expect(result).not.toContain("");
});
it("should format web selected text with proper XML tags", () => {
const webContext: WebSelectedTextContext = {
id: "web-1",
sourceType: "web",
content: "# React Documentation\n\nReact is a JavaScript library for building user interfaces.",
title: "React Docs",
url: "https://react.dev/learn",
};
mockSelectedTextContexts.push(webContext);
const result = processor.processSelectedTextContexts();
expect(result).toContain(`<${WEB_SELECTED_TEXT_TAG}>`);
expect(result).toContain(`${WEB_SELECTED_TEXT_TAG}>`);
expect(result).toContain("React Docs");
expect(result).toContain("https://react.dev/learn");
expect(result).toContain("");
expect(result).toContain("React Documentation");
expect(result).toContain("");
// Should NOT contain note-specific tags
expect(result).not.toContain(`<${SELECTED_TEXT_TAG}>`);
expect(result).not.toContain("");
expect(result).not.toContain("");
expect(result).not.toContain("");
});
it("should handle mixed note and web selected text contexts", () => {
const noteContext: NoteSelectedTextContext = {
id: "note-1",
sourceType: "note",
content: "Local note content about React patterns",
noteTitle: "React Patterns",
notePath: "dev/react-patterns.md",
startLine: 15,
endLine: 20,
};
const webContext: WebSelectedTextContext = {
id: "web-1",
sourceType: "web",
content: "Web content about React best practices",
title: "React Best Practices",
url: "https://react.dev/best-practices",
};
mockSelectedTextContexts.push(noteContext, webContext);
const result = processor.processSelectedTextContexts();
// Verify both context types are present
expect(result).toContain(`<${SELECTED_TEXT_TAG}>`);
expect(result).toContain(`${SELECTED_TEXT_TAG}>`);
expect(result).toContain(`<${WEB_SELECTED_TEXT_TAG}>`);
expect(result).toContain(`${WEB_SELECTED_TEXT_TAG}>`);
// Verify note selection has path and line numbers
expect(result).toContain("dev/react-patterns.md");
expect(result).toContain("15");
expect(result).toContain("20");
// Verify web selection has url
expect(result).toContain("https://react.dev/best-practices");
// Verify content from both
expect(result).toContain("Local note content about React patterns");
expect(result).toContain("Web content about React best practices");
});
it("should escape XML special characters in content", () => {
const noteContext: NoteSelectedTextContext = {
id: "note-1",
sourceType: "note",
content: "Code with & special \"chars\"",
noteTitle: "Test ",
notePath: "test/path&file.md",
startLine: 1,
endLine: 1,
};
mockSelectedTextContexts.push(noteContext);
const result = processor.processSelectedTextContexts();
// Title and path should be escaped
expect(result).toContain("Test <Note>");
expect(result).toContain("test/path&file.md");
});
it("should escape XML special characters in web context", () => {
const webContext: WebSelectedTextContext = {
id: "web-1",
sourceType: "web",
content: "Content with tags",
title: "Page ",
url: "https://example.com/page?a=1&b=2",
};
mockSelectedTextContexts.push(webContext);
const result = processor.processSelectedTextContexts();
// Title and URL should be escaped
expect(result).toContain("Page <Title>");
expect(result).toContain("https://example.com/page?a=1&b=2");
});
});