forked from heavy-duty/stoke
test: cover import-batch result boundaries
This commit is contained in:
parent
1bb4bd608c
commit
5f2f58a249
1 changed files with 102 additions and 9 deletions
|
|
@ -24,27 +24,33 @@ function run(args, env = {}) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
test('repo import-batch continues after one item has no source token', async () => {
|
async function startMigrationServer() {
|
||||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'stoke-import-batch-'));
|
|
||||||
const configFile = path.join(dir, 'config.json');
|
|
||||||
const manifestFile = path.join(dir, 'manifest.json');
|
|
||||||
const emptyPath = path.join(dir, 'bin');
|
|
||||||
const forgeToken = 'forge-token-must-not-be-printed';
|
|
||||||
const requests = [];
|
const requests = [];
|
||||||
const server = http.createServer((req, res) => {
|
const server = http.createServer((req, res) => {
|
||||||
let body = '';
|
let body = '';
|
||||||
req.setEncoding('utf8');
|
req.setEncoding('utf8');
|
||||||
req.on('data', (chunk) => { body += chunk; });
|
req.on('data', (chunk) => { body += chunk; });
|
||||||
req.on('end', () => {
|
req.on('end', () => {
|
||||||
requests.push({ method: req.method, url: req.url, body: JSON.parse(body) });
|
const payload = JSON.parse(body);
|
||||||
|
requests.push({ method: req.method, url: req.url, body: payload });
|
||||||
res.writeHead(201, { 'Content-Type': 'application/json' });
|
res.writeHead(201, { 'Content-Type': 'application/json' });
|
||||||
res.end(JSON.stringify({
|
res.end(JSON.stringify({
|
||||||
full_name: 'destination/imported-second',
|
full_name: `destination/${payload.repo_name}`,
|
||||||
html_url: 'https://forge.test/destination/imported-second',
|
html_url: `https://forge.test/destination/${payload.repo_name}`,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
|
||||||
|
return { server, requests };
|
||||||
|
}
|
||||||
|
|
||||||
|
test('repo import-batch continues after one item has no source token', async () => {
|
||||||
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'stoke-import-batch-'));
|
||||||
|
const configFile = path.join(dir, 'config.json');
|
||||||
|
const manifestFile = path.join(dir, 'manifest.json');
|
||||||
|
const emptyPath = path.join(dir, 'bin');
|
||||||
|
const forgeToken = 'forge-token-must-not-be-printed';
|
||||||
|
const { server, requests } = await startMigrationServer();
|
||||||
fs.mkdirSync(emptyPath);
|
fs.mkdirSync(emptyPath);
|
||||||
fs.writeFileSync(configFile, JSON.stringify({
|
fs.writeFileSync(configFile, JSON.stringify({
|
||||||
url: `http://127.0.0.1:${server.address().port}`,
|
url: `http://127.0.0.1:${server.address().port}`,
|
||||||
|
|
@ -91,3 +97,90 @@ test('repo import-batch continues after one item has no source token', async ()
|
||||||
fs.rmSync(dir, { recursive: true, force: true });
|
fs.rmSync(dir, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('repo import-batch preserves successful batch output', async () => {
|
||||||
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'stoke-import-batch-success-'));
|
||||||
|
const configFile = path.join(dir, 'config.json');
|
||||||
|
const manifestFile = path.join(dir, 'manifest.json');
|
||||||
|
const { server, requests } = await startMigrationServer();
|
||||||
|
fs.writeFileSync(configFile, JSON.stringify({
|
||||||
|
url: `http://127.0.0.1:${server.address().port}`,
|
||||||
|
login: 'destination',
|
||||||
|
token: 'forge-token-must-not-be-printed',
|
||||||
|
}));
|
||||||
|
fs.writeFileSync(manifestFile, JSON.stringify([
|
||||||
|
{ name: 'first', from: 'https://git.example/source/first.git', service: 'git' },
|
||||||
|
{ name: 'second', from: 'https://git.example/source/second.git', service: 'git' },
|
||||||
|
]));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await run(['--config', configFile, 'repo', 'import-batch', '--file', manifestFile]);
|
||||||
|
|
||||||
|
assert.equal(result.status, 0, result.stderr);
|
||||||
|
assert.equal(result.stderr, '');
|
||||||
|
assert.equal(result.stdout,
|
||||||
|
'Imported: destination/first -> https://forge.test/destination/first\n'
|
||||||
|
+ 'Imported: destination/second -> https://forge.test/destination/second\n'
|
||||||
|
+ '\nBatch complete: 2/2 imported.\n');
|
||||||
|
assert.deepEqual(requests.map(({ body }) => body.repo_name), ['first', 'second']);
|
||||||
|
} finally {
|
||||||
|
await new Promise((resolve) => server.close(resolve));
|
||||||
|
fs.rmSync(dir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('repo import-batch keeps file and JSON errors at batch level', async () => {
|
||||||
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'stoke-import-batch-invalid-'));
|
||||||
|
const configFile = path.join(dir, 'config.json');
|
||||||
|
const missingFile = path.join(dir, 'missing.json');
|
||||||
|
const malformedFile = path.join(dir, 'malformed.json');
|
||||||
|
fs.writeFileSync(configFile, JSON.stringify({
|
||||||
|
url: 'https://forge.test',
|
||||||
|
login: 'destination',
|
||||||
|
token: 'forge-token-must-not-be-printed',
|
||||||
|
}));
|
||||||
|
fs.writeFileSync(malformedFile, '{not json');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const missing = await run(['--config', configFile, 'repo', 'import-batch', '--file', missingFile]);
|
||||||
|
const malformed = await run(['--config', configFile, 'repo', 'import-batch', '--file', malformedFile]);
|
||||||
|
|
||||||
|
assert.equal(missing.status, 1);
|
||||||
|
assert.match(missing.stderr, /^Batch import failed: ENOENT:/);
|
||||||
|
assert.equal(missing.stdout, '');
|
||||||
|
assert.equal(malformed.status, 1);
|
||||||
|
assert.match(malformed.stderr, /^Batch import failed: /);
|
||||||
|
assert.match(malformed.stderr, /JSON/);
|
||||||
|
assert.equal(malformed.stdout, '');
|
||||||
|
} finally {
|
||||||
|
fs.rmSync(dir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('repo import-batch excludes skipped invalid entries from the summary', async () => {
|
||||||
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'stoke-import-batch-skip-'));
|
||||||
|
const configFile = path.join(dir, 'config.json');
|
||||||
|
const manifestFile = path.join(dir, 'manifest.json');
|
||||||
|
const { server, requests } = await startMigrationServer();
|
||||||
|
fs.writeFileSync(configFile, JSON.stringify({
|
||||||
|
url: `http://127.0.0.1:${server.address().port}`,
|
||||||
|
login: 'destination',
|
||||||
|
token: 'forge-token-must-not-be-printed',
|
||||||
|
}));
|
||||||
|
fs.writeFileSync(manifestFile, JSON.stringify([
|
||||||
|
{ name: 'missing-source' },
|
||||||
|
{ name: 'valid', from: 'https://git.example/source/valid.git', service: 'git' },
|
||||||
|
]));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await run(['--config', configFile, 'repo', 'import-batch', '--file', manifestFile]);
|
||||||
|
|
||||||
|
assert.equal(result.status, 0, result.stderr);
|
||||||
|
assert.equal(result.stderr, 'Skipping invalid manifest entry: {"name":"missing-source"}\n');
|
||||||
|
assert.match(result.stdout, /Batch complete: 1\/1 imported\./);
|
||||||
|
assert.deepEqual(requests.map(({ body }) => body.repo_name), ['valid']);
|
||||||
|
} finally {
|
||||||
|
await new Promise((resolve) => server.close(resolve));
|
||||||
|
fs.rmSync(dir, { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue