mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 18:34:02 +00:00
186 lines
5.5 KiB
JavaScript
186 lines
5.5 KiB
JavaScript
import test from 'node:test';
|
|
import { execFileSync } from 'node:child_process';
|
|
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',
|
|
);
|
|
},
|
|
);
|
|
|
|
test('runtime discovery includes new nested modules and respects Git and formatter exclusions', async (t) => {
|
|
const root = await fixture(t);
|
|
execFileSync('git', ['init', '-q'], { cwd: root });
|
|
await mkdir(path.join(root, 'src/nested'), { recursive: true });
|
|
await mkdir(path.join(root, 'vendor'), { recursive: true });
|
|
await writeFile(
|
|
path.join(root, 'scripts/format-runtime.json'),
|
|
JSON.stringify({ roots: ['src'] }),
|
|
);
|
|
await writeFile(path.join(root, '.gitignore'), 'src/ignored.js\n');
|
|
await writeFile(path.join(root, '.prettierignore'), 'src/generated.js\n');
|
|
const source = 'export const value="yes"';
|
|
for (const name of [
|
|
'src/nested/new.js',
|
|
'src/module.mjs',
|
|
'src/check.test.mjs',
|
|
'src/ignored.js',
|
|
'src/generated.js',
|
|
'vendor/other.js',
|
|
])
|
|
await writeFile(path.join(root, name), source);
|
|
const expected = ['adopted.js', 'src/module.mjs', 'src/nested/new.js'];
|
|
assert.deepEqual(
|
|
(await formatAdoptedFiles(root, '--check')).changed,
|
|
expected,
|
|
);
|
|
await formatAdoptedFiles(root, '--write');
|
|
assert.deepEqual((await formatAdoptedFiles(root, '--check')).changed, []);
|
|
for (const name of [
|
|
'src/check.test.mjs',
|
|
'src/ignored.js',
|
|
'src/generated.js',
|
|
'vendor/other.js',
|
|
])
|
|
assert.equal(await readFile(path.join(root, name), 'utf8'), source);
|
|
});
|
|
|
|
test('runtime scope rejects unsafe roots before formatting existing entries', async (t) => {
|
|
for (const roots of [
|
|
[],
|
|
['src', 'src'],
|
|
['../outside'],
|
|
['/absolute'],
|
|
['.'],
|
|
['src/*'],
|
|
]) {
|
|
const root = await fixture(t);
|
|
await writeFile(
|
|
path.join(root, 'scripts/format-runtime.json'),
|
|
JSON.stringify({ roots }),
|
|
);
|
|
await assert.rejects(
|
|
formatAdoptedFiles(root, '--write'),
|
|
/Runtime formatting roots/,
|
|
);
|
|
assert.equal(
|
|
await readFile(path.join(root, 'adopted.js'), 'utf8'),
|
|
'const value="yes"\r\n',
|
|
);
|
|
}
|
|
});
|
|
|
|
test(
|
|
'discovered runtime symlinks cannot escape the repository',
|
|
{ skip: process.platform === 'win32' },
|
|
async (t) => {
|
|
const root = await fixture(t);
|
|
const other = await fixture(t);
|
|
execFileSync('git', ['init', '-q'], { cwd: root });
|
|
await mkdir(path.join(root, 'src'));
|
|
await writeFile(
|
|
path.join(root, 'scripts/format-runtime.json'),
|
|
JSON.stringify({ roots: ['src'] }),
|
|
);
|
|
await symlink(
|
|
path.join(other, 'adopted.js'),
|
|
path.join(root, 'src/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',
|
|
);
|
|
},
|
|
);
|