From 050f311a604a0026d98920261a506c8b4d686332 Mon Sep 17 00:00:00 2001 From: gnezim Date: Tue, 14 Apr 2026 23:07:18 +0300 Subject: [PATCH] Add fabricated violation tests for restricted import rules --- tests/eslint/restricted-imports.test.ts | 80 +++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tests/eslint/restricted-imports.test.ts diff --git a/tests/eslint/restricted-imports.test.ts b/tests/eslint/restricted-imports.test.ts new file mode 100644 index 00000000..84f2db54 --- /dev/null +++ b/tests/eslint/restricted-imports.test.ts @@ -0,0 +1,80 @@ +import { describe, expect, it } from "vitest"; +import { execSync } from "node:child_process"; +import fs from "node:fs"; +import path from "node:path"; +import crypto from "node:crypto"; + +const ROOT = path.resolve(import.meta.dirname, "../.."); + +/** Short random suffix to avoid collisions when tests run in parallel. */ +function uid(): string { + return crypto.randomBytes(4).toString("hex"); +} + +function lintString(filePath: string, content: string): string { + const absPath = path.join(ROOT, filePath); + fs.mkdirSync(path.dirname(absPath), { recursive: true }); + fs.writeFileSync(absPath, content, "utf8"); + try { + execSync(`pnpm exec eslint "${absPath}" --format json`, { + cwd: ROOT, + encoding: "utf8", + stdio: ["pipe", "pipe", "pipe"], + }); + return "PASS"; + } catch (err: unknown) { + const error = err as { stdout?: string }; + return error.stdout ?? "UNKNOWN_ERROR"; + } finally { + fs.unlinkSync(absPath); + // Remove empty parent directories created for probes + let dir = path.dirname(absPath); + const srcDir = path.join(ROOT, "src"); + while (dir.length > srcDir.length) { + try { + fs.rmdirSync(dir); + } catch { + break; + } + dir = path.dirname(dir); + } + } +} + +describe("no-restricted-imports rules", () => { + it("blocks @opentelemetry/sdk-metrics outside otel.ts", () => { + const id = uid(); + const result = lintString( + `src/features/online-board/__ri_probe_${id}__.ts`, + 'import { MeterProvider } from "@opentelemetry/sdk-metrics";\nexport const x = MeterProvider;\n', + ); + expect(result).toContain("no-restricted-imports"); + }); + + it("blocks react-i18next outside provider.tsx", () => { + const id = uid(); + const result = lintString( + `src/features/online-board/__ri_probe_${id}__.ts`, + 'import { useTranslation } from "react-i18next";\nexport const x = useTranslation;\n', + ); + expect(result).toContain("no-restricted-imports"); + }); + + it("blocks @microsoft/signalr in routes/ (SSR bundle)", () => { + const id = uid(); + const result = lintString( + `src/routes/__probe_${id}__/__ri_probe__.ts`, + 'import { HubConnectionBuilder } from "@microsoft/signalr";\nexport const x = HubConnectionBuilder;\n', + ); + expect(result).toContain("no-restricted-imports"); + }); + + it("blocks localStorage outside storage.ts", () => { + const id = uid(); + const result = lintString( + `src/features/online-board/__ri_probe_${id}__.ts`, + 'const x = localStorage.getItem("key");\nexport default x;\n', + ); + expect(result).toContain("no-restricted-globals"); + }); +});