import { mkdtempSync, writeFileSync, existsSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { ListingsService } from '../app/modules/listings/service.mjs'; import { InventoryService } from '../app/modules/inventory/service.mjs'; import { MediaService } from '../app/modules/media/service.mjs'; const failures=[]; const assert=(c,m)=>{if(!c)failures.push(m)}; const expectThrow=(fn,code,m)=>{try{fn();failures.push(m)}catch(e){if(code&&e.code!==code)failures.push(`${m} (${e.code||e.message})`)}}; let listings=[{id:1,title:'Aktiv',deleted_at:null,tags:[],photos:[]},{id:2,title:'Papierkorb',deleted_at:'2026-01-01',tags:[],photos:[]}]; const listRepo={ create(data){const row={id:3,...data,tags:data.tags||[],photos:data.photos||[]};listings.push(row);return row;}, get(id){return listings.find(x=>x.id===Number(id))||null;}, list(){return listings.filter(x=>!x.deleted_at);}, update(id,data){const row=this.get(id);Object.assign(row,data);return row;}, softDelete(id){this.get(id).deleted_at='now';}, restore(id){this.get(id).deleted_at=null;}, listDeleted(){return listings.filter(x=>x.deleted_at);}, permanentDelete(id){listings=listings.filter(x=>x.id!==Number(id));}, trashCount(){return this.listDeleted().length;}, duplicate(id){const row=this.get(id);return row?this.create({...row,id:undefined,title:`${row.title} (Kopie)`,deleted_at:null}):null;}, }; const ls=new ListingsService(listRepo); expectThrow(()=>ls.validateCreate({platform:'ebay'}),'LISTING_INPUT_INVALID','Titelpflicht wurde nicht erzwungen'); expectThrow(()=>ls.validateCreate({title:'OK',hacker:true}),'LISTING_INPUT_INVALID','Unbekanntes Listingfeld wurde akzeptiert'); const cleaned=ls.validateCreate({title:'Test',description_html:'
Text
',tags:['a','b']}); assert(!cleaned.description_html.includes('