scripts/guard-review-artifacts-ignored.test.mjs
scripts/guard-review-artifacts-ignored.test.mjsBrowse 11 files
1,271 tokens
4,730 bytes
Token encoding: o200k_base
Snapshot fac8604
← Back to SKILL.md
1import { spawnSync } from 'node:child_process';2import { mkdirSync, mkdtempDisposableSync, realpathSync, symlinkSync, writeFileSync } from 'node:fs';3import { tmpdir } from 'node:os';4import { delimiter, dirname, join } from 'node:path';5import { after, before, describe, it } from 'node:test';6import assert from 'node:assert/strict';7import { fileURLToPath } from 'node:url';8 9const guardPath = join(dirname(fileURLToPath(import.meta.url)), 'guard-review-artifacts-ignored.mjs');10 11const FAKE_JJ_SCRIPT = `#!/bin/sh12case "$*" in13 "workspace root --ignore-working-copy") ;;14 *) echo "fake jj: unexpected args: $*" >&2; exit 2 ;;15esac16if [ -z "$FAKE_JJ_WORKSPACE_ROOT" ]; then17 echo 'Error: There is no jj repo in "."' >&218 exit 119fi20printf '%s\\n' "$FAKE_JJ_WORKSPACE_ROOT"21`;22 23let tempRoot;24let workspaceRoot;25let outsideRoot;26let fakeWorkspaceRoot;27let wipLinkWorkspaceRoot;28let fakeJjBinDir;29 30function runGuard(dir, { jjRoot = workspaceRoot, cwd = workspaceRoot } = {}) {31 return spawnSync(process.execPath, [guardPath, '--dir', dir], {32 cwd,33 encoding: 'utf8',34 env: {35 ...process.env,36 PATH: `${fakeJjBinDir}${delimiter}${process.env.PATH}`,37 FAKE_JJ_WORKSPACE_ROOT: jjRoot ?? '',38 },39 });40}41 42describe('guard-review-artifacts-ignored in a jj workspace without git', () => {43 before(() => {44 tempRoot = mkdtempDisposableSync(join(tmpdir(), 'guard-review-'));45 const base = realpathSync(tempRoot.path);46 workspaceRoot = join(base, 'workspace');47 outsideRoot = join(base, 'outside');48 fakeWorkspaceRoot = join(base, 'fake-workspace');49 fakeJjBinDir = join(base, 'bin');50 wipLinkWorkspaceRoot = join(base, 'wip-link-workspace');51 mkdirSync(join(workspaceRoot, 'wip', 'reviews', 'x'), { recursive: true });52 mkdirSync(join(workspaceRoot, 'docs'), { recursive: true });53 mkdirSync(join(outsideRoot, 'reviews'), { recursive: true });54 mkdirSync(join(fakeWorkspaceRoot, '.jj'), { recursive: true });55 mkdirSync(join(fakeWorkspaceRoot, 'wip', 'reviews'), { recursive: true });56 mkdirSync(join(wipLinkWorkspaceRoot, 'docs', 'reviews'), { recursive: true });57 mkdirSync(fakeJjBinDir, { recursive: true });58 writeFileSync(join(fakeJjBinDir, 'jj'), FAKE_JJ_SCRIPT, { mode: 0o755 });59 symlinkSync(outsideRoot, join(workspaceRoot, 'wip', 'escape'), 'dir');60 symlinkSync(join(base, 'nonexistent'), join(workspaceRoot, 'wip', 'dangling'), 'dir');61 symlinkSync(join(wipLinkWorkspaceRoot, 'docs'), join(wipLinkWorkspaceRoot, 'wip'), 'dir');62 });63 64 after(() => {65 tempRoot.remove();66 });67 68 it('accepts a directory under the ignored wip/ tree', () => {69 const result = runGuard(join(workspaceRoot, 'wip', 'reviews', 'x'));70 assert.equal(result.status, 0, result.stderr);71 assert.match(result.stdout, /ok: review artifacts are under the ignored wip\/ tree/);72 });73 74 it('rejects a directory outside the wip/ tree', () => {75 const result = runGuard(join(workspaceRoot, 'docs'));76 assert.equal(result.status, 1);77 assert.match(result.stderr, /must live under the ignored wip\/ tree/);78 });79 80 it('rejects a path that a symlink under wip/ points outside the workspace', () => {81 const result = runGuard(join(workspaceRoot, 'wip', 'escape', 'reviews'));82 assert.equal(result.status, 1);83 assert.match(result.stderr, /outside/);84 });85 86 it('rejects a path through a dangling symlink under wip/', () => {87 const result = runGuard(join(workspaceRoot, 'wip', 'dangling', 'reviews'));88 assert.equal(result.status, 1);89 assert.match(result.stderr, /ENOENT/);90 });91 92 it('rejects an artifact dir when wip itself is a symlink to a non-ignored directory', () => {93 const result = runGuard(join(wipLinkWorkspaceRoot, 'wip', 'reviews'), {94 jjRoot: wipLinkWorkspaceRoot,95 cwd: wipLinkWorkspaceRoot,96 });97 assert.equal(result.status, 1);98 assert.match(result.stderr, /must live under the ignored wip\/ tree/);99 });100 101 it('fails with ENOENT for a missing output path', () => {102 const result = runGuard(join(workspaceRoot, 'wip', 'reviews', 'missing'));103 assert.equal(result.status, 1);104 assert.match(result.stderr, /ENOENT/);105 });106 107 it('rejects a directory under another workspace marked only by a .jj directory', () => {108 const result = runGuard(join(fakeWorkspaceRoot, 'wip', 'reviews'));109 assert.equal(result.status, 1);110 assert.match(result.stderr, /must stay inside the workspace/);111 });112 113 it('fails when jj reports no workspace for the working directory', () => {114 const result = runGuard(join(workspaceRoot, 'wip', 'reviews', 'x'), { jjRoot: null });115 assert.equal(result.status, 1);116 assert.match(result.stderr, /not in a git repository or a jj workspace/);117 });118});119