Files
stack/apps/api/src/personalities/services/prompt-formatter.service.spec.ts
T
Jason Woltje 8383a98070 feat(#82): add prompt formatter service to personality module
- Add PromptFormatterService for formatting system prompts based on personality
- Support context variable interpolation (userName, workspaceName, etc.)
- Add formality level modifiers (VERY_CASUAL to VERY_FORMAL)
- Add template validation for custom variables
- Add preview endpoint for formatted prompts
- Fix UpdatePersonalityDto to avoid @nestjs/mapped-types dependency
- Update PersonalitiesController with new endpoints
- Add comprehensive tests (33 passing tests)

Closes #82
2026-01-29 19:38:18 -06:00

109 lines
4.0 KiB
TypeScript

import { describe, it, expect, beforeEach } from "vitest";
import { Test, TestingModule } from "@nestjs/testing";
import { PromptFormatterService, PromptContext } from "./prompt-formatter.service";
describe("PromptFormatterService", () => {
let service: PromptFormatterService;
const mockPersonality = {
id: "personality-123",
workspaceId: "workspace-123",
name: "Professional",
description: "Professional communication style",
tone: "professional",
formalityLevel: "FORMAL" as const,
systemPromptTemplate: "You are a helpful assistant for {{userName}} at {{workspaceName}}.",
isDefault: true,
isActive: true,
createdAt: new Date(),
updatedAt: new Date(),
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [PromptFormatterService],
}).compile();
service = module.get<PromptFormatterService>(PromptFormatterService);
});
describe("formatPrompt", () => {
it("should format prompt with context variables", () => {
const context: PromptContext = { userName: "John", workspaceName: "Acme Corp" };
const result = service.formatPrompt(mockPersonality, context);
expect(result.systemPrompt).toContain("John");
expect(result.systemPrompt).toContain("Acme Corp");
expect(result.metadata.personalityId).toBe(mockPersonality.id);
});
it("should add formality modifier", () => {
const result = service.formatPrompt(mockPersonality);
expect(result.systemPrompt).toContain("professional");
});
it("should include metadata", () => {
const result = service.formatPrompt(mockPersonality);
expect(result.metadata.formattedAt).toBeInstanceOf(Date);
expect(result.metadata.tone).toBe("professional");
});
it("should handle custom context variables", () => {
const personality = { ...mockPersonality, systemPromptTemplate: "Custom: {{customVar}}" };
const context: PromptContext = { custom: { customVar: "test-value" } };
const result = service.formatPrompt(personality, context);
expect(result.systemPrompt).toContain("test-value");
});
});
describe("buildSystemPrompt", () => {
it("should build complete prompt with context", () => {
const context: PromptContext = { userName: "Jane" };
const result = service.buildSystemPrompt(mockPersonality, context);
expect(result).toContain("Jane");
});
it("should include date/time when requested", () => {
const context: PromptContext = { currentDate: "2024-01-29", currentTime: "14:30", timezone: "UTC" };
const result = service.buildSystemPrompt(mockPersonality, context, { includeDateTime: true });
expect(result).toContain("2024-01-29");
expect(result).toContain("14:30");
});
it("should include additional instructions", () => {
const result = service.buildSystemPrompt(mockPersonality, undefined, {
additionalInstructions: "Be concise.",
});
expect(result).toContain("Be concise.");
});
});
describe("validateTemplate", () => {
it("should validate known variables", () => {
const template = "Hello {{userName}}, welcome to {{workspaceName}}!";
const result = service.validateTemplate(template);
expect(result.valid).toBe(true);
});
it("should report unknown variables", () => {
const template = "Hello {{unknownVar}}!";
const result = service.validateTemplate(template);
expect(result.valid).toBe(false);
expect(result.missingVariables).toContain("unknownVar");
});
it("should allow custom_ prefixed variables", () => {
const template = "Value: {{custom_myVar}}";
const result = service.validateTemplate(template);
expect(result.valid).toBe(true);
});
});
describe("getFormalityLevels", () => {
it("should return all formality levels", () => {
const levels = service.getFormalityLevels();
expect(levels).toHaveLength(5);
expect(levels.map((l) => l.level)).toContain("FORMAL");
});
});
});