// Regression test for the "no download logic in extension/" ESLint gate // (eslint.config.mjs, answering gui/docs/ext-requests-m1.md). Runs ESLint's Node API // directly against fixture source so a future edit to the rule set can't silently stop // catching the patterns it was written for. import { ESLint } from 'eslint'; import { describe, expect, it } from 'vitest'; async function lint(code: string): Promise { const eslint = new ESLint({ cwd: new URL('../..', import.meta.url).pathname }); // Path only needs to match the `files: ['src/**/*.ts']` glob in eslint.config.mjs. const [result] = await eslint.lintText(code, { filePath: 'src/background/__fixture.ts' }); return result.messages.filter((m) => m.severity === 2).length; } describe('no-download-logic ESLint gate', () => { it('goes red on fetch() + a hand-built Range header + a stream reader', async () => { const errors = await lint(` export async function grabBytes(url: string) { const res = await fetch(url, { headers: { Range: 'bytes=0-1023' } }); const reader = res.body!.getReader(); return reader.read(); } `); expect(errors).toBeGreaterThan(0); }); it('goes red on XMLHttpRequest', async () => { const errors = await lint(`const x = new XMLHttpRequest();`); expect(errors).toBeGreaterThan(0); }); it('stays green on ordinary transport/RPC code', async () => { const errors = await lint(` export function greet(name: string): string { return \`hello \${name}\`; } `); expect(errors).toBe(0); }); });