// Run with node tests/test_spot_application_validation.js [path/to/app.js]. // Uses only built-in modules and simulated DOM/fetch; never sends requests. const assert = require('assert/strict'); const fs = require('fs'); const vm = require('vm'); const path = require('path'); const source = fs.readFileSync(process.argv[2] || path.join(__dirname, '../static/js/app.js'), 'utf8'); const code = source.slice(source.indexOf('function validateSpotApplicationForm('), source.indexOf('function decideSpotApplication(')); function fixture() { const nodes = {}, alerts = [], requests = []; function node() { return {value:'', style:{}, listeners:{}, disabled:false, error:'', setCustomValidity(message) { this.error = message; }, addEventListener(name, fn) { this.listeners[name] = fn; }, remove() { this.removed = true; }}; } const fields = {}; for (const name of ['product_name','barcode','sample_quantity','recipient_info','group_name','brand','department']) fields[name] = node(); const button = node(), form = node(); form.elements = {namedItem:name=>fields[name]}; form.querySelector = ()=>button; form.checkValidity = ()=>['product_name','barcode','sample_quantity','recipient_info'].every(name=> fields[name].value.trim() !== '' && !fields[name].error) && /^[0-9]{13}$/.test(fields.barcode.value) && /^\d+$/.test(fields.sample_quantity.value) && !fields.group_name.error; form.reportValidity = ()=>{form.reported = true;}; nodes.spotApplicationForm = form; const context = { document: {getElementById:id=>nodes[id] || (nodes[id]=node()), createElement:node, body:{appendChild:el=>{nodes[el.id]=el;}}}, window: {switchSpotApplicationTab:()=>{}}, alert:message=>alerts.push(message), FormData:function(form) { this.form = form; }, fetch:(url, options)=>{ requests.push({url,options}); return Promise.resolve({json:()=>Promise.resolve(context.response)}); }, response:{code:409, msg:'无法保存,存在重复值:产品名称或条形码已存在'} }; vm.createContext(context); vm.runInContext(code, context); context.openSpotApplicationModal(); function fill() { fields.product_name.value='样品'; fields.barcode.value='0012345678901'; fields.sample_quantity.value='2'; fields.recipient_info.value='收件人及地址'; form.listeners.input.call(form); } const submit = ()=>form.listeners.submit.call(form,{preventDefault(){}}); return {context, fields, button, form, nodes, alerts, requests, fill, submit}; } async function run() { let f = fixture(); assert.equal(f.button.disabled, true); const html = f.nodes.spotApplicationModal.innerHTML; assert.equal((html.match(/(必填)/g)||[]).length, 5); assert(!html.includes('>*')); for (const name of ['京东1组','京东2组','阿里1组','阿里2组','阿里3组']) assert(html.includes('value="'+name+'"')); assert(html.includes('