Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:39:37 +08:00

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);
});
});