bmc_hub/tests/test_case_create_dom.cjs
Christian 81b8229db1 feat: Add Kuando Busylight integration and enhance case creation UI
- Introduced Kuando Busylight integration for centralized presence management.
- Updated case creation UI to support new modules and improved type handling.
- Added personal Buzzwords visibility preferences for users.
- Implemented file upload functionality directly from the case topbar.
- Enhanced validation and user experience in case creation process.
- Created migration for user-specific module preferences.
- Updated tests to cover new features and ensure functionality.
2026-09-23 00:23:30 +02:00

66 lines
5.0 KiB
JavaScript

// Run with NODE_PATH pointing to a jsdom installation (no application dependency).
const {JSDOM} = require('jsdom');
const fs = require('node:fs');
const assert = require('node:assert/strict');
const source = fs.readFileSync('app/modules/sag/templates/create.html','utf8');
const script = source.match(/<script>([\s\S]*?)<\/script>/)[1];
const html = source.split('{% block content %}')[1].split('<script>')[0]
.replace(/\{% for user[\s\S]*?\{% endfor %\}/, '<option value="7">Test bruger</option>')
.replace(/\{% for group[\s\S]*?\{% endfor %\}/, '<option value="2">Support</option>');
const extension = fs.readFileSync('static/js/case-create.js','utf8');
const delay = ms => new Promise(r=>setTimeout(r,ms));
async function page(storage, userId=7, search='') {
const dom = new JSDOM(html,{url:`http://localhost:8001/sag/new${search}`,runScripts:'outside-only'});
const w=dom.window;
await new Promise(r=>w.addEventListener('DOMContentLoaded',r));
w.CSS = {escape:s=>s}; w.confirm=()=>true; w.alert=()=>{};
w.setTagPickerContext=()=>{}; w.tagPicker={showSelection:cb=>cb({id:9,name:'Hardware',color:'#112233'})};
w.bootstrap={Modal:class {show(){} hide(){}}};
w.fetch=async url=>({ok:true,json:async()=>{
if(url.includes('/settings/case_types'))return {value:'["ticket","pipeline","ordre","opgave","service","abonnement"]'};
if(url.includes('/auth/me/profile'))return {default_case_type:'ticket'};
if(url.includes('/auth/me'))return {id:userId};
if(url.includes('/pipeline/stages'))return [{id:1,name:'Tilbud'}];
if(url.includes('/case-create/workload'))return {total:0,items:[]};
if(url.includes('/case-create/contacts-open-cases'))return {5:{total:2,items:[{id:44,titel:'Eksisterende routerfejl',status:'åben',ansvarlig_navn:'Test bruger',deadline:null}]}};
if(url.includes('/case-create/templates'))return [{id:1,name:'Test',values:{type:'pipeline',titel:'Tilbud',beskrivelse:'Tekst',status:'åben',tag_ids:[9]}}];
if(url.includes('/tags?'))return [{id:9,name:'Hardware'},{id:10,name:'Router',type:'brand',catch_words:['router'],color:'#112233'}];
return [];
}});
if(storage)for(const [k,v] of Object.entries(storage))w.localStorage.setItem(k,v);
w.eval(script + '\n' + extension + '\nwindow.testSetCustomer = () => { selectedCustomer={id:11,name:"Firma"}; selectedContacts={}; renderSelections(); }; window.testSetContact = () => { selectedContacts={5:{id:5,name:"Ada"}}; renderSelections(); window.caseCreateUI.contactsChanged(); };'); w.document.dispatchEvent(new w.Event('DOMContentLoaded'));
await delay(60);
return dom;
}
(async()=>{
const dom=await page(),w=dom.window,d=w.document;
assert.equal(d.querySelectorAll('#cc-types > button[data-case-type]').length,8);
assert.equal(d.querySelectorAll('#cc-types > button[data-case-message]').length,1);
assert.equal(d.querySelectorAll('form#createForm').length,1);
for(const id of ['customerSearch','contactSearch','titel','beskrivelse','status','deadline','submitBtn'])assert.ok(d.getElementById(id).closest('#createForm'),id);
assert.equal(w.caseCreateUI.validate(),false);
assert.ok(d.getElementById('typeDetailsSection').classList.contains('d-none'),'Type fields stay hidden until a type button is selected');
d.querySelector('[data-case-type="bug_report"]').click();
assert.ok(!d.getElementById('typeModuleAction').classList.contains('d-none'));
assert.ok(d.getElementById('typeDetailsSection').classList.contains('d-none'));
d.getElementById('openTypeModuleBtn').click();
assert.ok(!d.getElementById('typeDetailsSection').classList.contains('d-none'));
assert.match(d.getElementById('typeDetailsFields').textContent,/Berørt område/);
w.testSetCustomer();
await w.loadSelectedCustomerContacts(11);
const search=d.getElementById('contactSearch'), results=d.getElementById('contactResults');
search.value='Fi';search.dispatchEvent(new w.Event('input',{bubbles:true}));assert.ok(!results.classList.contains('d-none'),'Explicit search opens results');
d.getElementById('titel').value='Test oprettelse';
d.getElementById('beskrivelse').value='Router mister forbindelsen';
assert.equal(w.caseCreateUI.validate(),true);
d.getElementById('titel').dispatchEvent(new w.Event('input',{bubbles:true}));
await delay(650);
const key=Object.keys(w.localStorage)[0];assert.ok(key?.startsWith('bmc:case-draft:v1:7:'), d.getElementById('cc-save').textContent);
const saved={[key]:w.localStorage.getItem(key)};
const restored=await page(saved);restored.window.document.getElementById('cc-restore').click();await delay(80);
assert.equal(restored.window.document.getElementById('titel').value,'Test oprettelse');
restored.window.caseCreateUI.created({id:99});await delay(600);assert.equal(restored.window.localStorage.getItem(key),null);
[dom,restored].forEach(x=>x.window.close());
console.log('PASS: simple flow, all type buttons, required fields and draft restore');
})().catch(e=>{console.error(e);process.exit(1);});