chore: enforce scoped formatting and browser package boundaries

This commit is contained in:
Sameh Khamis committed 2026-09-11 16:06:35 -07:00
1 parent ef69f01cd8
commit 76ddc6a9ef
15 files changed
+547 -22

No files matched your search

+95
View File
@@ -0,0 +1,95 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import {
mkdtemp,
mkdir,
writeFile,
readFile,
rm,
symlink,
} from 'node:fs/promises';
import { tmpdir } from 'node:os';
import path from 'node:path';
import { formatAdoptedFiles } from '../../scripts/format.mjs';
async function fixture(t, scope = ['adopted.js']) {
const root = await mkdtemp(path.join(tmpdir(), 'gev-format-'));
t.after(() => rm(root, { recursive: true, force: true }));
await mkdir(path.join(root, 'scripts'));
await writeFile(
path.join(root, 'scripts/format-scope.json'),
JSON.stringify(scope),
);
await writeFile(
path.join(root, '.prettierrc.json'),
JSON.stringify({
singleQuote: true,
semi: true,
tabWidth: 2,
endOfLine: 'lf',
}),
);
await writeFile(path.join(root, '.prettierignore'), 'ignored.js\n');
await writeFile(path.join(root, 'adopted.js'), 'const value="yes"\r\n');
return root;
}
test('format check is read-only; write only changes adopted files and is repeatable', async (t) => {
const root = await fixture(t);
const outside = 'const untouched="yes"';
await writeFile(path.join(root, 'legacy.js'), outside);
assert.deepEqual((await formatAdoptedFiles(root, '--check')).changed, [
'adopted.js',
]);
assert.equal(
await readFile(path.join(root, 'adopted.js'), 'utf8'),
'const value="yes"\r\n',
);
await formatAdoptedFiles(root, '--write');
assert.equal(
await readFile(path.join(root, 'adopted.js'), 'utf8'),
"const value = 'yes';\n",
);
assert.equal(await readFile(path.join(root, 'legacy.js'), 'utf8'), outside);
assert.deepEqual((await formatAdoptedFiles(root, '--check')).changed, []);
assert.deepEqual((await formatAdoptedFiles(root, '--write')).changed, []);
});
test('invalid, ignored and missing scope entries fail before any file is written', async (t) => {
for (const scope of [
[],
['adopted.js', 'adopted.js'],
['adopted.js', '../escape.js'],
['adopted.js', 'ignored.js'],
['adopted.js', 'missing.js'],
]) {
const root = await fixture(t, scope);
await writeFile(path.join(root, 'ignored.js'), 'const ignored=1');
await assert.rejects(formatAdoptedFiles(root, '--write'));
assert.equal(
await readFile(path.join(root, 'adopted.js'), 'utf8'),
'const value="yes"\r\n',
);
}
});
test(
'formatting rejects a symlink outside the repository',
{ skip: process.platform === 'win32' },
async (t) => {
const root = await fixture(t, ['adopted.js', 'outside.js']);
const other = await fixture(t);
await symlink(
path.join(other, 'adopted.js'),
path.join(root, 'outside.js'),
);
await assert.rejects(
formatAdoptedFiles(root, '--write'),
/repository files/,
);
assert.equal(
await readFile(path.join(root, 'adopted.js'), 'utf8'),
'const value="yes"\r\n',
);
},
);
+77
View File
@@ -0,0 +1,77 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import { mkdtemp, mkdir, writeFile, rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import path from 'node:path';
import { checkPackageBoundaries } from '../../scripts/check-package-boundaries.mjs';
async function fixture(
t,
entry = 'export const value = 1;',
extraExports = {},
) {
const root = await mkdtemp(path.join(tmpdir(), 'gev-boundaries-'));
t.after(() => rm(root, { recursive: true, force: true }));
await mkdir(path.join(root, 'scripts'));
await writeFile(
path.join(root, 'package.json'),
JSON.stringify({
name: 'boundary-fixture',
type: 'module',
exports: { './feature': './entry.js', ...extraExports },
}),
);
await writeFile(
path.join(root, 'scripts/package-boundaries.json'),
JSON.stringify({
feature: { exports: ['./feature'], modules: ['entry.js'], external: [] },
}),
);
await writeFile(path.join(root, 'entry.js'), entry);
return root;
}
test('a declared browser export builds without running app setup', async (t) => {
const root = await fixture(t);
await writeFile(
path.join(root, 'vite.config.js'),
"throw new Error('must not load app config');",
);
assert.deepEqual(await checkPackageBoundaries(root), [
{ name: 'feature', exports: 1, modules: 1 },
]);
});
test('an unclassified package export fails the boundary gate', async (t) => {
const root = await fixture(t, undefined, { './another': './another.js' });
await assert.rejects(
checkPackageBoundaries(root),
/exactly one boundary group/,
);
});
test('even an unused import of application code violates ownership', async (t) => {
const root = await fixture(
t,
"import { app } from './startup.js'; export const value = 1;",
);
await writeFile(path.join(root, 'startup.js'), 'export const app = 2;');
await assert.rejects(checkPackageBoundaries(root), /unowned module.*startup/);
});
test('Node builtins cannot enter a browser export', async (t) => {
const root = await fixture(
t,
"import fs from 'node:fs'; export const value = fs;",
);
await assert.rejects(checkPackageBoundaries(root), /unowned module|browser/);
});
test('dynamic imports obey the same component ownership rule', async (t) => {
const root = await fixture(
t,
"export const load = () => import('./startup.js');",
);
await writeFile(path.join(root, 'startup.js'), 'export const app = 2;');
await assert.rejects(checkPackageBoundaries(root), /unowned module.*startup/);
});