bmc_hub/tests/js/case-create-commands.test.cjs
Christian 85e019783b Add comprehensive test coverage for case creation, assignment, and remote recovery
- Introduced tests for case creation commands, ensuring proper handling of UUIDs and payloads.
- Added tests for v5 assignment functionality, validating employee identification and group assignment.
- Implemented tests for remote recovery scenarios, including handling network failures and response validation.
- Created tests for hardware label generation and validation, ensuring proper URL formatting and QR code generation.
- Developed extensive tests for remote control functionality, covering connection isolation, command execution, and user permissions.
- Added tests for workflow timer registration, ensuring correct handling of timer states and ownership validation.
2026-10-15 12:17:09 +02:00

56 lines
4.6 KiB
JavaScript

const test=require('node:test'),assert=require('node:assert/strict');
const {CommandRun,init}=require('../../static/js/case-create-commands.js');
const parser=require('../../static/js/case-commands.js');
const completion=require('../../static/js/case-command-suggestions.js');
test('creation commands target the new case and retry with the same UUID and payload',async()=>{
const calls=[];let fail=true;
const run=new CommandRun(async(url,body)=>{calls.push({url,body:JSON.stringify(body)});if(fail){fail=false;throw new Error('offline');}return {};},()=> 'same-uuid');
const parsed=parser.parse('Sagens beskrivelse\n/undersag "Router"\n//tildel ct "Opsæt router"\n//tid 30m support "Opsætning"');
assert.equal(parsed.comment,'Sagens beskrivelse');assert.equal(parsed.errors.length,0);
run.attach(198,parsed.commands);
await assert.rejects(run.execute(),/offline/);assert.equal(run.pending.caseId,198);
await run.execute();assert.equal(run.pending,null);assert.deepEqual(calls[0],calls[1]);
assert.equal(calls[0].url,'/api/v1/sag/198/command-execute');
});
class Element {
constructor(){this.children=[];this.listeners={};this.value='';this.selectionStart=0;this.selectionEnd=0;this.classList={toggle(){}};}
append(...nodes){this.children.push(...nodes);}after(){}replaceChildren(){this.children=[];}setAttribute(){}
addEventListener(type,fn){this.listeners[type]=fn;}focus(){}
setSelectionRange(start,end){this.selectionStart=start;this.selectionEnd=end;}
setRangeText(text,start,end){this.value=this.value.slice(0,start)+text+this.value.slice(end);this.setSelectionRange(start+text.length,start+text.length);}
dispatchEvent(event){this.listeners[event.type]?.(event);}
}
async function fixture(handler){
const nodes=[],input=new Element(),button=new Element();
const root={document:{getElementById:id=>id==='beskrivelse'?input:id==='submitBtn'?button:{textContent:'{"users":[{"user_id":3,"username":"ct","full_name":"Christian Thomas"}],"groups":[]}'},createElement:()=>{const node=new Element();nodes.push(node);return node;},createTextNode:text=>({textContent:text})},CaseCommands:parser,CaseCommandSuggestions:completion,Event:class{constructor(type){this.type=type;}},crypto:{randomUUID:(()=>{let n=0;return ()=>`uuid-${++n}`;})()},sessionStorage:{getItem(){return null;},setItem(){},removeItem(){}},fetch:async(url,options)=>options&&handler?handler(url,JSON.parse(options.body)):({ok:true,json:async()=>({id:17})})};
init(root);await root.caseCreateCommands.ready;
const type=text=>{input.value=text;input.setSelectionRange(text.length,text.length);input.dispatchEvent(new root.Event('input'));};
const press=key=>input.listeners.keydown({key,preventDefault(){}});
return {root,input,nodes,type,press};
}
test('new case supports first-suggestion Enter, initials and automatic description quotes',async()=>{
const f=await fixture();f.type('Beskrivelse\n/ti');f.press('Enter');assert.equal(f.input.value,'Beskrivelse\n/tid ');
f.type('Beskrivelse\n/tid 30m support ');assert.equal(f.input.value,'Beskrivelse\n/tid 30m support ""');
f.type('Beskrivelse\n/undersag "Router"\n//tildel ct');f.press('Enter');
assert.equal(f.input.value,'Beskrivelse\n/undersag "Router"\n//tildel ct ""');
});
test('Enter preserves closing quotes and prose stays separate from commands',async()=>{
const f=await fixture();f.type('Beskrivelse\n/todo "Opgave"');f.input.setSelectionRange(f.input.value.length-1,f.input.value.length-1);f.press('Enter');
assert.equal(f.input.value,'Beskrivelse\n/todo "Opgave"\n');
const parsed=f.root.caseCreateCommands.prepare();assert.equal(parsed.comment,'Beskrivelse');assert.equal(parsed.commands[0].title,'Opgave');
f.type('Beskrivelse\n/ukendt');assert.throws(()=>f.root.caseCreateCommands.prepare(),/Ukendt kommando/);
});
test('a rejected command can be corrected on the same created case',async()=>{
const calls=[];let reject=true;
const f=await fixture(async(url,body)=>{calls.push({url,body});return reject?{ok:false,status:400,json:async()=>({detail:'Initialerne er tvetydige'})}:{ok:true,json:async()=>({results:[]})};});
f.type('Beskrivelse\n/tildel ct "Overdrag"');f.root.caseCreateCommands.prepare();
await assert.rejects(f.root.caseCreateCommands.created({id:99}),/Sag #99 er oprettet/);
assert.equal(f.input.readOnly,false);assert.equal(f.root.caseCreateCommands.pendingCaseId(),99);
reject=false;f.type('Beskrivelse\n/tildel carlt "Overdrag"');await f.root.caseCreateCommands.retry();
assert.equal(calls[1].url,'/api/v1/sag/99/command-execute');
assert.equal(calls[1].body.commands[0].assignee,'carlt');
assert.notEqual(calls[0].body.request_id,calls[1].body.request_id);
assert.equal(f.root.caseCreateCommands.hasPending(),false);
});