dy-dashboard/tests/test_spot_application_validation.js
2026-10-28 11:14:17 +08:00

107 lines
5.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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('>*</span>'));
for (const name of ['京东1组','京东2组','阿里1组','阿里2组','阿里3组']) assert(html.includes('value="'+name+'"'));
assert(html.includes('<select name="department">'));
assert(!html.includes('<option value="阿里">'));
f.submit(); assert.equal(f.requests.length, 0);
f.fill(); assert.equal(f.button.disabled, false);
f.fields.brand.value='洁维塔'; f.form.listeners.change.call(f.form);
assert.equal(f.button.disabled, true);
assert.equal(f.fields.group_name.required, true);
assert.equal(f.nodes.spotApplicationGroupRequired.style.display, '');
f.submit(); assert.equal(f.requests.length, 0);
f.fields.group_name.value='京东1组'; f.form.listeners.change.call(f.form);
assert.equal(f.button.disabled, false);
f.fields.group_name.value=''; f.fields.brand.value='泊紫汀兰';
f.form.listeners.change.call(f.form);
assert.equal(f.button.disabled, false);
assert.equal(f.fields.group_name.required, false);
assert.equal(f.fields.group_name.error, '');
assert.equal(f.nodes.spotApplicationGroupRequired.style.display, 'none');
for (const name of ['product_name','sample_quantity','barcode','recipient_info']) {
const original = f.fields[name].value;
f.fields[name].value=' '; f.form.listeners.input.call(f.form);
assert.equal(f.button.disabled, true, name);
f.fields[name].value=original; f.form.listeners.input.call(f.form);
assert.equal(f.button.disabled, false);
}
for (const value of ['123456789012','12345678901234','a123456789012','1234567890123']) {
f.fields.barcode.value=value; f.form.listeners.input.call(f.form);
assert.equal(f.button.disabled, true);
assert.equal(f.nodes.spotApplicationBarcodeError.style.display, 'block');
assert(f.fields.barcode.error.includes('请填写正确的条形码'));
f.submit(); assert.equal(f.requests.length, 0);
}
f.fill(); f.submit(); f.submit();
assert.equal(f.requests.length, 1, 'double-click must not send two requests');
assert.equal(f.button.disabled, true);
f.form.listeners.input.call(f.form);
assert.equal(f.button.disabled, true, 'editing during save must not enable button');
await new Promise(resolve=>setImmediate(resolve));
assert.equal(f.button.disabled, false);
assert(f.alerts[0].includes('存在重复值'));
assert(!f.nodes.spotApplicationModal.removed);
f = fixture(); f.fill(); f.context.response={code:0,id:8}; f.submit();
await new Promise(resolve=>setImmediate(resolve));
assert.equal(f.nodes.spotApplicationModal.removed, true);
assert.equal(f.alerts[0], '申请已添加');
console.log('PASS: required markers, disabled save, barcode validation, group options, duplicate errors, double submission, successful save');
}
run().catch(error=>{console.error(error);process.exitCode=1;});