152 lines
4.6 KiB
TypeScript
152 lines
4.6 KiB
TypeScript
import { mkdtemp, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { describe, expect, it } from "@suaveplan/testing/runner";
|
|
import { checkRoots } from "../../../../../scripts/lint/check-no-hardcoded-strings.js";
|
|
|
|
async function makeTempFile(name: string, body: string): Promise<string> {
|
|
const dir = await mkdtemp(join(tmpdir(), "no-hardcoded-strings-"));
|
|
const file = join(dir, name);
|
|
await writeFile(file, body, "utf8");
|
|
return dir;
|
|
}
|
|
|
|
describe("check-no-hardcoded-strings", () => {
|
|
it(
|
|
"passes a t-wrapped JSX text node",
|
|
{ timeout: 10000 },
|
|
async () => {
|
|
const root = await makeTempFile(
|
|
"ok.tsx",
|
|
`import { useTranslation } from '@suaveplan/react-i18n';
|
|
export function X() {
|
|
const { t } = useTranslation();
|
|
return <button type="button">{t('react-ui.themeToggle.label')}</button>;
|
|
}
|
|
`
|
|
);
|
|
const diagnostics = await checkRoots([{ root }]);
|
|
expect(diagnostics).toEqual([]);
|
|
}
|
|
);
|
|
|
|
it(
|
|
"fails a bare JSX text node",
|
|
{ timeout: 10000 },
|
|
async () => {
|
|
const root = await makeTempFile(
|
|
"bad.tsx",
|
|
`export function X() {
|
|
return <button type="button">Close</button>;
|
|
}
|
|
`
|
|
);
|
|
const diagnostics = await checkRoots([{ root }]);
|
|
expect(diagnostics.length).toBeGreaterThanOrEqual(1);
|
|
expect(diagnostics[0]?.rule).toBe("jsx-text");
|
|
expect(diagnostics[0]?.snippet).toBe("Close");
|
|
}
|
|
);
|
|
|
|
it(
|
|
"fails a string literal aria-label",
|
|
{ timeout: 10000 },
|
|
async () => {
|
|
const root = await makeTempFile(
|
|
"aria.tsx",
|
|
`export function X() {
|
|
return <button type="button" aria-label="Close" />;
|
|
}
|
|
`
|
|
);
|
|
const diagnostics = await checkRoots([{ root }]);
|
|
expect(diagnostics.length).toBeGreaterThanOrEqual(1);
|
|
expect(diagnostics[0]?.rule).toBe("jsx-attr-aria-label");
|
|
}
|
|
);
|
|
|
|
it(
|
|
"fails an object-literal label string",
|
|
{ timeout: 10000 },
|
|
async () => {
|
|
const root = await makeTempFile(
|
|
"obj.ts",
|
|
`export const fields = { email: { label: 'Email' } };
|
|
`
|
|
);
|
|
const diagnostics = await checkRoots([{ root }]);
|
|
expect(diagnostics.length).toBeGreaterThanOrEqual(1);
|
|
expect(diagnostics[0]?.rule).toBe("object-label");
|
|
}
|
|
);
|
|
|
|
it(
|
|
"fails a JSX expression string-literal child",
|
|
{ timeout: 10000 },
|
|
async () => {
|
|
const root = await makeTempFile(
|
|
"literal.tsx",
|
|
`export function X() {
|
|
return <span>{'hardcoded'}</span>;
|
|
}
|
|
`
|
|
);
|
|
const diagnostics = await checkRoots([{ root }]);
|
|
expect(diagnostics.length).toBeGreaterThanOrEqual(1);
|
|
}
|
|
);
|
|
|
|
it(
|
|
"fails a string-literal placeholder attribute",
|
|
{ timeout: 10000 },
|
|
async () => {
|
|
const root = await makeTempFile(
|
|
"placeholder.tsx",
|
|
`export function X() {
|
|
return <input type="text" placeholder="Email address" />;
|
|
}
|
|
`
|
|
);
|
|
const diagnostics = await checkRoots([{ root }]);
|
|
expect(diagnostics.length).toBeGreaterThanOrEqual(1);
|
|
expect(diagnostics[0]?.rule).toBe("jsx-attr-placeholder");
|
|
}
|
|
);
|
|
|
|
it(
|
|
"skips test/spec/stories files via the skip suffix list",
|
|
{ timeout: 10000 },
|
|
async () => {
|
|
const root = await makeTempFile(
|
|
"thing.test.tsx",
|
|
`export function X() {
|
|
return <button type="button">hardcoded but exempt</button>;
|
|
}
|
|
`
|
|
);
|
|
const diagnostics = await checkRoots([{ root }]);
|
|
expect(diagnostics).toEqual([]);
|
|
}
|
|
);
|
|
|
|
it(
|
|
"skips spike directories",
|
|
{ timeout: 10000 },
|
|
async () => {
|
|
const dir = await mkdtemp(join(tmpdir(), "spike-skip-"));
|
|
const spikeDir = join(dir, "spike");
|
|
const fs = await import("node:fs/promises");
|
|
await fs.mkdir(spikeDir, { recursive: true });
|
|
await fs.writeFile(
|
|
join(spikeDir, "x.tsx"),
|
|
`export function X() {
|
|
return <button type="button">spike literal</button>;
|
|
}
|
|
`
|
|
);
|
|
const diagnostics = await checkRoots([{ root: dir }]);
|
|
expect(diagnostics).toEqual([]);
|
|
}
|
|
);
|
|
});
|