asks: a replayed tap is said as the answer already recorded, on its acknowledgement (issue 393)
Since issue 372 the router answers the same answer again from the same account with 'You already chose Approve at HH:MM: recorded.', on the tap's acknowledgement rather than in the chat. The proof from #74 still waited for a chat refusal, so it failed on every mesh-lab pull request. The lab's phone now keeps a tap's acknowledgement words, and the replay subtest waits for them; its checks that nothing more is done stay.
This commit is contained in:
@@ -27,6 +27,11 @@ type fakeTelegram struct {
|
||||
msgID int64
|
||||
taps int // answerCallbackQuery calls
|
||||
deleted int
|
||||
// toasts are the words a tap's acknowledgement showed over the chat (answerCallbackQuery), by the chat the
|
||||
// tap came from: what the phone shows the tapper and never puts in the chat. Kept apart from sent, so a
|
||||
// chat's messages stay what the chat holds.
|
||||
toasts []tgMessage
|
||||
tappedIn map[string]int64 // a tap's callback id to the chat it came from
|
||||
}
|
||||
|
||||
// tgMessage is one message the bot sent or edited: its chat, its id, its words and its buttons (label →
|
||||
@@ -108,9 +113,18 @@ func (f *fakeTelegram) serve(w http.ResponseWriter, r *http.Request) {
|
||||
f.t.Logf("phone: %s to %d (#%d): %q %v", method, chat, m.ID, firstLine(text), m.Buttons)
|
||||
ok(map[string]any{"message_id": m.ID, "chat": map[string]any{"id": chat, "type": "private"}, "text": text})
|
||||
case "answerCallbackQuery":
|
||||
id, _ := body["callback_query_id"].(string)
|
||||
text, _ := body["text"].(string)
|
||||
f.mu.Lock()
|
||||
f.taps++
|
||||
chat, known := f.tappedIn[id]
|
||||
if known && text != "" {
|
||||
f.toasts = append(f.toasts, tgMessage{Chat: chat, Text: text, At: time.Now()})
|
||||
}
|
||||
f.mu.Unlock()
|
||||
if text != "" {
|
||||
f.t.Logf("phone: answerCallbackQuery %s in %d: %q", id, chat, firstLine(text))
|
||||
}
|
||||
ok(true)
|
||||
case "deleteMessage":
|
||||
f.mu.Lock()
|
||||
@@ -152,7 +166,14 @@ func (f *fakeTelegram) tapped(from int64, chat int64, chatType string, onMessage
|
||||
// tappedOn is a tap on a message showing the words given: what a message changed under the operator's thumb,
|
||||
// or forwarded and edited elsewhere, carries.
|
||||
func (f *fakeTelegram) tappedOn(from int64, chat int64, chatType string, onMessage int64, data, text string) {
|
||||
f.push(map[string]any{"callback_query": map[string]any{"id": fmt.Sprintf("cb-%d", f.nextID()), "data": data,
|
||||
id := fmt.Sprintf("cb-%d", f.nextID())
|
||||
f.mu.Lock()
|
||||
if f.tappedIn == nil {
|
||||
f.tappedIn = map[string]int64{}
|
||||
}
|
||||
f.tappedIn[id] = chat
|
||||
f.mu.Unlock()
|
||||
f.push(map[string]any{"callback_query": map[string]any{"id": id, "data": data,
|
||||
"from": map[string]any{"id": from, "is_bot": false, "first_name": fmt.Sprintf("Account %d", from)},
|
||||
"message": map[string]any{"message_id": onMessage, "text": text,
|
||||
"chat": map[string]any{"id": chat, "type": chatType}}}})
|
||||
@@ -197,6 +218,26 @@ func (f *fakeTelegram) waitFor(what string, chat int64, since time.Time, within
|
||||
return tgMessage{}
|
||||
}
|
||||
|
||||
// toldTapper waits for words the phone showed in a chat at or after a time, as a message in it or as a tap's
|
||||
// acknowledgement over it: where the channel says the router's word on a tap (issue 372).
|
||||
func (f *fakeTelegram) toldTapper(what string, chat int64, since time.Time, within time.Duration, match func(string) bool) string {
|
||||
f.t.Helper()
|
||||
deadline := time.Now().Add(within)
|
||||
for time.Now().Before(deadline) {
|
||||
f.mu.Lock()
|
||||
for _, m := range append(append([]tgMessage{}, f.sent...), f.toasts...) {
|
||||
if m.Chat == chat && !m.At.Before(since) && match(m.Text) {
|
||||
f.mu.Unlock()
|
||||
return m.Text
|
||||
}
|
||||
}
|
||||
f.mu.Unlock()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
f.t.Fatalf("the phone never showed %s (chat %d) within %s; it showed:\n%s", what, chat, within, f.transcript())
|
||||
return ""
|
||||
}
|
||||
|
||||
// since is every message to a chat sent at or after a time.
|
||||
func (f *fakeTelegram) since(chat int64, at time.Time) []tgMessage {
|
||||
f.mu.Lock()
|
||||
@@ -218,6 +259,9 @@ func (f *fakeTelegram) transcript() string {
|
||||
fmt.Fprintf(&b, " %s to %d #%d edited=%v %q %v\n", m.At.Format("15:04:05.000"), m.Chat, m.ID, m.Edited,
|
||||
firstLine(m.Text), m.Buttons)
|
||||
}
|
||||
for _, m := range f.toasts {
|
||||
fmt.Fprintf(&b, " %s to %d tap acknowledged %q\n", m.At.Format("15:04:05.000"), m.Chat, firstLine(m.Text))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -178,11 +178,15 @@ func TestTheOperatorsAnswerEndToEnd(t *testing.T) {
|
||||
})
|
||||
|
||||
// --- 4. A replayed tap, and a redelivered warrant, do nothing more.
|
||||
// The replay is the operator's own answer again: the router says it is the one already recorded (on the tap's
|
||||
// acknowledgement, issue 372), not refused as if the approval failed, and it is no second warrant or act.
|
||||
t.Run("a replayed tap and a redelivered warrant do nothing more", func(t *testing.T) {
|
||||
tapped := time.Now()
|
||||
l.tg.tapped(operatorAccount, operatorAccount, "private", firstMessage.ID, button(firstMessage, "Approve"))
|
||||
l.tg.waitFor("the refusal of a replayed tap", operatorAccount, tapped, 90*time.Second,
|
||||
func(m tgMessage) bool { return strings.Contains(m.Text, "That answer was not taken") })
|
||||
l.tg.toldTapper("that a replayed tap is the answer already recorded", operatorAccount, tapped, 90*time.Second,
|
||||
func(text string) bool {
|
||||
return strings.Contains(text, "You already chose Approve") && strings.Contains(text, "recorded")
|
||||
})
|
||||
time.Sleep(2 * time.Second)
|
||||
if n := a.wordsOn("a1"); n != 1 {
|
||||
t.Errorf("the router said %d words on one ask", n)
|
||||
|
||||
Reference in New Issue
Block a user