'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const test = require('node:test');
const root = path.resolve(__dirname, '..', '..');
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
let fixture;
function phpFixture() {
if (fixture) return fixture;
const result = spawnSync(process.env.PHP_BINARY || 'php', [path.join(__dirname, 'ban-admin-harness.php')], {
cwd: root,
encoding: 'utf8',
});
assert.equal(result.status, 0, result.stderr || result.stdout);
fixture = JSON.parse(result.stdout);
return fixture;
}
function inputValue(html, name) {
const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const match = html.match(new RegExp(`]*name="${escaped}"[^>]*value="([^"]*)"`));
return match ? match[1] : null;
}
test('ban queue merges all records, reports status counts, and clamps pages above 100 rows', () => {
const result = phpFixture();
assert.equal(result.queue.total, 132);
assert.equal(result.queue.page, 2);
assert.equal(result.queue.items, 20);
assert.deepEqual(result.queue.counts, { all: 132, pending: 128, resolved: 2, dismissed: 2 });
assert.equal(result.queue.overlarge_page, 7);
assert.equal(result.queue.overlarge_items, 12);
assert.deepEqual(result.filters, {
type: 'report', status: '', s: 'needle', send_user: 7, orderby: 'updated', order: 'ASC',
});
});
test('real PHP rendering keeps review forms in templates and completed records read-only', () => {
const { html, filtered_html: filteredHtml } = phpFixture();
assert.equal((html.match(/