feat(paket b): Umbenennen erreicht alle — PATCH /title und RENAMED im Feed (D85)
Backend: PATCH /documents/{id}/title mit expectedVersion (409 bei
veralteter Version, 400 bei leerem/zu langem Titel), neuer ChangeType
RENAMED (strukturell, immer Meilenstein), der Feed stellt den neuen Titel
im Klartext zu (ChangeEvent.title). Unter derselben Stripe-Sperre wie die
Inhalts-Patches; Owner-Vormerkung in der API-Beschreibung. Vier neue
Cucumber-Szenarien, zwei Unit-Tests.
Frontend: Der Zeilen-Stift eines Server-Dokuments benennt über den Server
um (optimistisch, 409-Retry, Rücknahme + Warnung bei Fehlschlag); fremde
Umbenennungen kommen als RENAMED über den Feed in Chip und Menü.
URL-Dokumente verlieren den Stift — ihr Name ist die URL.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
c438a88344
commit
fbe9b1fd22
@@ -205,6 +205,45 @@ class LiveEditingStepDefinitions {
|
||||
feed.content shouldBe erwartet
|
||||
}
|
||||
|
||||
@Wenn("das Dokument auf {string} umbenannt wird")
|
||||
fun `das Dokument wird umbenannt`(titel: String) =
|
||||
sendRename(titel, currentDocument().version)
|
||||
|
||||
@Wenn("das Dokument mit veralteter Version auf {string} umbenannt wird")
|
||||
fun `veraltete Umbenennung`(titel: String) =
|
||||
sendRename(titel, currentDocument().version - 1)
|
||||
|
||||
private fun sendRename(titel: String, version: Long) {
|
||||
lastResponse = client.patch()
|
||||
.uri("/api/v1/documents/$documentId/title")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body("""{"title":${json(titel)},"expectedVersion":$version}""")
|
||||
.exchange()
|
||||
.returnResult(String::class.java)
|
||||
}
|
||||
|
||||
@Dann("erhalte ich für das Umbenennen den Status {int}")
|
||||
fun `status des Umbenennens`(erwartet: Int) {
|
||||
status() shouldBe erwartet
|
||||
}
|
||||
|
||||
@Und("das Dokument trägt den Titel {string}")
|
||||
fun `dokument traegt den Titel`(titel: String) {
|
||||
currentDocument().title shouldBe titel
|
||||
}
|
||||
|
||||
@Und("das Dokument steht auf Version {long}")
|
||||
fun `dokument steht auf Version`(version: Long) {
|
||||
currentDocument().version shouldBe version
|
||||
}
|
||||
|
||||
@Und("das RENAMED-Ereignis nennt den Titel {string}")
|
||||
fun `renamed nennt den Titel`(titel: String) {
|
||||
lastBody<ChangeFeed>().events
|
||||
.first { it.changeType.value == "RENAMED" }
|
||||
.title shouldBe titel
|
||||
}
|
||||
|
||||
@Und("der Feed meldet das Ereignis {string}")
|
||||
fun `der Feed meldet das Ereignis`(typ: String) {
|
||||
lastBody<ChangeFeed>().events.map { it.changeType.value } shouldContain typ
|
||||
|
||||
@@ -112,6 +112,35 @@ class DocumentServiceTest {
|
||||
entry.captured.version shouldBe 4
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rename inkrementiert Version und schreibt RENAMED-Meilenstein`() {
|
||||
val doc = sampleDocument(version = 3)
|
||||
every { repository.findById(doc.id) } returns doc
|
||||
val saved = slot<Document>()
|
||||
every { repository.save(capture(saved)) } answers { saved.captured }
|
||||
val entry = captureAppended()
|
||||
|
||||
val result = service.rename(doc.id, title = "Team-Plan", expectedVersion = 3)
|
||||
|
||||
result.version shouldBe 4
|
||||
result.title shouldBe "Team-Plan"
|
||||
result.content shouldBe doc.content /* der Inhalt bleibt */
|
||||
entry.captured.changeType shouldBe ChangeType.RENAMED
|
||||
entry.captured.milestone shouldBe true /* strukturell, nie bloss Sync */
|
||||
entry.captured.title shouldBe "Team-Plan"
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `rename mit veralteter Version wirft Konflikt und schreibt nichts`() {
|
||||
val doc = sampleDocument(version = 3)
|
||||
every { repository.findById(doc.id) } returns doc
|
||||
|
||||
shouldThrow<DocumentConflictException> {
|
||||
service.rename(doc.id, title = "Zu spaet", expectedVersion = 2)
|
||||
}
|
||||
verify(exactly = 0) { repository.save(any()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `delete entfernt Dokument und schreibt DELETED-Tombstone`() {
|
||||
val doc = sampleDocument(version = 2)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# language: de
|
||||
Funktionalität: Ein geteiltes Dokument umbenennen
|
||||
Als Bearbeiter eines geteilten Plans
|
||||
möchte ich den Titel für alle ändern,
|
||||
damit jeder im Wähler denselben Namen sieht.
|
||||
|
||||
Grundlage: Der Titel ist ein Metadatum und bekommt seinen eigenen Weg mit
|
||||
Versionsprüfung (D76/D85); der Änderungsfeed stellt die Umbenennung samt
|
||||
neuem Titel zu.
|
||||
|
||||
Szenario: Umbenennen mit aktueller Version gilt und lässt den Inhalt stehen
|
||||
Angenommen es existiert ein Dokument "Plan" mit den Zeilen:
|
||||
"""
|
||||
- [ ] Eins
|
||||
"""
|
||||
Wenn das Dokument auf "Team-Plan" umbenannt wird
|
||||
Dann erhalte ich für das Umbenennen den Status 200
|
||||
Und das Dokument trägt den Titel "Team-Plan"
|
||||
Und das Dokument steht auf Version 2
|
||||
Und das Dokument hat die Zeilen:
|
||||
"""
|
||||
- [ ] Eins
|
||||
"""
|
||||
|
||||
Szenario: Der Feed stellt die Umbenennung samt neuem Titel zu
|
||||
Angenommen es existiert ein Dokument "Plan" mit den Zeilen:
|
||||
"""
|
||||
- [ ] Eins
|
||||
"""
|
||||
Wenn das Dokument auf "Team-Plan" umbenannt wird
|
||||
Und ich die Änderungen seit Version 1 abrufe
|
||||
Dann der Feed meldet das Ereignis "RENAMED"
|
||||
Und das RENAMED-Ereignis nennt den Titel "Team-Plan"
|
||||
|
||||
Szenario: Eine veraltete Version wird abgelehnt
|
||||
Angenommen es existiert ein Dokument "Plan" mit den Zeilen:
|
||||
"""
|
||||
- [ ] Eins
|
||||
"""
|
||||
Wenn das Dokument mit veralteter Version auf "Zu spät" umbenannt wird
|
||||
Dann erhalte ich für das Umbenennen den Status 409
|
||||
Und das Dokument trägt den Titel "Plan"
|
||||
|
||||
Szenario: Ein leerer Titel wird abgelehnt
|
||||
Angenommen es existiert ein Dokument "Plan" mit den Zeilen:
|
||||
"""
|
||||
- [ ] Eins
|
||||
"""
|
||||
Wenn das Dokument auf " " umbenannt wird
|
||||
Dann erhalte ich für das Umbenennen den Status 400
|
||||
Und das Dokument trägt den Titel "Plan"
|
||||
Reference in New Issue
Block a user