- 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>
89 lines
3.7 KiB
JavaScript
89 lines
3.7 KiB
JavaScript
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],
|
||
]
|
||
)
|
||
})
|