61 lines
3.0 KiB
JavaScript
61 lines
3.0 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert');
|
|
const http = require('node:http');
|
|
const { deleteGiteaPathsBatched } = require('../src/git/apiHandler.js');
|
|
|
|
// Minimaler Gitea-Nachbau: Repo-Info, Trees-API (seitenweise) und Mehrfach-Commit-Endpunkt.
|
|
function fakeGitea(paths, { perPage = 1000, failPath = null } = {}) {
|
|
const files = new Map(paths.map((p, i) => [p, `sha${i}`]));
|
|
const commits = [];
|
|
const server = http.createServer((req, res) => {
|
|
const u = new URL(req.url, 'http://x');
|
|
const send = (code, obj) => { res.statusCode = code; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(obj)); };
|
|
if (req.method === 'GET' && u.pathname === '/api/v1/repos/o/r') return send(200, { default_branch: 'main' });
|
|
if (req.method === 'GET' && u.pathname === '/api/v1/repos/o/r/git/trees/main') {
|
|
const page = Number(u.searchParams.get('page') || 1);
|
|
const all = [...files.keys()].map(p => ({ path: p, type: 'blob', sha: files.get(p) }));
|
|
const slice = all.slice((page - 1) * perPage, page * perPage);
|
|
return send(200, { tree: slice, truncated: page * perPage < all.length, total_count: all.length, page });
|
|
}
|
|
if (req.method === 'POST' && u.pathname === '/api/v1/repos/o/r/contents') {
|
|
let body = '';
|
|
req.on('data', c => body += c);
|
|
req.on('end', () => {
|
|
const { files: ops } = JSON.parse(body);
|
|
if (failPath && ops.some(o => o.path === failPath)) return send(422, { message: 'kaputt' });
|
|
for (const o of ops) {
|
|
assert.strictEqual(o.operation, 'delete');
|
|
assert.strictEqual(o.sha, files.get(o.path));
|
|
files.delete(o.path);
|
|
}
|
|
commits.push(ops.length);
|
|
send(201, {});
|
|
});
|
|
return;
|
|
}
|
|
send(404, { message: 'object does not exist' });
|
|
});
|
|
return new Promise(r => server.listen(0, '127.0.0.1', () => r({ server, files, commits, url: `http://127.0.0.1:${server.address().port}` })));
|
|
}
|
|
|
|
test('Ordner wird paketweise gelöscht, Nachbarn bleiben', async () => {
|
|
const paths = [...Array.from({ length: 2500 }, (_, i) => `mobile/build/f${i}.dex`), 'mobile/build.gradle.kts', 'mobile/src/A.kt'];
|
|
const g = await fakeGitea(paths, { perPage: 1000 });
|
|
try {
|
|
const r = await deleteGiteaPathsBatched({ token: 't', url: g.url, owner: 'o', repo: 'r', prefix: 'mobile/build' });
|
|
assert.strictEqual(r.deleted, 2500);
|
|
assert.deepStrictEqual(g.commits, Array(25).fill(100));
|
|
assert.deepStrictEqual([...g.files.keys()].sort(), ['mobile/build.gradle.kts', 'mobile/src/A.kt']);
|
|
} finally { g.server.close(); }
|
|
});
|
|
|
|
test('eine fehlerhafte Datei blockiert nicht das ganze Paket', async () => {
|
|
const paths = Array.from({ length: 10 }, (_, i) => `x/f${i}`);
|
|
const g = await fakeGitea(paths, { failPath: 'x/f3' });
|
|
try {
|
|
const r = await deleteGiteaPathsBatched({ token: 't', url: g.url, owner: 'o', repo: 'r', paths });
|
|
assert.strictEqual(r.deleted, 9);
|
|
assert.deepStrictEqual(r.failed.map(f => f.path), ['x/f3']);
|
|
} finally { g.server.close(); }
|
|
});
|