mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-24 07:53:09 +00:00
build(scripts): server ratchets share one baseline library at the repository root
scripts/lib/ratchet.mjs carries the tree walk, the CRLF-safe reader and the baseline handling the client ratchets already use, next to a warning tally and a format comparison that take ESLint and Prettier from the calling workspace. server lint:size now runs on it with the same messages and exit codes, and the libraries have node:test suites that CI runs in the server job.
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { afterEach, describe, it } from 'node:test';
|
||||
import * as prettier from 'prettier';
|
||||
import { check, isFormatted } from './format.mjs';
|
||||
import { RatchetError } from './ratchet.mjs';
|
||||
import { ratchetTree } from './tree-fixture.mjs';
|
||||
|
||||
let tree;
|
||||
afterEach(() => tree?.remove());
|
||||
|
||||
const BASELINE = 'scripts/format-baseline.json';
|
||||
const CONFIG = { '.prettierrc': JSON.stringify({ semi: true, singleQuote: true, endOfLine: 'lf' }) };
|
||||
const FORMATTED = "const a = 'x';\n";
|
||||
const UNFORMATTED = 'const a = "x"\n';
|
||||
const DIRS = ['src', 'tests'];
|
||||
const accepts = (key) => key.endsWith('.ts');
|
||||
|
||||
function run(baseline, files, update = false, list = false) {
|
||||
tree = ratchetTree({
|
||||
...CONFIG,
|
||||
[BASELINE]: JSON.stringify(baseline),
|
||||
'src/keep.ts': FORMATTED,
|
||||
'tests/keep.ts': FORMATTED,
|
||||
...files,
|
||||
});
|
||||
return check({ prettier, root: tree.root, dirs: DIRS, accepts, baselinePath: tree.path(BASELINE), update, list, ...tree.out });
|
||||
}
|
||||
|
||||
describe('scripts/lib/format', () => {
|
||||
it('tells formatted from unformatted files, and reads CRLF as LF', async () => {
|
||||
tree = ratchetTree({
|
||||
...CONFIG,
|
||||
'a.ts': FORMATTED,
|
||||
'b.ts': UNFORMATTED,
|
||||
'c.ts': "const a = 'x';\r\n",
|
||||
'd.ts': 'const (',
|
||||
});
|
||||
assert.equal(await isFormatted(prettier, tree.path('a.ts')), true);
|
||||
assert.equal(await isFormatted(prettier, tree.path('b.ts')), false);
|
||||
assert.equal(await isFormatted(prettier, tree.path('c.ts')), true);
|
||||
assert.equal(await isFormatted(prettier, tree.path('d.ts')), false);
|
||||
});
|
||||
|
||||
it('passes when every unformatted file is listed, and --list names each one', async () => {
|
||||
assert.equal(await run(['src/old.ts'], { 'src/old.ts': UNFORMATTED, 'src/new.ts': FORMATTED }, false, true), 0);
|
||||
assert.deepEqual(tree.error, []);
|
||||
assert.ok(tree.log.includes('listed src/old.ts'));
|
||||
});
|
||||
|
||||
it('fails a new file that is not formatted, and leaves files it does not accept alone', async () => {
|
||||
assert.equal(await run([], { 'tests/new.ts': UNFORMATTED, 'src/data.json': '{"a":1}' }), 1);
|
||||
const out = tree.error.join('\n');
|
||||
assert.match(out, /tests\/new\.ts is not formatted\. Run: npx prettier --write tests\/new\.ts/);
|
||||
assert.doesNotMatch(out, /data\.json/);
|
||||
});
|
||||
|
||||
it('fails a listed file that is formatted now or gone, until --update takes it off', async () => {
|
||||
assert.equal(await run(['src/done.ts', 'src/gone.ts'], { 'src/done.ts': FORMATTED }), 1);
|
||||
const out = tree.error.join('\n');
|
||||
assert.match(out, /src\/done\.ts is listed .* formatted now or gone/);
|
||||
assert.match(out, /src\/gone\.ts is listed/);
|
||||
assert.match(out, /npm run lint:format -- --update/);
|
||||
tree.remove();
|
||||
assert.equal(await run(['src/done.ts', 'src/old.ts'], { 'src/done.ts': FORMATTED, 'src/old.ts': UNFORMATTED }, true), 0);
|
||||
assert.deepEqual(JSON.parse(readFileSync(tree.path(BASELINE), 'utf8')), ['src/old.ts']);
|
||||
});
|
||||
|
||||
it('never puts a file on the list with --update', async () => {
|
||||
assert.equal(await run([], { 'src/new.ts': UNFORMATTED }, true), 1);
|
||||
assert.deepEqual(JSON.parse(readFileSync(tree.path(BASELINE), 'utf8')), []);
|
||||
});
|
||||
|
||||
it('stops on a missing baseline or a missing Prettier config', async () => {
|
||||
tree = ratchetTree({ ...CONFIG, 'src/a.ts': FORMATTED, 'tests/a.ts': FORMATTED });
|
||||
await assert.rejects(
|
||||
check({ prettier, root: tree.root, dirs: DIRS, accepts, baselinePath: tree.path(BASELINE), ...tree.out }),
|
||||
RatchetError,
|
||||
);
|
||||
tree.remove();
|
||||
tree = ratchetTree({ [BASELINE]: '[]', 'src/a.ts': FORMATTED, 'tests/a.ts': FORMATTED });
|
||||
const stub = { resolveConfig: async () => null, check: async () => true };
|
||||
await assert.rejects(
|
||||
check({ prettier: stub, root: tree.root, dirs: DIRS, accepts, baselinePath: tree.path(BASELINE), ...tree.out }),
|
||||
/no Prettier config/,
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user