/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { describe, it, expect } from 'vitest'; import { countOccurrences, unescapeStringForGeminiBug, } from './editCorrector.js'; describe('editCorrector', () => { describe('countOccurrences', () => { it('should return 0 for empty string', () => { expect(countOccurrences('', 'a')).toBe(0); }); it('should return 0 for empty substring', () => { expect(countOccurrences('abc', '')).toBe(0); }); it('should return 0 if substring is not found', () => { expect(countOccurrences('abc', 'd')).toBe(0); }); it('should return 1 if substring is found once', () => { expect(countOccurrences('abc', 'b')).toBe(1); }); it('should return correct count for multiple occurrences', () => { expect(countOccurrences('ababa', 'a')).toBe(3); expect(countOccurrences('ababab', 'ab')).toBe(3); }); it('should count non-overlapping occurrences', () => { expect(countOccurrences('aaaaa', 'aa')).toBe(2); // Non-overlapping: aa_aa_ expect(countOccurrences('ababab', 'aba')).toBe(1); // Non-overlapping: aba_ab -> 1 }); it('should correctly count occurrences when substring is longer', () => { expect(countOccurrences('abc', 'abcdef')).toBe(0); }); it('should be case sensitive', () => { expect(countOccurrences('abcABC', 'a')).toBe(1); expect(countOccurrences('abcABC', 'A')).toBe(1); }); }); describe('unescapeStringForGeminiBug', () => { it('should unescape common sequences', () => { expect(unescapeStringForGeminiBug('\\n')).toBe('\n'); expect(unescapeStringForGeminiBug('\\t')).toBe('\t'); expect(unescapeStringForGeminiBug("\\'")).toBe("'"); expect(unescapeStringForGeminiBug('\\"')).toBe('"'); expect(unescapeStringForGeminiBug('\\`')).toBe('`'); }); it('should handle multiple escaped sequences', () => { expect(unescapeStringForGeminiBug('Hello\\nWorld\\tTest')).toBe( 'Hello\nWorld\tTest', ); }); it('should not alter already correct sequences', () => { expect(unescapeStringForGeminiBug('\n')).toBe('\n'); expect(unescapeStringForGeminiBug('Correct string')).toBe( 'Correct string', ); }); it('should handle mixed correct and incorrect sequences', () => { expect(unescapeStringForGeminiBug('\\nCorrect\t\\`')).toBe( '\nCorrect\t`', ); }); it('should handle backslash followed by actual newline character', () => { expect(unescapeStringForGeminiBug('\\\n')).toBe('\n'); expect(unescapeStringForGeminiBug('First line\\\nSecond line')).toBe( 'First line\nSecond line', ); }); it('should handle multiple backslashes before an escapable character', () => { expect(unescapeStringForGeminiBug('\\\\n')).toBe('\n'); // \\n -> \n expect(unescapeStringForGeminiBug('\\\\\\t')).toBe('\t'); // \\\t -> \t expect(unescapeStringForGeminiBug('\\\\\\\\`')).toBe('`'); // \\\\` -> ` }); it('should return empty string for empty input', () => { expect(unescapeStringForGeminiBug('')).toBe(''); }); it('should not alter strings with no targeted escape sequences', () => { expect(unescapeStringForGeminiBug('abc def')).toBe('abc def'); // \\F and \\S are not targeted escapes, so they should remain as \\F and \\S expect(unescapeStringForGeminiBug('C:\\Folder\\File')).toBe( 'C:\\Folder\\File', ); }); it('should correctly process strings with some targeted escapes', () => { // \\U is not targeted, \\n is. expect(unescapeStringForGeminiBug('C:\\Users\\name')).toBe( 'C:\\Users\name', ); }); it('should handle complex cases with mixed slashes and characters', () => { expect( unescapeStringForGeminiBug('\\\\\\nLine1\\\nLine2\\tTab\\\\`Tick\\"'), ).toBe('\nLine1\nLine2\tTab`Tick"'); }); }); });