Files
stack/packages/cli/tests/project-name-repo.test.mjs

67 lines
3.5 KiB
JavaScript

// Row 171: diagnostic file reads stay in fixture config; project creation uses a real broker.
import test from 'node:test';
import assert from 'node:assert/strict';
import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
import { hostDir, hostFile, startTimeOf } from '../src/host.mjs';
import { join } from 'node:path';
import { run } from '../src/cli.mjs';
import { broker, BUSINESSES, fixture, io, tmp } from './helpers.mjs';
function setup(t) {
const root = tmp(t), config = fixture(root, 'demo');
const s = broker(t, { demo: { ...BUSINESSES.demo, projects: { stack: {} } } });
const reads = [];
const transport = business => async (verb, args) => {
reads.push(verb);
if (verb === 'plugins') return { business, revision: 'a'.repeat(64), plugins: { channel: ['cli', 'webui'] } };
return s.transport(business)(verb, args);
};
const cli = async (args, explicit = true) => {
const x = io(config.env);
const code = await run([...args, ...(explicit ? ['--business', 'demo'] : [])], x, { system: { dataRoot: config.dataRoot }, transport });
return { code, out: x.out.text, err: x.err.text };
};
return { ...s, root, config, reads, cli };
}
test('threads project resolution explains a business repository and falls back if its file cannot load', async t => {
const s = setup(t);
const args = ['threads', '--project', 'stack'];
assert.deepEqual(await s.cli(args), {
code: 2, out: '',
err: 'mosaic: "stack" is a repository in the business file, not a thread project yet; mosaic project create stack --repo stack makes one\n',
});
assert.deepEqual(s.reads, ['plugins', 'project.list']);
// A stand-in host state names this test process; no host or unit is started.
mkdirSync(hostDir(s.config.dataRoot), { recursive: true, mode: 0o700 });
writeFileSync(hostFile(s.config.dataRoot), JSON.stringify({ pid: process.pid, startTime: startTimeOf(process.pid), business: 'demo' }), { mode: 0o600 });
s.reads.length = 0;
const implicit = await s.cli(args, false);
assert.equal(implicit.code, 2);
assert.equal(implicit.err, 'mosaic: "stack" is a repository in the business file, not a thread project yet; mosaic project create stack --repo stack makes one\n');
assert.deepEqual(s.reads, ['plugins', 'project.list']);
const existing = setup(t);
assert.equal((await existing.cli(['project', 'create', 'stack', '--repo', 'stack'])).code, 0);
writeFileSync(join(existing.root, 'config/businesses/demo.json'), '{broken json');
assert.deepEqual(await existing.cli(args), { code: 0, out: 'no threads\n', err: '' });
assert.deepEqual(await existing.cli(['threads', '--project', 'other']), {
code: 2, out: '', err: 'mosaic: no project is named or numbered "other"; see mosaic project list\n',
});
s.reads.length = 0;
rmSync(join(s.root, 'config/businesses/demo.json'));
assert.deepEqual(await s.cli(args), {
code: 2, out: '', err: 'mosaic: no project is named or numbered "stack"; see mosaic project list\n',
});
assert.deepEqual(s.reads, ['plugins', 'project.list']);
});
test('project create prints the repository-name refusal and exits two without writing', async t => {
const s = setup(t);
assert.deepEqual(await s.cli(['project', 'create', 'stack']), {
code: 2, out: '',
err: 'mosaic: "stack" is a repository in the business file; add --repo stack to make its thread project, or pick another name\n',
});
assert.deepEqual(s.b.request(s.human, { verb: 'project.list' }), []);
assert.equal((await s.cli(['project', 'create', 'stack', '--repo', 'stack'])).code, 0);
});