Files
Git-Manager-Gui/__tests__/delete.test.js
T
2026-10-22 06:53:45 +00:00

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(); }
});