Workers P4 Endprüfung W2: „Vorschau bauen“ fragt vor dem Start nach und fehlt bei toten Interessenten
Der Knopf startete einen Opus-Lauf mit einem einzigen Klick (Handy: voll breit zwischen anderen Knöpfen), ohne dass sich der Bau in der Oberfläche zurücknehmen lässt. Wie Freigeben und Verwerfen fragt er jetzt zuerst nach („Wirklich bauen?“, 4 s) und zeigt dabei, dass ein Opus-Lauf startet und die Vorschau gebaut wird, als hätte der Interessent Ja gesagt (ohne „nur wenn Ja“: der Knopf gilt gerade für unklare Antworten). rowModel blendet den Knopf bei gesperrtem, verlorenem oder abgeschlossenem Interessenten (gesperrt, verloren, deal) aus; ohne Kurzfassung entscheidet weiter der Dienst. Prüfstand: die Fehler- und Fokus-Läufe klicken zweimal, Szenario bauen prüft Frage, Hinweis und Verfall. Doppeltipp-Schutz und Dienst-Härtung (bauLauf nur nach Ja) bleiben offen, siehe final-fix-report-woms.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
1536a3bbc1
commit
871b87fac0
5 files changed
+99
-19
No files matched your search
@@ -368,6 +368,21 @@ test('rowModel canStartBuild (GB16): nur Art unsicher mit prospectId, bearbeitba
|
||||
for (const status of ['gesendet', 'erledigt', 'verworfen']) assert.equal(rowModel(entry({ status }), T32_CTX).canStartBuild, false, status)
|
||||
})
|
||||
|
||||
// Endprüfung P4 (W2): ein toter Interessent bekommt keinen Knopf „Vorschau bauen“ (der Dienst lehnt ihn ohnehin mit 409 ab)
|
||||
test('rowModel canStartBuild (W2): bei gesperrtem, verlorenem oder abgeschlossenem Interessenten (gesperrt, verloren, deal) kein Knopf, sonst bleibt er', () => {
|
||||
for (const status of ['gesperrt', 'verloren', 'deal']) {
|
||||
assert.equal(rowModel(entry({ prospect: { $id: 'p1', name: 'X', status } }), T32_CTX).canStartBuild, false, status)
|
||||
}
|
||||
// lebende Interessenten und Kurzfassungen ohne Status behalten den Knopf (der Dienst prüft das Übrige: doppelte Vorschau)
|
||||
for (const status of ['gefunden', 'kontaktiert', 'gespraech', 'ja', 'vorschau_bau', undefined, null, 7]) {
|
||||
assert.equal(rowModel(entry({ prospect: { $id: 'p1', name: 'X', status } }), T32_CTX).canStartBuild, true, String(status))
|
||||
}
|
||||
assert.equal(rowModel(entry({ prospect: null }), T32_CTX).canStartBuild, true) // keine Kurzfassung: der Dienst entscheidet
|
||||
// alles andere zählt weiter: nur Art unsicher, bearbeitbar, nicht von einem anderen gehalten, mit prospectId
|
||||
assert.equal(rowModel(entry({ prospect: { status: 'gesperrt' }, status: 'veraltet' }), T32_CTX).canStartBuild, false)
|
||||
assert.equal(rowModel(entry({ prospect: { status: 'verloren' }, prospectId: '' }), T32_CTX).canStartBuild, false)
|
||||
})
|
||||
|
||||
test('rowModel canPaste: Art plattform_antwort mit Interessent, in jedem Status außer verworfen, auch bei einem Kollegen', () => {
|
||||
const plattform = (over = {}) => entry({ kind: 'plattform_antwort', prospect: { name: 'X' }, ...over })
|
||||
for (const status of ['offen', 'in_arbeit', 'veraltet', 'gesendet', 'erledigt']) assert.equal(rowModel(plattform({ status }), T32_CTX).canPaste, true, status)
|
||||
|
||||
@@ -484,7 +484,7 @@ test('PultList (P4-T32): Quelltext – Aktionen über pultAction, Prüfung mit v
|
||||
for (const t of [
|
||||
"'reply'", "'approve-preview'", "'paste'", "'start-build'", 'validateReplyText', 'canReply', 'canApprovePreview', 'canStartBuild', 'canPaste', 'previewHref',
|
||||
'actionErrorText', 'pasteDoneText', 'rel="noopener noreferrer"', 'target="_blank"',
|
||||
'Als Mensch antworten', 'Jetzt senden', 'Vorschau ansehen', 'Freigeben & senden', 'Wirklich freigeben?', 'Vorschau bauen',
|
||||
'Als Mensch antworten', 'Jetzt senden', 'Vorschau ansehen', 'Freigeben & senden', 'Wirklich freigeben?', 'Vorschau bauen', 'Wirklich bauen?',
|
||||
'Antwort des Kunden einfügen', 'Einfügen', 'wk-pult-reply', 'wk-pult-paste',
|
||||
'Kopiere die Antwort aus der Plattform hierher. Nora sortiert sie ein; bei einer Frage schreibt Clara den nächsten Entwurf.',
|
||||
]) assert.ok(s.includes(t), t)
|
||||
@@ -546,6 +546,12 @@ test('PultList (gerendert, P4-T32): Aktionen je Art – Antworten, Freigeben, Ba
|
||||
// Interessent ohne Adresse (Plattform): kein Mail-Kanal ⇒ nicht antworten, aber bauen
|
||||
html = show([{ ...base, prospect: { $id: 'p1', name: 'Verein' } }])
|
||||
assert.ok(!html.includes('Als Mensch antworten')); assert.ok(html.includes('Vorschau bauen'))
|
||||
// Endprüfung P4 (W2): ein toter Interessent (gesperrt, verloren, Deal) bekommt keinen Knopf zum Bauen, ein lebender behält ihn
|
||||
for (const status of ['gesperrt', 'verloren', 'deal']) {
|
||||
html = show([{ ...base, prospect: { ...base.prospect, status } }])
|
||||
assert.ok(!html.includes('Vorschau bauen'), status); assert.ok(buttonOf(html, 'Als Mensch antworten'), status); assert.ok(buttonOf(html, 'Erledigt'), status)
|
||||
}
|
||||
assert.ok(buttonOf(show([{ ...base, prospect: { ...base.prospect, status: 'gespraech' } }]), 'Vorschau bauen'))
|
||||
// von einem Kollegen übernommen: weder antworten noch bauen, der Rest bleibt wie bisher
|
||||
html = show([{ ...base, status: 'in_arbeit', claimedBy: 'mensch:u2' }])
|
||||
assert.ok(html.includes('übernommen von Kenso')); assert.ok(!html.includes('Als Mensch antworten')); assert.ok(!html.includes('Vorschau bauen')); assert.ok(buttonOf(html, 'Erledigt'))
|
||||
@@ -752,22 +758,56 @@ test('PultList (bedient, P4-T32): während einer Anfrage sind alle Knöpfe der Z
|
||||
} finally { ui.end() }
|
||||
})
|
||||
|
||||
test('PultList (bedient, P4-T32): ein „unsicher“-Eintrag ohne Entwurf öffnet „Als Mensch antworten“ mit leerem Feld; „Vorschau bauen“ startet den Bau', async () => {
|
||||
const api = scriptedApi(failure('Für diesen Interessenten gibt es schon eine Vorschau.', 409), Promise.resolve({ item: { $id: 'e1' } }))
|
||||
test('PultList (bedient, P4-T32): ein „unsicher“-Eintrag ohne Entwurf öffnet „Als Mensch antworten“ mit leerem Feld', async () => {
|
||||
const api = scriptedApi()
|
||||
const ui = await startList([{ ...unsicher, draft: undefined }], api)
|
||||
try {
|
||||
await ui.click('Als Mensch antworten')
|
||||
assert.deepEqual(ui.value('Text der Antwort'), ['']); assert.ok(ui.text().includes('0 / 8000'))
|
||||
// Bau starten: ohne Body, Fehler des Dienstes als Satz, Erfolg oben bei der Liste
|
||||
assert.equal(api.calls.length, 0)
|
||||
} finally { ui.end() }
|
||||
})
|
||||
|
||||
// Endprüfung P4 (W2): „Vorschau bauen“ startet einen Opus-Lauf und lässt sich in der Oberfläche nicht zurücknehmen: wie Freigeben und Verwerfen
|
||||
// fragt der Knopf zuerst nach (4 s). Ein Fehlklick (Handy: der Knopf liegt in voller Breite zwischen anderen) startet keinen Bau mehr.
|
||||
test('PultList (bedient, W2): „Vorschau bauen“ – erster Klick fragt nach (4 s, Hinweis), zweiter startet den Bau; Fehler und Erfolg wie bisher', async () => {
|
||||
const api = scriptedApi(failure('Für diesen Interessenten gibt es schon eine Vorschau.', 409), Promise.resolve({ item: { $id: 'e1' } }))
|
||||
const ui = await startList([{ ...unsicher, draft: undefined }], api)
|
||||
try {
|
||||
// erster Klick: Rückfrage und Hinweis zu Kosten und Wirkung, nichts geht hinaus; die Rückfrage verfällt nach 4 s
|
||||
assert.ok(!ui.text().includes('Opus'))
|
||||
await ui.click('Vorschau bauen')
|
||||
assert.equal(api.calls.length, 0); assert.ok(ui.has('Wirklich bauen?')); assert.ok(!ui.has('Vorschau bauen'))
|
||||
assert.ok(ui.text().includes('Startet einen Opus-Lauf')); assert.ok(ui.text().includes('als hätte der Interessent Ja gesagt'))
|
||||
assert.ok(!ui.text().includes('nur wenn')) // kein „nur wenn der Interessent Ja gesagt hat“: der Knopf gilt gerade für unklare Antworten
|
||||
assert.deepEqual([...ui.timers.values()].map((t) => t.ms), [4000])
|
||||
ui.fireTimers(); await settle()
|
||||
assert.ok(ui.has('Vorschau bauen')); assert.ok(!ui.has('Wirklich bauen?')); assert.ok(!ui.text().includes('Opus')); assert.equal(api.calls.length, 0)
|
||||
// Rückfrage und zweiter Klick ⇒ Aktion ohne Body; der Dienst lehnt ab: sein Satz erscheint, die Rückfrage beginnt von vorn
|
||||
await ui.click('Vorschau bauen'); await ui.click('Wirklich bauen?')
|
||||
assert.deepEqual(api.calls, [['e1', 'start-build']])
|
||||
assert.deepEqual(ui.messages(), [{ kind: 'err', text: 'Für diesen Interessenten gibt es schon eine Vorschau.', role: 'alert' }])
|
||||
await ui.click('Vorschau bauen')
|
||||
assert.ok(ui.has('Vorschau bauen')); assert.ok(!ui.text().includes('Opus'))
|
||||
// Erfolg oben bei der Liste
|
||||
await ui.click('Vorschau bauen'); await ui.click('Wirklich bauen?')
|
||||
assert.deepEqual(ui.messages(), [{ kind: 'ok', text: '„Unklare Antwort“ wird gebaut.', role: 'status' }])
|
||||
assert.equal(api.calls.length, 2)
|
||||
} finally { ui.end() }
|
||||
})
|
||||
|
||||
test('PultList (bedient, W2): die Rückfragen vor Bauen, Verwerfen und Freigeben lösen einander ab; Verwerfen sendet nichts ohne zweiten Klick', async () => {
|
||||
const api = scriptedApi()
|
||||
const ui = await startList([unsicher], api)
|
||||
try {
|
||||
await ui.click('Vorschau bauen'); assert.ok(ui.has('Wirklich bauen?'))
|
||||
await ui.click('Verwerfen'); assert.ok(ui.has('Wirklich verwerfen?')); assert.ok(ui.has('Vorschau bauen')); assert.ok(!ui.text().includes('Opus'))
|
||||
await ui.click('Vorschau bauen'); assert.ok(ui.has('Wirklich bauen?')); assert.ok(ui.has('Verwerfen'))
|
||||
assert.equal(api.calls.length, 0)
|
||||
await ui.click('Wirklich bauen?')
|
||||
assert.deepEqual(api.calls, [['e1', 'start-build']])
|
||||
} finally { ui.end() }
|
||||
})
|
||||
|
||||
test('PultList (bedient, P4-T32): Vorschau freigeben – erster Klick fragt nach (4 s), zweiter sendet; keine Antwort heißt „Kann gesendet sein“', async () => {
|
||||
const freigabe = { ...unsicher, $id: 'f1', kind: 'vorschau_freigabe', title: 'Vorschau prüfen', draft: 'Hier ist Ihre Vorschau.', sourceUrl: 'https://entwurf.project.webklar.com/AAA/' }
|
||||
const api = scriptedApi(failure('Die Vorschau ist nicht freigabebereit.', 409), failure('Der Hustler-Dienst ist gerade nicht erreichbar.', 0), Promise.resolve({ item: { $id: 'f1' }, previewUrl: freigabe.sourceUrl }))
|
||||
|
||||
Reference in new issue
Block a user