import { disconnectQueues } from "@/src/__tests__/test-utils"; import { appRouter } from "@/src/server/api/root"; import { createInnerTRPCContext } from "@/src/server/api/trpc"; import { prisma } from "@langfuse/shared/src/db"; import { createOrgProjectAndApiKey } from "@langfuse/shared/src/server"; import type { Session } from "next-auth"; import { v4 } from "uuid"; import waitForExpect from "wait-for-expect"; async function prepare() { const { project, org } = await createOrgProjectAndApiKey(); const session: Session = { expires: "1", user: { id: "user-1", canCreateOrganizations: true, name: "Demo User", organizations: [ { id: org.id, name: org.name, role: "OWNER", plan: "cloud:hobby", cloudConfig: undefined, metadata: {}, projects: [ { id: project.id, role: "ADMIN", retentionDays: 30, deletedAt: null, name: project.name, metadata: {}, }, ], }, ], featureFlags: { excludeClickhouseRead: false, templateFlag: true, }, admin: true, }, environment: { enableExperimentalFeatures: false, selfHostedInstancePlan: "cloud:hobby", }, }; const ctx = createInnerTRPCContext({ session, headers: {} }); const caller = appRouter.createCaller({ ...ctx, prisma }); return { project, org, session, ctx, caller }; } describe("prompts trpc", () => { afterAll(async () => { await disconnectQueues(); }); describe("prompts.setLabels", () => { it("should set labels on a prompt and remove them from other versions", async () => { const { project, caller } = await prepare(); // Create trigger for prompt updates const trigger = await prisma.trigger.create({ data: { id: v4(), projectId: project.id, eventSource: "prompt", eventActions: ["updated"], filter: [], status: "ACTIVE", }, }); // Create webhook action const action = await prisma.action.create({ data: { id: v4(), projectId: project.id, type: "WEBHOOK", config: { type: "WEBHOOK", url: "https://example.com/prompt-labels-webhook", headers: { "Content-Type": "application/json" }, apiVersion: { prompt: "v1" }, }, }, }); // Link trigger to action await prisma.automation.create({ data: { projectId: project.id, triggerId: trigger.id, actionId: action.id, name: "Prompt Labels Automation", }, }); // Create test prompts with different versions const prompt1 = await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "test-prompt", version: 1, type: "text", prompt: { text: "Hello world v1" }, createdBy: "test-user", labels: ["production"], }, }); const prompt2 = await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "test-prompt", version: 2, type: "text", prompt: { text: "Hello world v2" }, createdBy: "test-user", labels: ["latest"], }, }); // Set "production" label on prompt2, which should remove it from prompt1 await caller.prompts.setLabels({ projectId: project.id, promptId: prompt2.id, labels: ["production", "latest"], }); // Verify that prompt1 no longer has the "production" label const updatedPrompt1 = await prisma.prompt.findUnique({ where: { id: prompt1.id }, }); expect(updatedPrompt1?.labels).not.toContain("production"); // Verify that prompt2 has both labels const updatedPrompt2 = await prisma.prompt.findUnique({ where: { id: prompt2.id }, }); expect(updatedPrompt2?.labels).toEqual( expect.arrayContaining(["production", "latest"]), ); await waitForExpect(async () => { const executions = await prisma.automationExecution.findMany({ where: { projectId: project.id, triggerId: trigger.id, actionId: action.id, }, }); expect(executions).toHaveLength(2); expect(executions).toEqual( expect.arrayContaining([ expect.objectContaining({ sourceId: prompt1.id, status: "PENDING", }), expect.objectContaining({ sourceId: prompt2.id, status: "PENDING", }), ]), ); }); }); }); describe("prompts.updateTags", () => { it("should update tags on all versions of a prompt", async () => { const { project, caller } = await prepare(); // Create trigger for prompt updates const trigger = await prisma.trigger.create({ data: { id: v4(), projectId: project.id, eventSource: "prompt", eventActions: ["updated"], filter: [], status: "ACTIVE", }, }); // Create webhook action const action = await prisma.action.create({ data: { id: v4(), projectId: project.id, type: "WEBHOOK", config: { type: "WEBHOOK", url: "https://example.com/prompt-labels-webhook", headers: { "Content-Type": "application/json" }, apiVersion: { prompt: "v1" }, }, }, }); // Link trigger to action await prisma.automation.create({ data: { projectId: project.id, triggerId: trigger.id, actionId: action.id, name: "Prompt Tags Automation", }, }); // Create test prompts with different versions but same name await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "test-prompt-tags", version: 1, type: "text", prompt: { text: "Hello world v1" }, createdBy: "test-user", tags: ["old-tag"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "test-prompt-tags", version: 2, type: "text", prompt: { text: "Hello world v2" }, createdBy: "test-user", tags: ["old-tag"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "test-prompt-tags", version: 3, type: "text", prompt: { text: "Hello world v3" }, createdBy: "test-user", tags: ["old-tag"], }, }); // Update tags for all versions of the prompt await caller.prompts.updateTags({ projectId: project.id, name: "test-prompt-tags", tags: ["new-tag", "updated-tag"], }); // Verify that all versions now have the new tags const updatedPrompts = await prisma.prompt.findMany({ where: { projectId: project.id, name: "test-prompt-tags", }, orderBy: { version: "asc" }, }); expect(updatedPrompts).toHaveLength(3); updatedPrompts.forEach((prompt) => { expect(prompt.tags).toEqual( expect.arrayContaining(["new-tag", "updated-tag"]), ); expect(prompt.tags).not.toContain("old-tag"); }); await waitForExpect(async () => { const executions = await prisma.automationExecution.findMany({ where: { projectId: project.id, triggerId: trigger.id, actionId: action.id, }, }); expect(executions).toHaveLength(3); expect(executions).toEqual( expect.arrayContaining([ expect.objectContaining({ sourceId: updatedPrompts[0].id, status: "PENDING", }), expect.objectContaining({ sourceId: updatedPrompts[1].id, status: "PENDING", }), expect.objectContaining({ sourceId: updatedPrompts[2].id, status: "PENDING", }), ]), ); }); }); }); describe("prompts.delete", () => { it("should delete all versions of a prompt", async () => { const { project, caller } = await prepare(); // Create trigger for prompt deletions const trigger = await prisma.trigger.create({ data: { id: v4(), projectId: project.id, eventSource: "prompt", eventActions: ["deleted"], filter: [], status: "ACTIVE", }, }); // Create webhook action const action = await prisma.action.create({ data: { id: v4(), projectId: project.id, type: "WEBHOOK", config: { type: "WEBHOOK", url: "https://example.com/prompt-delete-webhook", headers: { "Content-Type": "application/json" }, apiVersion: { prompt: "v1" }, }, }, }); // Link trigger to action await prisma.automation.create({ data: { projectId: project.id, triggerId: trigger.id, actionId: action.id, name: "Prompt Delete Automation", }, }); // Create test prompts with multiple versions const prompt1 = await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "test-prompt-delete", version: 1, type: "text", prompt: { text: "Hello world v1" }, createdBy: "test-user", }, }); const prompt2 = await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "test-prompt-delete", version: 2, type: "text", prompt: { text: "Hello world v2" }, createdBy: "test-user", }, }); // Delete all versions of the prompt await caller.prompts.delete({ projectId: project.id, promptName: "test-prompt-delete", }); // Verify prompts are deleted const remainingPrompts = await prisma.prompt.findMany({ where: { projectId: project.id, name: "test-prompt-delete", }, }); expect(remainingPrompts).toHaveLength(0); await waitForExpect(async () => { // Verify automation executions were created for both deleted prompts const executions = await prisma.automationExecution.findMany({ where: { projectId: project.id, triggerId: trigger.id, actionId: action.id, }, }); expect(executions).toHaveLength(2); expect(executions).toEqual( expect.arrayContaining([ expect.objectContaining({ sourceId: prompt1.id, status: "PENDING", }), expect.objectContaining({ sourceId: prompt2.id, status: "PENDING", }), ]), ); }); }); }); describe("prompts.deleteVersion", () => { it("should delete a specific version of a prompt", async () => { const { project, caller } = await prepare(); // Create trigger for prompt deletions const trigger = await prisma.trigger.create({ data: { id: v4(), projectId: project.id, eventSource: "prompt", eventActions: ["deleted"], filter: [], status: "ACTIVE", }, }); // Create webhook action const action = await prisma.action.create({ data: { id: v4(), projectId: project.id, type: "WEBHOOK", config: { type: "WEBHOOK", url: "https://example.com/prompt-delete-version-webhook", headers: { "Content-Type": "application/json" }, apiVersion: { prompt: "v1" }, }, }, }); // Link trigger to action await prisma.automation.create({ data: { projectId: project.id, triggerId: trigger.id, actionId: action.id, name: "Prompt Delete Version Automation", }, }); // Create test prompts with multiple versions const prompt1 = await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "test-prompt-delete-version", version: 1, type: "text", prompt: { text: "Hello world v1" }, createdBy: "test-user", }, }); const prompt2 = await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "test-prompt-delete-version", version: 2, type: "text", prompt: { text: "Hello world v2" }, createdBy: "test-user", }, }); // Delete only version 1 await caller.prompts.deleteVersion({ projectId: project.id, promptVersionId: prompt1.id, }); // Verify only version 1 is deleted const remainingPrompts = await prisma.prompt.findMany({ where: { projectId: project.id, name: "test-prompt-delete-version", }, }); expect(remainingPrompts).toHaveLength(1); expect(remainingPrompts[0].id).toBe(prompt2.id); await waitForExpect(async () => { // Verify automation execution was created for the deleted prompt const executions = await prisma.automationExecution.findMany({ where: { projectId: project.id, triggerId: trigger.id, actionId: action.id, }, }); expect(executions).toHaveLength(1); expect(executions[0]).toEqual( expect.objectContaining({ sourceId: prompt1.id, status: "PENDING", }), ); }); }); }); describe("prompts.duplicatePrompt", () => { it("should duplicate a prompt and trigger webhook automation", async () => { const { project, caller } = await prepare(); // Create trigger for prompt creation const trigger = await prisma.trigger.create({ data: { id: v4(), projectId: project.id, eventSource: "prompt", eventActions: ["created"], filter: [], status: "ACTIVE", }, }); // Create webhook action const action = await prisma.action.create({ data: { id: v4(), projectId: project.id, type: "WEBHOOK", config: { type: "WEBHOOK", url: "https://example.com/prompt-duplicate-webhook", headers: { "Content-Type": "application/json" }, apiVersion: { prompt: "v1" }, }, }, }); // Link trigger to action await prisma.automation.create({ data: { projectId: project.id, triggerId: trigger.id, actionId: action.id, name: "Prompt Duplicate Automation", }, }); // Create original prompt to duplicate const originalPrompt = await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "original-prompt", version: 1, type: "text", prompt: "Hello world original", createdBy: "test-user", labels: ["production"], tags: ["original"], }, }); // Duplicate the prompt const duplicatedPrompt = await caller.prompts.duplicatePrompt({ projectId: project.id, promptId: originalPrompt.id, name: "duplicated-prompt", isSingleVersion: true, }); expect(duplicatedPrompt).toMatchObject({ name: "duplicated-prompt", version: 1, type: "text", prompt: "Hello world original", labels: expect.arrayContaining(["production", "latest"]), tags: ["original"], }); // Verify the duplicated prompt exists in database const dbPrompt = await prisma.prompt.findUnique({ where: { id: duplicatedPrompt.id }, }); expect(dbPrompt).not.toBeNull(); expect(dbPrompt?.name).toBe("duplicated-prompt"); await waitForExpect(async () => { // Verify automation execution was created for the duplicated prompt const executions = await prisma.automationExecution.findMany({ where: { projectId: project.id, triggerId: trigger.id, actionId: action.id, }, }); expect(executions).toHaveLength(1); expect(executions[0]).toEqual( expect.objectContaining({ sourceId: duplicatedPrompt.id, status: "PENDING", }), ); }); }); }); describe("prompts.all with search", () => { it("should find prompts by searching in content, name, tags, and labels", async () => { const { project, caller } = await prepare(); // Create test prompts with different searchable content await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "customer-service-prompt", version: 1, type: "text", prompt: { text: "You are a helpful customer support agent. Answer questions about billing and account issues.", }, createdBy: "test-user", tags: ["support", "customer"], labels: ["production"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "marketing-prompt", version: 1, type: "text", prompt: { text: "Create engaging marketing content that drives sales and conversions.", }, createdBy: "test-user", tags: ["marketing", "content"], labels: ["staging"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "technical-docs", version: 1, type: "text", prompt: { text: "Generate comprehensive technical documentation for APIs and software systems.", }, createdBy: "test-user", tags: ["technical", "documentation"], labels: ["latest"], }, }); // Test 1: Search by prompt content const contentSearchResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, searchQuery: "customer support agent", searchType: ["content"], }); expect(contentSearchResults.prompts).toHaveLength(1); expect(contentSearchResults.prompts[0].name).toBe( "customer-service-prompt", ); // Test 2: Search by prompt name const nameSearchResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, searchQuery: "marketing", searchType: ["id"], }); expect(nameSearchResults.prompts).toHaveLength(1); expect(nameSearchResults.prompts[0].name).toBe("marketing-prompt"); // Test 3: Search by tags const tagSearchResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, searchQuery: "documentation", searchType: ["id"], }); expect(tagSearchResults.prompts).toHaveLength(1); expect(tagSearchResults.prompts[0].name).toBe("technical-docs"); // Test 4: Search with no matches const noMatchResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, searchQuery: "nonexistent content", searchType: ["id", "content"], }); expect(noMatchResults.prompts).toHaveLength(0); // Test 5: Case insensitive search const caseInsensitiveResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, searchQuery: "TECHNICAL", searchType: ["id"], }); expect(caseInsensitiveResults.prompts).toHaveLength(1); expect(caseInsensitiveResults.prompts[0].name).toBe("technical-docs"); }); it("should find prompts with multiple versions when searching content", async () => { const { project, caller } = await prepare(); // Create multiple versions of the same prompt with different content await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "evolving-prompt", version: 1, type: "text", prompt: { text: "You are a basic chatbot. Answer simple questions." }, createdBy: "test-user", tags: ["basic"], labels: [], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "evolving-prompt", version: 2, type: "text", prompt: { text: "You are an advanced AI assistant with expertise in machine learning.", }, createdBy: "test-user", tags: ["advanced"], labels: ["latest"], }, }); // Search for content that exists in version 2 but not version 1 const searchResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, searchQuery: "machine learning", searchType: ["content"], }); // Should find the prompt because one of its versions contains the search term expect(searchResults.prompts).toHaveLength(1); expect(searchResults.prompts[0].name).toBe("evolving-prompt"); // The returned prompt should be the latest version expect(searchResults.prompts[0].version).toBe(2); }); }); describe("prompts.count with search and searchType", () => { it("should count prompts correctly with different search types", async () => { const { project, caller } = await prepare(); // Create test prompts with different searchable content await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "customer-service-prompt", version: 1, type: "text", prompt: { text: "You are a helpful customer support agent. Answer questions about billing and account issues.", }, createdBy: "test-user", tags: ["support", "customer"], labels: ["production"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "marketing-prompt", version: 1, type: "text", prompt: { text: "Create engaging marketing content that drives sales and conversions.", }, createdBy: "test-user", tags: ["marketing", "content"], labels: ["staging"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "technical-docs", version: 1, type: "text", prompt: { text: "Generate comprehensive technical documentation for APIs and software systems.", }, createdBy: "test-user", tags: ["technical", "documentation"], labels: ["latest"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "sales-support-prompt", version: 1, type: "text", prompt: { text: "Assist sales teams with lead qualification and customer outreach.", }, createdBy: "test-user", tags: ["sales", "support"], labels: ["production"], }, }); // Test 1: Count all prompts (no search) const totalCountResult = await caller.prompts.count({ projectId: project.id, }); expect(totalCountResult.totalCount).toBe(BigInt(4)); // Test 2: Count with ID search type (default) - search in names and tags const idSearchCountResult = await caller.prompts.count({ projectId: project.id, searchQuery: "support", searchType: ["id"], }); // Should find "customer-service-prompt" and "sales-support-prompt" (by name and tags) expect(idSearchCountResult.totalCount).toBe(BigInt(2)); // Test 3: Count with content search type - search in prompt content const contentSearchCountResult = await caller.prompts.count({ projectId: project.id, searchQuery: "customer", searchType: ["content"], }); // Should find "customer-service-prompt" and "sales-support-prompt" (by content: "customer" appears in both) expect(contentSearchCountResult.totalCount).toBe(BigInt(2)); // Test 4: Count with both ID and content search types const combinedSearchCountResult = await caller.prompts.count({ projectId: project.id, searchQuery: "marketing", searchType: ["id", "content"], }); // Should find "marketing-prompt" (by both name and content) expect(combinedSearchCountResult.totalCount).toBe(BigInt(1)); // Test 5: Count with tag-specific search (ID search type) const tagSearchCountResult = await caller.prompts.count({ projectId: project.id, searchQuery: "documentation", searchType: ["id"], }); // Should find "technical-docs" (by tag) expect(tagSearchCountResult.totalCount).toBe(BigInt(1)); // Test 6: Count with content that doesn't exist in names/tags but exists in prompt text const contentOnlySearchResult = await caller.prompts.count({ projectId: project.id, searchQuery: "billing", searchType: ["content"], }); // Should find "customer-service-prompt" (by content only) expect(contentOnlySearchResult.totalCount).toBe(BigInt(1)); // Test 7: Count with no matches const noMatchCountResult = await caller.prompts.count({ projectId: project.id, searchQuery: "nonexistent", searchType: ["id", "content"], }); expect(noMatchCountResult.totalCount).toBe(BigInt(0)); // Test 8: Count with case insensitive search const caseInsensitiveCountResult = await caller.prompts.count({ projectId: project.id, searchQuery: "TECHNICAL", searchType: ["id"], }); // Should find "technical-docs" (case insensitive) expect(caseInsensitiveCountResult.totalCount).toBe(BigInt(1)); // Test 9: Count with filters and search combined const filteredSearchCountResult = await caller.prompts.count({ projectId: project.id, searchQuery: "support", searchType: ["id"], filter: [ { column: "labels", type: "arrayOptions", operator: "any of", value: ["production"], }, ], }); // Should find prompts with "support" AND "production" label expect(filteredSearchCountResult.totalCount).toBe(BigInt(2)); }); it("should count prompts with folder path prefix and search", async () => { const { project, caller } = await prepare(); // Create prompts in different folder structures await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "folder1/customer-prompt", version: 1, type: "text", prompt: { text: "Customer service prompt" }, createdBy: "test-user", tags: ["customer"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "folder1/support-prompt", version: 1, type: "text", prompt: { text: "Technical support prompt" }, createdBy: "test-user", tags: ["support"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "folder2/customer-prompt", version: 1, type: "text", prompt: { text: "Another customer prompt" }, createdBy: "test-user", tags: ["customer"], }, }); // Test: Count with path prefix and search const folderSearchCountResult = await caller.prompts.count({ projectId: project.id, pathPrefix: "folder1", searchQuery: "customer", searchType: ["id"], }); // Should only find prompts in folder1 that match "customer" expect(folderSearchCountResult.totalCount).toBe(BigInt(1)); // Test: Count with path prefix but no search const folderCountResult = await caller.prompts.count({ projectId: project.id, pathPrefix: "folder1", }); // Should find all prompts in folder1 expect(folderCountResult.totalCount).toBe(BigInt(2)); }); }); describe("folder navigation with conflicting names", () => { it("should handle prompts where individual prompt name conflicts with folder prefix - BUG REPRODUCTION", async () => { const { project, caller } = await prepare(); // Create the exact bug scenario: // - a/prompt (individual prompt) // - a/prompt/v1 (prompt in subfolder) // - a/prompt/v2 (prompt in subfolder) // Bug: LFE-6515 await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "a/prompt", version: 1, type: "text", prompt: { text: "This is the individual a/prompt" }, createdBy: "test-user", tags: ["individual"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "a/prompt/v1", version: 1, type: "text", prompt: { text: "This is a/prompt/v1" }, createdBy: "test-user", tags: ["subfolder"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "a/prompt/v2", version: 1, type: "text", prompt: { text: "This is a/prompt/v2" }, createdBy: "test-user", tags: ["subfolder"], }, }); // Test 1: Root level should show folder "a" const rootResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, }); // Should show exactly one item: the "a" folder expect(rootResults.prompts).toHaveLength(1); expect(rootResults.prompts[0].name).toBe("a"); // Test 2: Folder "a" level should show BOTH individual "prompt" AND folder entry for "prompt/*" const folderAResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, pathPrefix: "a", }); // We expect 2 items: individual "prompt" and folder "prompt" (for v1, v2) expect(folderAResults.prompts).toHaveLength(2); // Should have both an individual prompt and a folder entry const promptNames = folderAResults.prompts.map((p) => p.name); expect(promptNames).toContain("prompt"); // Test 3: Folder "a/prompt" level should show v1 and v2 const subfolderResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, pathPrefix: "a/prompt", }); // Should show exactly 2 items: v1 and v2 expect(subfolderResults.prompts).toHaveLength(2); const subfolderNames = subfolderResults.prompts.map((p) => p.name); expect(subfolderNames).toContain("v1"); expect(subfolderNames).toContain("v2"); // Test 4: Count verification const rootCount = await caller.prompts.count({ projectId: project.id, }); expect(rootCount.totalCount).toBe(BigInt(1)); // Should show 1 folder const folderACount = await caller.prompts.count({ projectId: project.id, pathPrefix: "a", }); expect(folderACount.totalCount).toBe(BigInt(2)); // Should show individual + folder entry const subfolderCount = await caller.prompts.count({ projectId: project.id, pathPrefix: "a/prompt", }); expect(subfolderCount.totalCount).toBe(BigInt(2)); // Should show v1 and v2 }); it("should maintain search functionality across conflicting folder/prompt names", async () => { const { project, caller } = await prepare(); // Create searchable content in conflicting structure await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "search/test", version: 1, type: "text", prompt: { text: "Individual search test with unique keyword" }, createdBy: "test-user", tags: ["searchable"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "search/test/nested1", version: 1, type: "text", prompt: { text: "Nested prompt with unique keyword" }, createdBy: "test-user", tags: ["nested"], }, }); await prisma.prompt.create({ data: { id: v4(), projectId: project.id, name: "search/test/nested2", version: 1, type: "text", prompt: { text: "Another nested prompt" }, createdBy: "test-user", tags: ["nested"], }, }); // Test search at different folder levels const searchResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, searchQuery: "unique", searchType: ["content"], }); // Should find prompts containing "unique" keyword expect(searchResults.prompts.length).toBeGreaterThan(0); // Test search within specific folder const folderSearchResults = await caller.prompts.all({ projectId: project.id, page: 0, limit: 10, filter: [], orderBy: { column: "createdAt", order: "DESC" }, pathPrefix: "search/test", searchQuery: "nested", searchType: ["content"], }); // Should find nested prompts within the folder expect(folderSearchResults.prompts.length).toBeGreaterThan(0); }); }); });