/)
+ assert.match(ansicht, /
Deine Auftragsbestätigungen\. Offene Aufträge bestätigst du hier mit einem Klick\.<\/p>/, 'Portal: Du-Form')
+ assert.ok(ansicht.indexOf('id="orders-section"') < ansicht.indexOf('id="invoices-body"'))
+ assert.equal([...html.matchAll(/id="orders-section"/g)].length, 1)
+ assert.match(ansicht, /
Rechnungen<\/h1>/, 'Kopf und Hinweis des Reiters bleiben')
+})
+
+test('app.js: loadCustomerOrders lädt auftrag-portal.js nach der Rechnungsliste, mit api und Ansichtsmodus; Fehler bleiben still', () => {
+ const funktion = app.slice(app.indexOf('function loadCustomerOrders()'), app.indexOf('/* ---', app.indexOf('function loadCustomerOrders()')))
+ assert.ok(funktion.length > 40, 'Funktion gefunden')
+ assert.match(funktion, /import\('\/auftrag-portal\.js'\)/)
+ assert.match(funktion, /m\.initAuftraege\(/)
+ for (const teil of ["section: document.getElementById('orders-section')", "body: document.getElementById('orders-body')", "invoicesTitle: document.getElementById('invoices-title')", 'request: api', 'viewAs: chatState.viewAs']) {
+ assert.ok(funktion.includes(teil), teil)
+ }
+ assert.match(funktion, /\.catch\(\(\) => \{\}\)/)
+ const dashboard = app.slice(app.indexOf('async function initDashboardPage'))
+ const aufruf = (name) => dashboard.search(new RegExp(`^\\s*${name}\\(\\)\\s*$`, 'm'))
+ assert.ok(aufruf('loadCustomerInvoices') > 0 && aufruf('loadCustomerOrders') > aufruf('loadCustomerInvoices'), 'ein eigener Aufruf, nach der Rechnungsliste')
+ assert.equal([...app.matchAll(/function loadCustomerOrders\(\)/g)].length, 1)
+})
+
+test('invoiceNumberHtml: Projekt unter der Rechnungsnummer, alles maskiert', () => {
+ const ausschnitt = (muster) => {
+ const treffer = app.match(muster)
+ assert.ok(treffer, `${muster} nicht in app.js`)
+ return treffer[0]
+ }
+ const code = [
+ ausschnitt(/function escapeHtml\(str\) \{[\s\S]*?\n\}/),
+ ausschnitt(/\/\/ @rechnungsnummer-anfang[\s\S]*?\/\/ @rechnungsnummer-ende/),
+ ].join('\n')
+ const { invoiceNumberHtml } = vm.runInNewContext(`${code}\n({ invoiceNumberHtml })`)
+ assert.equal(invoiceNumberHtml({ number: 'WEBKLAR-0009', projekt: 'Website Anelia Wolf' }), 'WEBKLAR-0009Website Anelia Wolf')
+ assert.equal(invoiceNumberHtml({ number: 'WEBKLAR-0009', projekt: '' }), 'WEBKLAR-0009')
+ assert.equal(invoiceNumberHtml({ number: 'H96T-0004' }), 'H96T-0004')
+ assert.equal(
+ invoiceNumberHtml({ number: 'X', projekt: '
& "Bäckerei"' }),
+ 'X<img src=x onerror=alert(1)> & "Bäckerei"',
+ )
+ assert.match(app, /\$\{invoiceNumberHtml\(i\)\}<\/td>/)
+ assert.doesNotMatch(app, /\$\{i\.projekt\}/, 'der Projektname geht nie unmaskiert in eine Vorlage')
+})
+
+test('auftrag.css: Projektname unter der Rechnungsnummer (Tabelle und Handy-Karte)', () => {
+ assert.match(css, /\.inv-project\s*\{[^}]*display:\s*block/)
+ assert.match(css, /\.inv-project\s*\{[^}]*overflow-wrap:\s*anywhere/)
+})
|