Files
tickte-system/tests/unit/projectAssign.test.mjs
ClaudeandClaude Opus 5.5 f4c8b235b9 Projekte im Ticketsystem: Anlegen, Archiv und Anzeige repariert
- Neues Projekt (Projekte-Seite): Repo-Name blieb nach dem ersten
  Buchstaben der Subdomain stehen ("m" statt "musterfirma")
- Ticket "Projekt waehlen": archivierte Repos nach Flag ausblenden, nicht
  nach status (reaktivierte fehlten, archivierte wurden angeboten)
- Projektliste: "Aktive Projekte" + neue Ansicht "Alle inkl. Archiv";
  Liste wird auch nach einem Anlege-Fehler neu geladen
- Kundenauswahl: "Kein Kunde" entfernt Kunde und Ticket wirklich (mit
  Rueckfrage); beim Kundenwechsel bleibt kein fremdes Ticket haengen
- Zuordnen-Assistent ueberschreibt eine vorhandene Website nicht mehr
- Neues Projekt am Ticket bekommt die Art Website
- Umlaute in Subdomains wie im Portal (mueller statt m-ller)
- Preview-Block nur mit gespeicherter Subdomain; archivierte Projekte
  erst reaktivieren, bevor sie bearbeitet werden
- Repo-Import beim Aufklappen hoechstens einmal pro Minute

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 13:23:01 +00:00

89 lines
3.7 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import test from 'node:test'
import assert from 'node:assert/strict'
import { loadModule } from './load.mjs'
const { isOutsideOrg, needsPreviewButton, assignSummary, assignSequentially, assignableProjects, ticketIdForCustomer } = await loadModule(
'src/lib/projectAssign.js'
)
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
test('isOutsideOrg', () => {
assert.equal(isOutsideOrg('JUSN/D-ner-Nation'), true)
assert.equal(isOutsideOrg('webklar/x'), false)
assert.equal(isOutsideOrg(''), false)
})
test('needsPreviewButton', () => {
assert.equal(needsPreviewButton({ subdomain: 'x', previewUrl: 'https://x', status: 'deployed' }), false)
assert.equal(needsPreviewButton({ previewUrl: '', status: 'synced' }), true)
// gerade angelegt, der Runner baut noch (status noch synced/pending): kein "Preview einschalten"
assert.equal(needsPreviewButton({ subdomain: 'x', previewUrl: 'https://x', status: 'synced' }), false)
assert.equal(needsPreviewButton({ subdomain: 'x', previewUrl: 'https://x', status: 'pending' }), false)
// archiviert: erst reaktivieren
assert.equal(needsPreviewButton({ archived: true, status: 'archived' }), false)
})
test('assignableProjects: Flag archived zaehlt, nicht status', () => {
const all = [
{ $id: 'a', repoFullName: 'WEBklar/a', status: 'archived', archived: false }, // reaktiviert, alter status
{ $id: 'b', repoFullName: 'JUSN/b', status: 'synced', archived: true }, // in Gitea archiviert
{ $id: 'c', repoFullName: 'WEBklar/c', customerId: 'k2' }, // anderer Kunde
{ $id: 'd', repoFullName: 'WEBklar/d', customerId: 'k1' },
{ $id: 'e', repoFullName: 'WEBklar/e', isTemplate: true },
{ $id: 'f', projectName: 'ohne Repo' },
{ $id: 'g', repoFullName: 'WEBklar/g' },
]
const ids = assignableProjects(all, { customerId: 'k1' }, new Set(['g'])).map((p) => p.$id)
assert.deepEqual(ids, ['a', 'd'])
})
test('ticketIdForCustomer: altes Ticket nur beim gleichen Kunden', () => {
const p = { customerId: 'A', ticketId: 'tA' }
const wo = { tA: { customerId: 'A' }, tB: { customerId: 'B' } }
assert.equal(ticketIdForCustomer(p, 'A', wo), 'tA')
assert.equal(ticketIdForCustomer(p, 'B', wo), '')
assert.equal(ticketIdForCustomer({ customerId: 'A', ticketId: 'tB' }, 'B', wo), 'tB')
assert.equal(ticketIdForCustomer({ customerId: '', ticketId: '' }, 'B', wo), '')
})
test('assignSummary', () => {
assert.deepEqual(
assignSummary('Döner Nation', {
moved: { from: 'JUSN/D-ner-Nation', to: 'WEBklar/D-ner-Nation' },
backfilled: 1,
warnings: [],
}),
{ text: 'Döner Nation: nach WEBklar verschoben · 1 Push nachgetragen', warnings: [] }
)
assert.deepEqual(
assignSummary('X', { moved: null, backfilled: 0, warnings: ['Internes Repo, bleibt wo es ist.'] }),
{ text: 'X: keine neuen Pushes', warnings: ['Internes Repo, bleibt wo es ist.'] }
)
assert.equal(assignSummary('X', { moved: null, backfilled: 3, warnings: [] }).text, 'X: 3 Pushes nachgetragen')
assert.deepEqual(assignSummary('X', { error: 'boom' }), { text: 'X: Zuweisen fehlgeschlagen – boom', warnings: [] })
})
test('nacheinander und weiter nach Fehler', async () => {
const log = []
const fn = async (id) => {
log.push(id + ':start')
await sleep(10)
log.push(id + ':end')
if (id === 'b') throw new Error('boom')
return { backfilled: 0 }
}
const r = await assignSequentially(['a', 'b', 'c'], { ticketId: 't1' }, fn)
assert.deepEqual(log, ['a:start', 'a:end', 'b:start', 'b:end', 'c:start', 'c:end'])
assert.deepEqual(
r.map((x) => [x.projectId, x.ok, x.error]),
[
['a', true, undefined],
['b', false, 'boom'],
['c', true, undefined],
]
)
})