- 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.
66 lines
5.0 KiB
JavaScript
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);});
|