UNPKG

ai-pp3

Version:

CLI tool combining multimodal AI analysis with RawTherapee's engine to generate optimized PP3 profiles for RAW photography

193 lines (190 loc) 6.93 kB
import { describe, expect, it } from "vitest"; // We need to import the function from agent.ts, but it's not exported // For testing purposes, let's create a test version // Helper functions to reduce cognitive complexity function findSectionHeader(searchLines) { const sectionHeaderLine = searchLines.find((line) => line.trim().startsWith("[")); return sectionHeaderLine ? sectionHeaderLine.trim() : null; } function findSectionEndIndex(contentLines, sectionStartIndex) { let sectionEndIndex = contentLines.length; for (let index = sectionStartIndex + 1; index < contentLines.length; index++) { const line = contentLines[index].trim(); if (line.startsWith("[") && line.endsWith("]")) { sectionEndIndex = index; break; } } return sectionEndIndex; } function extractParameters(lines) { return lines .filter((line) => !line.trim().startsWith("[") && line.trim().length > 0) .map((line) => line.trim()); } function createReplaceMap(searchParameters, replaceParameters) { const replaceMap = new Map(); for (const [index, searchParameter] of searchParameters.entries()) { const replaceParameter = replaceParameters[index]; const searchParameterName = searchParameter.split("=")[0]; replaceMap.set(searchParameterName, replaceParameter); } return replaceMap; } function applyFuzzySearchReplace(content, search, replace) { // This is a simplified version for testing - we'll import the actual function later const searchLines = search.trim().split("\n"); const replaceLines = replace.trim().split("\n"); const contentLines = content.split("\n"); // Find the section header const sectionHeader = findSectionHeader(searchLines); if (!sectionHeader) { return content.replace(search.trim(), replace.trim()); } const sectionStartIndex = contentLines.findIndex((line) => line.trim() === sectionHeader); if (sectionStartIndex === -1) { return content; } // Find section end const sectionEndIndex = findSectionEndIndex(contentLines, sectionStartIndex); // Extract parameters const searchParameters = extractParameters(searchLines); const replaceParameters = extractParameters(replaceLines); if (searchParameters.length !== replaceParameters.length) { return content.replace(search.trim(), replace.trim()); } // Create replacement map const replaceMap = createReplaceMap(searchParameters, replaceParameters); // Apply replacements const result = [...contentLines]; const indentationRegex = /^\s*/; for (let index = sectionStartIndex + 1; index < sectionEndIndex; index++) { const line = result[index].trim(); if (line.length === 0) continue; const parameterName = line.split("=")[0]; if (replaceMap.has(parameterName)) { const originalIndentation = indentationRegex.exec(result[index])?.[0] ?? ""; const replacementValue = replaceMap.get(parameterName); if (replacementValue !== undefined) { result[index] = originalIndentation + replacementValue; } } } return result.join("\n"); } describe("Fuzzy Search/Replace", () => { const samplePP3Content = `[Version] AppVersion=5.11 Version=351 [General] ColorLabel=0 InTrash=false [ColorToning] Enabled=false Method=LabRegions Lumamode=true Twocolor=Std Redlow=0 Greenlow=0 Bluelow=0 Satlow=0 Balance=0 [Exposure] Auto=false Clip=0.02 Compensation=0 Brightness=0 Contrast=0`; it("should handle line skipping in ColorToning section", () => { const search = `[ColorToning] Lumamode=true Twocolor=Std Redlow=0`; const replace = `[ColorToning] Lumamode=true Twocolor=Std Redlow=20`; const result = applyFuzzySearchReplace(samplePP3Content, search, replace); expect(result).toContain("Redlow=20"); expect(result).toContain("Enabled=false"); expect(result).toContain("Method=LabRegions"); expect(result).toContain("Lumamode=true"); expect(result).toContain("Twocolor=Std"); }); it("should preserve indentation", () => { const contentWithIndentation = `[ColorToning] Enabled=false Method=LabRegions Lumamode=true Twocolor=Std Redlow=0`; const search = `[ColorToning] Lumamode=true Redlow=0`; const replace = `[ColorToning] Lumamode=false Redlow=25`; const result = applyFuzzySearchReplace(contentWithIndentation, search, replace); expect(result).toContain(" Lumamode=false"); expect(result).toContain(" Redlow=25"); expect(result).toContain(" Enabled=false"); }); it("should handle multiple parameter changes", () => { const search = `[ColorToning] Lumamode=true Redlow=0 Greenlow=0 Balance=0`; const replace = `[ColorToning] Lumamode=false Redlow=15 Greenlow=10 Balance=5`; const result = applyFuzzySearchReplace(samplePP3Content, search, replace); expect(result).toContain("Lumamode=false"); expect(result).toContain("Redlow=15"); expect(result).toContain("Greenlow=10"); expect(result).toContain("Balance=5"); // Should preserve other parameters expect(result).toContain("Enabled=false"); expect(result).toContain("Method=LabRegions"); }); it("should fallback to exact match when no section header found", () => { const search = "Auto=false"; const replace = "Auto=true"; const result = applyFuzzySearchReplace(samplePP3Content, search, replace); expect(result).toContain("Auto=true"); }); it("should return original content when section not found", () => { const search = `[NonExistentSection] Param=value`; const replace = `[NonExistentSection] Param=newvalue`; const result = applyFuzzySearchReplace(samplePP3Content, search, replace); expect(result).toBe(samplePP3Content); }); it("should handle parameter count mismatch", () => { const search = `[ColorToning] Lumamode=true Redlow=0`; const replace = `[ColorToning] Lumamode=false`; const result = applyFuzzySearchReplace(samplePP3Content, search, replace); // Should fallback to exact match, which won't find anything expect(result).toBe(samplePP3Content); }); it("should not affect other sections", () => { const search = `[ColorToning] Redlow=0`; const replace = `[ColorToning] Redlow=50`; const result = applyFuzzySearchReplace(samplePP3Content, search, replace); expect(result).toContain("Redlow=50"); // Exposure section should remain unchanged expect(result).toContain("[Exposure]"); expect(result).toContain("Auto=false"); expect(result).toContain("Clip=0.02"); }); }); //# sourceMappingURL=fuzzy-search-replace.test.js.map