Recognise a pinned message (§6.19)
Codec only — the app does not pin yet — but without this branch an inbound pin falls through parse to the attachment path and comes back renderable, so every pin the iPhone app sets would draw an empty bubble in the conversation. isRenderable excludes it for the same reason it excludes a reaction, and it is NOT in Kind.CONTROL: a build that swallowed it as generic control would drop every pin while looking like it worked. 🔴 The envelope carries an id and never a copy of the message. A pin carrying the text would keep a message readable after its own timer had removed it, so pinning would quietly defeat disappearing messages. Refs paulhitt/flamenet-messenger-ios#50 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
400c910615
commit
3614665732
@@ -0,0 +1,86 @@
|
||||
package io.flamenet.e2e
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Pinning a message in a conversation (§6.19).
|
||||
*
|
||||
* ⚠️ **The codec half.** The Android app does not pin yet, but it must already
|
||||
* understand an envelope the iPhone app sends — and in particular must not draw
|
||||
* one as a message, which is what an unrecognised pin becomes.
|
||||
*
|
||||
* 🔴 A pin is an id and never a copy of the message. A pin carrying the text
|
||||
* would keep a message readable after its own timer had removed it, so pinning
|
||||
* would quietly defeat disappearing messages.
|
||||
*/
|
||||
class PinTest {
|
||||
|
||||
@Test
|
||||
fun `a pin names the message it pins`() {
|
||||
val content = Content.parse(Content.pin("abc"))
|
||||
assertEquals("abc", content.pins)
|
||||
assertEquals(Content.Kind.PIN, content.kind)
|
||||
}
|
||||
|
||||
/** An empty id takes the pin down. */
|
||||
@Test
|
||||
fun `an unpin round trips`() {
|
||||
assertEquals("", Content.parse(Content.pin("")).pins)
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔴 The bug this prevents. An unrecognised pin falls through `parse` to
|
||||
* the attachment path and comes back renderable — an empty bubble in
|
||||
* somebody's conversation every time the other side pins something.
|
||||
*/
|
||||
@Test
|
||||
fun `a pin is not a message`() {
|
||||
val content = Content.parse(Content.pin("abc"))
|
||||
assertFalse(content.isRenderable, "a pin would be drawn as a bubble")
|
||||
assertTrue(content.text.isEmpty())
|
||||
assertNull(content.attachment)
|
||||
}
|
||||
|
||||
/**
|
||||
* ⚠️ Not swallowed as generic control either. A build that consumed it
|
||||
* silently would drop every pin while looking like it worked.
|
||||
*/
|
||||
@Test
|
||||
fun `a pin is a known kind, not unknown control`() {
|
||||
assertTrue(Content.Kind.PIN in Content.Kind.KNOWN)
|
||||
assertTrue(Content.Kind.PIN !in Content.Kind.CONTROL,
|
||||
"a pin swallowed as control would drop silently")
|
||||
}
|
||||
|
||||
/** 🔴 The envelope carries no copy of the message — only its id. */
|
||||
@Test
|
||||
fun `the envelope carries no copy of the message`() {
|
||||
val wire = Content.pin("abc")
|
||||
assertFalse(wire.contains("caption"), "a pin carried message text: $wire")
|
||||
assertEquals("", Content.parse(wire).about?.preview)
|
||||
}
|
||||
|
||||
/** Group routing survives, for when a group transcript can name a message. */
|
||||
@Test
|
||||
fun `a group pin keeps its routing`() {
|
||||
val content = Content.parse(Content.pin("abc", groupId = "g1"))
|
||||
assertEquals("g1", content.groupId)
|
||||
assertEquals("abc", content.pins)
|
||||
}
|
||||
|
||||
/** ⚠️ `fnc` first, like every other envelope. */
|
||||
@Test
|
||||
fun `the envelope starts with the marker`() {
|
||||
assertTrue(Content.pin("abc").startsWith("{\"fnc\":1,"))
|
||||
}
|
||||
|
||||
/** A pin with no target is not a pin. */
|
||||
@Test
|
||||
fun `a pin with no reference is not treated as one`() {
|
||||
assertNull(Content.parse("""{"fnc":1,"kind":"pin"}""").pins)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user