const assert = require('node:assert/strict'); const fs = require('node:fs'); const vm = require('node:vm'); const test = require('node:test'); function setup(conversationID = '') { const fields = ['conversation-id', 'title', 'description', 'severity', 'type', 'target', 'reproduction-steps', 'evidence', 'impact', 'recommendation', 'project-id', 'conversation-tag', 'task-tag', 'status', 'preconditions', 'retest-notes']; const elements = Object.fromEntries(fields.map(name => ['vulnerability-' + name, { value: 'value' }])); elements['vulnerability-conversation-id'].value = conversationID; elements['vulnerability-project-id'].value = ''; const requests = [], alerts = []; let reloaded = false; const ctx = vm.createContext({ document: { getElementById: id => elements[id] }, currentVulnerabilityId: null, vulnerabilityPagination: { currentPage: 3 }, vulnT: key => key, alert: message => alerts.push(message), console, apiFetch: async (url, options) => { requests.push({ url, ...options }); return { ok: true, json: async () => ({ id: 'created' }) }; }, closeVulnerabilityModal() {}, loadVulnerabilityStats() {}, loadVulnerabilities() { reloaded = true; }, }); const source = fs.readFileSync('web/static/js/vulnerability.js', 'utf8'); vm.runInContext(source.slice(source.indexOf('async function saveVulnerability()'), source.indexOf('// 删除漏洞')), ctx); return { ctx, elements, requests, alerts, reloaded: () => reloaded }; } test('manual finding without a conversation submits and reloads', async () => { const s = setup(' '); await s.ctx.saveVulnerability(); assert.equal(s.alerts.length, 0); assert.equal(s.requests.length, 1); assert.equal(s.requests[0].method, 'POST'); assert.equal(JSON.parse(s.requests[0].body).conversation_id, ''); assert.equal(s.ctx.vulnerabilityPagination.currentPage, 1); assert.equal(s.reloaded(), true); }); test('an existing conversation ID is trimmed and sent', async () => { const s = setup(' existing '); await s.ctx.saveVulnerability(); assert.equal(JSON.parse(s.requests[0].body).conversation_id, 'existing'); }); test('other required fields remain required', async () => { const s = setup(); s.elements['vulnerability-title'].value = ' '; await s.ctx.saveVulnerability(); assert.equal(s.requests.length, 0); assert.equal(s.alerts[0], 'vulnerabilityPage.saveRequiredFields'); });