719032b19f
Update Schema / Update configuration json schema (push) Has been cancelled
Memory Benchmark / Memory Test (Full Analysis) (push) Has been cancelled
CI Quality / Lint GitHub Actions (actionlint) (push) Has been cancelled
CI Quality / Lint GitHub Actions (zizmor) (push) Has been cancelled
CI Quality / Check typos (push) Has been cancelled
CI / Test coverage (push) Has been cancelled
CI / Test (22.x, windows-latest) (push) Has been cancelled
CI / Test (24.x, macos-latest) (push) Has been cancelled
CI / Test (24.x, ubuntu-latest) (push) Has been cancelled
CI / Test (24.x, windows-latest) (push) Has been cancelled
CI / Test (26.x, macos-latest) (push) Has been cancelled
CI / Test (26.x, ubuntu-latest) (push) Has been cancelled
CI / Test (26.x, windows-latest) (push) Has been cancelled
CI / Test with Bun (latest, macos-latest) (push) Has been cancelled
CI / Test with Bun (latest, ubuntu-latest) (push) Has been cancelled
CI / Test with Bun (latest, windows-latest) (push) Has been cancelled
CI / Build and run (22.x, macos-latest) (push) Has been cancelled
CI / Build and run (22.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (22.x, windows-latest) (push) Has been cancelled
autofix.ci / autofix (push) Has been cancelled
CI Browser Extension / Lint Browser Extension (push) Has been cancelled
CI Browser Extension / Test Browser Extension (push) Has been cancelled
Memory Benchmark / Memory Test (push) Has been cancelled
CI Website / Lint Website Client (push) Has been cancelled
CI Website / Lint Website Server (push) Has been cancelled
CI Website / Test Website Server (push) Has been cancelled
CI Website / Bundle Website Server (push) Has been cancelled
CI / Lint Biome (push) Has been cancelled
CI / Lint oxlint (push) Has been cancelled
CI / Lint TypeScript (push) Has been cancelled
CI / Lint Secretlint (push) Has been cancelled
CI / Test (22.x, macos-latest) (push) Has been cancelled
CI / Test (22.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (24.x, macos-latest) (push) Has been cancelled
CI / Build and run (24.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (24.x, windows-latest) (push) Has been cancelled
CI / Build and run (26.x, macos-latest) (push) Has been cancelled
CI / Build and run (26.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (26.x, windows-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, macos-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, ubuntu-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Docker / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Docker / build (linux/arm/v7, ubuntu-24.04-arm) (push) Has been cancelled
Docker / build (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Docker / merge (push) Has been cancelled
Pack repository with Repomix / pack-repo (push) Has been cancelled
Performance Benchmark History / Benchmark (macos-latest) (push) Has been cancelled
Performance Benchmark History / Benchmark (ubuntu-latest) (push) Has been cancelled
Performance Benchmark History / Benchmark (windows-latest) (push) Has been cancelled
Performance Benchmark History / Store Results (push) Has been cancelled
Test Repomix Action / Test Node.js 22 (push) Has been cancelled
Test Repomix Action / Test Node.js 24 (push) Has been cancelled
Test Repomix Action / Test Node.js 26 (push) Has been cancelled
139 lines
7.0 KiB
TypeScript
139 lines
7.0 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { truncateBase64Content } from '../../../src/core/file/truncateBase64.js';
|
|
|
|
// A realistic long base64 string (344 chars) with digits, upper, lower, and special chars
|
|
const longBase64 =
|
|
'DTJXfKHG6xA1Wn+kye4TOF2Cp8zxFjtgharP9Bk+Y4it0vccQWaLsNX6H0RpjrPY/SJHbJG22wAlSm+Uud4DKE1yl7zhBitQdZq/5AkuU3idwucMMVZ7oMXqDzRZfqPI7RI3XIGmy/AVOl+Eqc7zGD1ih6zR9htAZYqv1PkeQ2iNstf8IUZrkLXa/yRJbpO43QInTHGWu+AFKk90mb7jCC1Sd5zB5gswVXqfxOkOM1h9osfsETZbgKXK7xQ5XoOozfIXPGGGq9D1Gj9kia7T+B1CZ4yx1vsgRWqPtNn+I0htkrfcASZLcJW63wQpTnOYveIHLFF2m8DlCi9UeZ7D6A==';
|
|
|
|
describe('truncateBase64Content', () => {
|
|
it('should truncate data URI base64 strings', () => {
|
|
const input =
|
|
'background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==);';
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe('background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB...);');
|
|
});
|
|
|
|
it('should handle data URIs with charset parameter', () => {
|
|
const input =
|
|
'src="data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMDAiIGhlaWdodD0iMTAwIj48cmVjdCB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgZmlsbD0iIzAwMCIvPjwvc3ZnPg=="';
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe('src="data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53..."');
|
|
});
|
|
|
|
it('should truncate standalone base64 strings longer than 256 chars', () => {
|
|
const input = `const data = "${longBase64}";`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe('const data = "DTJXfKHG6xA1Wn+kye4TOF2Cp8zxFjtg...";');
|
|
});
|
|
|
|
it('should truncate standalone base64 strings at exactly 256 chars', () => {
|
|
// 192 bytes encodes to exactly 256 base64 chars with no padding
|
|
const exact256 =
|
|
'DTJXfKHG6xA1Wn+kye4TOF2Cp8zxFjtgharP9Bk+Y4it0vccQWaLsNX6H0RpjrPY/SJHbJG22wAlSm+Uud4DKE1yl7zhBitQdZq/5AkuU3idwucMMVZ7oMXqDzRZfqPI7RI3XIGmy/AVOl+Eqc7zGD1ih6zR9htAZYqv1PkeQ2iNstf8IUZrkLXa/yRJbpO43QInTHGWu+AFKk90mb7jCC1Sd5zB5gswVXqfxOkOM1h9osfsETZbgKXK7xQ5XoOo';
|
|
const input = `const data = "${exact256}";`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe('const data = "DTJXfKHG6xA1Wn+kye4TOF2Cp8zxFjtg...";');
|
|
});
|
|
|
|
it('should preserve short base64 strings', () => {
|
|
const input = 'const shortData = "SGVsbG8gV29ybGQ=";';
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe(input);
|
|
});
|
|
|
|
it('should not truncate non-base64 strings', () => {
|
|
const input =
|
|
'const longString = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";';
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe(input);
|
|
});
|
|
|
|
it('should not truncate path-like or XPath strings (no digits)', () => {
|
|
// This was the false positive reported in #1298
|
|
const xpath = 'postTransactionAmounts/sharesOwnedFollowingTransaction/value';
|
|
const input = `const path = ".///${xpath}";`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe(input);
|
|
});
|
|
|
|
it('should not truncate long path-like strings without digits', () => {
|
|
// Even if somehow longer than 256 chars, path-like strings without digits should be preserved
|
|
const longPath = 'abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'.repeat(6);
|
|
const input = `const path = "${longPath}";`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe(input);
|
|
});
|
|
|
|
it('should handle multiple base64 occurrences in same content', () => {
|
|
const input = `
|
|
const img1 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";
|
|
const img2 = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/wAALCAABAAEBAREA/8QAFAABAAAAAAAAAAAAAAAAAAAACf/EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAD8AKp//2Q==";
|
|
const data = "${longBase64}";
|
|
`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toContain('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB...');
|
|
expect(result).toContain('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBD...');
|
|
expect(result).toContain('DTJXfKHG6xA1Wn+kye4TOF2Cp8zxFjtg...');
|
|
});
|
|
|
|
it('should handle base64 with whitespace around it', () => {
|
|
const input = `const data = \`\n ${longBase64}\n\`;`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toContain('DTJXfKHG6xA1Wn+kye4TOF2Cp8zxFjtg...');
|
|
});
|
|
|
|
it('should handle base64 strings with padding', () => {
|
|
// longBase64 already ends with '==' padding
|
|
const input = `const paddedData = "${longBase64}";`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe('const paddedData = "DTJXfKHG6xA1Wn+kye4TOF2Cp8zxFjtg...";');
|
|
});
|
|
|
|
it('should produce consistent results on consecutive calls (regex lastIndex safety)', () => {
|
|
const input = `const img = "data:image/png;base64,${longBase64}";`;
|
|
const result1 = truncateBase64Content(input);
|
|
const result2 = truncateBase64Content(input);
|
|
expect(result1).toBe(result2);
|
|
});
|
|
|
|
it('should preserve medium-length base64-like strings under 256 chars', () => {
|
|
// 60-char string that previously would have been truncated
|
|
const mediumString = 'VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4=';
|
|
const input = `const data = "${mediumString}";`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe(input);
|
|
});
|
|
|
|
it('should handle empty input', () => {
|
|
expect(truncateBase64Content('')).toBe('');
|
|
});
|
|
|
|
it('should preserve base64-like runs of exactly 255 chars (just below threshold)', () => {
|
|
// One char below MIN_BASE64_LENGTH_STANDALONE — `hasLongBase64Run` precondition
|
|
// must return false so the regex is skipped and content is untouched.
|
|
const just255 = longBase64.slice(0, 255);
|
|
const input = `const data = "${just255}";`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe(input);
|
|
});
|
|
|
|
it('should preserve content where no single base64 run reaches the threshold', () => {
|
|
// Two 200-char base64-like runs separated by a non-base64 char (`=` is only
|
|
// valid as trailing padding, not inside the run). Neither run hits 256, so
|
|
// the regex must not match and the precondition must reset on the separator.
|
|
const run = longBase64.slice(0, 200);
|
|
const input = `${run} = ${run}`;
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe(input);
|
|
});
|
|
|
|
it('should leave non-base64 data URIs untouched', () => {
|
|
// `data:text/plain,hello` has no `;base64,` literal, so the dataUriPattern
|
|
// cannot match. Verifies the `includes(';base64,')` guard short-circuits
|
|
// correctly without accidentally rewriting plain data URIs.
|
|
const input = 'const url = "data:text/plain;charset=utf-8,Hello%20World";';
|
|
const result = truncateBase64Content(input);
|
|
expect(result).toBe(input);
|
|
});
|
|
});
|