const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const root = path.resolve(__dirname, '..', '..'); const read = (rel) => fs.readFileSync(path.join(root, rel), 'utf8'); test('upload marks pending and returns attachment id', () => { const controller = read('src/Admin/UserController.php'); assert.match(controller, /PendingUploads::mark\(\(int\) \$attachment_id\)/); assert.match(controller, /'id'\s*=> \(int\) \$attachment_id/); }); test('pending lifecycle: discard route, owner check, claim, cron cleanup', () => { const svc = read('src/Attachment/PendingUploads.php'); assert.match(svc, /'\/upload\/pending\/\(\?P\\d\+\)'/); assert.match(svc, /'methods'\s*=> 'DELETE'/); assert.match(svc, /'permission_callback'/); assert.match(svc, /post_author === \$user_id/); assert.match(svc, /wp_schedule_event\(time\(\) \+ HOUR_IN_SECONDS, 'hourly', self::CRON_HOOK\)/); assert.match(svc, /\$wpdb->prepare\(/); assert.match(svc, /add_action\('comment_post', \[\$this, 'claim_comment'\]/); assert.match(read('functions.php'), /PendingUploads::get_instance\(\)->init\(\)/); }); test('submit paths claim referenced uploads', () => { const rest = read('src/Ticket/TicketRest.php'); const admin = read('src/Ticket/TicketRestAdmin.php'); const report = read('src/Admin/UserControllerReportOperations.php'); assert.equal((rest.match(/PendingUploads::claim_urls\(\$attachment/g) || []).length, 2); assert.equal((admin.match(/PendingUploads::claim_urls\(\$attachment/g) || []).length, 2); assert.match(report, /PendingUploads::claim_text\(\$reason, \$reporter_id\)/); }); test('front-end remove buttons discard the pending upload', () => { const core = read('assets/js/ticket-center-core.js'); const report = read('assets/js/report.js'); assert.match(core, /'\/upload\/pending\/' \+ id/); assert.match(core, /data-aksrt-ticket-image-id/); assert.match(report, /'\/upload\/pending\/'/); });