Files
jackwener__opencli/src/interceptor.test.ts
jackwener 61ea05bff7 fix: URL injection, strictNullChecks, cross-platform build, +34 tests
Security:
- Fix URL injection in fetch.ts and bilibili.ts (JSON.stringify instead of string interpolation)
- Fix unused scroll() amount parameter

TypeScript:
- Enable strictNullChecks in tsconfig
- Change CliCommand.func signature to IPage (non-null) for browser adapters
- Fix 93 compile errors across all adapters

Build:
- Remove || true from build-manifest (report failures instead of silencing)
- Replace Unix shell commands with Node.js scripts for cross-platform builds

Code quality:
- Remove error-object special detection from pipeline executor
- Unify error handling to throw pattern

Tests:
- New interceptor.test.ts (11 tests)
- New executor.test.ts (13 tests)
- Rewrite output.test.ts with comprehensive coverage (10 tests)
2026-03-16 18:14:27 +08:00

95 lines
3.3 KiB
TypeScript

/**
* Tests for interceptor.ts: JavaScript code generators for XHR/Fetch interception.
*/
import { describe, it, expect } from 'vitest';
import { generateInterceptorJs, generateReadInterceptedJs, generateTapInterceptorJs } from './interceptor.js';
describe('generateInterceptorJs', () => {
it('generates valid JavaScript function source', () => {
const js = generateInterceptorJs('"api/search"');
expect(js).toContain('window.fetch');
expect(js).toContain('XMLHttpRequest');
expect(js).toContain('"api/search"');
// Should be a function expression wrapping
expect(js.trim()).toMatch(/^\(\)\s*=>/);
});
it('uses default array name and patch guard', () => {
const js = generateInterceptorJs('"test"');
expect(js).toContain('__opencli_intercepted');
expect(js).toContain('__opencli_interceptor_patched');
});
it('uses custom array name and patch guard', () => {
const js = generateInterceptorJs('"test"', {
arrayName: '__my_data',
patchGuard: '__my_guard',
});
expect(js).toContain('__my_data');
expect(js).toContain('__my_guard');
expect(js).not.toContain('__opencli_intercepted');
});
it('includes fetch clone and json parsing', () => {
const js = generateInterceptorJs('"api"');
expect(js).toContain('response.clone()');
expect(js).toContain('clone.json()');
});
it('includes XHR open and send patching', () => {
const js = generateInterceptorJs('"api"');
expect(js).toContain('XMLHttpRequest.prototype');
expect(js).toContain('__origOpen');
expect(js).toContain('__origSend');
});
});
describe('generateReadInterceptedJs', () => {
it('generates valid JavaScript to read and clear data', () => {
const js = generateReadInterceptedJs();
expect(js).toContain('__opencli_intercepted');
// Should clear the array after reading
expect(js).toContain('= []');
});
it('uses custom array name', () => {
const js = generateReadInterceptedJs('__custom_arr');
expect(js).toContain('__custom_arr');
expect(js).not.toContain('__opencli_intercepted');
});
});
describe('generateTapInterceptorJs', () => {
it('returns all required fields', () => {
const tap = generateTapInterceptorJs('"api/data"');
expect(tap.setupVar).toBeDefined();
expect(tap.capturedVar).toBe('captured');
expect(tap.promiseVar).toBe('capturePromise');
expect(tap.resolveVar).toBe('captureResolve');
expect(tap.fetchPatch).toBeDefined();
expect(tap.xhrPatch).toBeDefined();
expect(tap.restorePatch).toBeDefined();
});
it('contains the capture pattern in setup', () => {
const tap = generateTapInterceptorJs('"my-pattern"');
expect(tap.setupVar).toContain('"my-pattern"');
});
it('restores original fetch and XHR in restorePatch', () => {
const tap = generateTapInterceptorJs('"test"');
expect(tap.restorePatch).toContain('origFetch');
expect(tap.restorePatch).toContain('origXhrOpen');
expect(tap.restorePatch).toContain('origXhrSend');
});
it('uses first-match capture (only first response)', () => {
const tap = generateTapInterceptorJs('"test"');
// Both fetch and xhr patches should check !captured before storing
expect(tap.fetchPatch).toContain('!captured');
expect(tap.xhrPatch).toContain('!captured');
});
});