messenger, telegram: a second tap on the recorded answer is said as recorded, and the fallback claims nothing (issue 372 review)
mesh/merge-gate pass: builds messenger, telegram → novox; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
mesh/merge-gate pass: builds messenger, telegram → novox; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-check-typescript.sh (typescript)
mesh/delivery superseded: a newer head of the same pull request
The review found that a double tap while the phone's spinner turned would be answered 'That answer was not taken', reading as if the approval failed; it is now 'You already chose Approve at 13:30: recorded.' and does nothing more. The fallback toast no longer promises a change that may not come (a stranger's tap), the wait outlasts the router's 10 s wait for the controller's root word, the channel's own refusals stay in the chat too, and the store's error words stay in the journal.
This commit is contained in:
@@ -387,10 +387,17 @@ func TestAnApproveFromTheLinkedAccountIsAWarrantForTheAskerAlone(t *testing.T) {
|
||||
if out, _ := h.Chosen("telegram", choiceOf(release, "42", c.now())); out != "chosen" {
|
||||
t.Errorf("a redelivery of the same answer was acted on again: %s", out)
|
||||
}
|
||||
// The same answer from the same account, as a new tap, is what was recorded: said so, nothing more done
|
||||
// (issue 372). From another account it is refused.
|
||||
again := choiceOf(release, "42", c.now())
|
||||
again.ID = "another"
|
||||
if out, err := h.Chosen("telegram", again); err == nil || out != "refused" {
|
||||
t.Errorf("a used ticket was taken: %s", out)
|
||||
if out, err := h.Chosen("telegram", again); err != nil || out != "chosen" ||
|
||||
!strings.HasPrefix(tg.sends[len(tg.sends)-1].Title, "You already chose Release at ") {
|
||||
t.Errorf("the same answer again was not said as recorded: %s %v %q", out, err, tg.sends[len(tg.sends)-1].Title)
|
||||
}
|
||||
stranger := choiceOf(release, "666", c.now())
|
||||
if out, err := h.Chosen("telegram", stranger); err == nil || out != "refused" {
|
||||
t.Errorf("a used ticket was taken from another account: %s", out)
|
||||
}
|
||||
stop := ticketFor(tg.sends[0], "Stop")
|
||||
if out, err := h.Chosen("telegram", choiceOf(stop, "42", c.now())); err == nil || !strings.Contains(err.Error(), "already answered") {
|
||||
|
||||
@@ -755,6 +755,13 @@ func (h *Holder) confirmChoice(kind string, c asks.Choice, label, asker string,
|
||||
h.record(Sent{At: h.Now(), Channel: kind, Key: "(answer)", What: "confirmed " + label, Outcome: outcomeOf(err)})
|
||||
}
|
||||
|
||||
// confirmAgain says, in reply to the same answer given again, that it was already recorded.
|
||||
func (h *Holder) confirmAgain(kind string, c asks.Choice, label string, at time.Time) {
|
||||
err := h.showOn(kind, Message{Title: "You already chose " + label + " at " + at.In(h.zone()).Format("15:04") + ": recorded.",
|
||||
Quiet: true, Reply: c.ID})
|
||||
h.record(Sent{At: h.Now(), Channel: kind, Key: "(answer)", What: "confirmed again " + label, Outcome: outcomeOf(err)})
|
||||
}
|
||||
|
||||
// sweepAsks ends asks past their expiry, and tells again an asker not yet told. Called every minute.
|
||||
func (h *Holder) sweepAsks(now time.Time) {
|
||||
h.mu.Lock()
|
||||
@@ -865,6 +872,14 @@ func (h *Holder) judge(kind string, c asks.Choice, key string, root func(KindInf
|
||||
}
|
||||
now := h.Now()
|
||||
t, issued := rec.Tickets[c.Ticket]
|
||||
if w := rec.Warrant; issued && rec.State == string(asks.OutcomeChosen) && w != nil && w.Option == t.Option &&
|
||||
w.By != nil && w.By.Kind == kind && w.By.Identity == c.Sender.Identity && (c.Sender.Authenticated || !h.Bench.Promises(kind, "verified-sender")) {
|
||||
// The same answer again from the same account — a second tap while the first was being confirmed, or one
|
||||
// redelivered after a restart: it is what was recorded, so it is said so, not refused as if it failed
|
||||
// (issue 372). Nothing more is done.
|
||||
h.confirmAgain(kind, c, w.Label, rec.Closed)
|
||||
return "chosen", nil
|
||||
}
|
||||
switch {
|
||||
case !issued:
|
||||
return h.refuseChoice(kind, c, "it belongs to no ask this router holds")
|
||||
@@ -948,7 +963,9 @@ func (h *Holder) judge(kind string, c asks.Choice, key string, root func(KindInf
|
||||
if errors.Is(err, ErrChanged) {
|
||||
return h.refuseChoice(kind, c, "the question was already answered")
|
||||
}
|
||||
return h.refuseChoice(kind, c, "it could not be recorded: "+err.Error())
|
||||
// The store's own words stay in the journal: they are not the operator's to read on the phone.
|
||||
h.Logf("[messenger] the answer to %s's ask %s could not be recorded: %v", rec.Asker, rec.Ask.ID, err)
|
||||
return h.refuseChoice(kind, c, "it could not be recorded")
|
||||
}
|
||||
h.record(Sent{At: now, Channel: kind, Key: rec.Record, What: "answer " + o.Label, Outcome: "warrant to " + rec.Asker})
|
||||
h.Logf("[messenger] %s: a warrant for %s's ask %s", w.Says(), rec.Asker, rec.Ask.ID)
|
||||
|
||||
@@ -136,10 +136,10 @@ func TestARefusedAnswerSaysWhyInReplyToTheTap(t *testing.T) {
|
||||
settle(h, c)
|
||||
release := ticketFor(tg.sends[0], "Release")
|
||||
_, _ = h.Chosen("telegram", choiceOf(release, "42", c.now()))
|
||||
again := choiceOf(release, "42", c.now())
|
||||
again := choiceOf(ticketFor(tg.sends[0], "Stop"), "42", c.now())
|
||||
again.ID = "tg-tap-again"
|
||||
if out, _ := h.Chosen("telegram", again); out != "refused" {
|
||||
t.Fatalf("a used ticket was taken: %s", out)
|
||||
t.Fatalf("a second answer to an answered question was taken: %s", out)
|
||||
}
|
||||
last := tg.sends[len(tg.sends)-1]
|
||||
if last.Reply != "tg-tap-again" || last.Title != "That answer was not taken" ||
|
||||
@@ -150,3 +150,36 @@ func TestARefusedAnswerSaysWhyInReplyToTheTap(t *testing.T) {
|
||||
t.Error("the refusal carries what may not leave")
|
||||
}
|
||||
}
|
||||
|
||||
// A second tap on the answer just recorded — the phone's spinner still turning, or a redelivery after a restart
|
||||
// — is said as recorded, not refused as if it failed, and nothing more is done (issue 372).
|
||||
func TestTheSameAnswerTappedTwiceIsSaidAsRecorded(t *testing.T) {
|
||||
h, tg, _, c, store, w := newRouter(t)
|
||||
link(h, store, c, "42", c.now().Add(-2*time.Hour))
|
||||
submit(t, h, "mesh-delivery", heldAsk(c, "d-1"))
|
||||
settle(h, c)
|
||||
release := ticketFor(tg.sends[0], "Release")
|
||||
first := choiceOf(release, "42", c.now())
|
||||
first.ID = "tg-tap-1"
|
||||
if out, err := h.Chosen("telegram", first); err != nil || out != "chosen" {
|
||||
t.Fatalf("%s %v", out, err)
|
||||
}
|
||||
edits := len(tg.edits)
|
||||
second := choiceOf(release, "42", c.now())
|
||||
second.ID = "tg-tap-2"
|
||||
if out, err := h.Chosen("telegram", second); err != nil || out != "chosen" {
|
||||
t.Fatalf("the second tap: %s %v", out, err)
|
||||
}
|
||||
last := tg.sends[len(tg.sends)-1]
|
||||
if last.Reply != "tg-tap-2" || last.Title != "You already chose Release at 12:00: recorded." {
|
||||
t.Errorf("the second tap was answered %+v", last)
|
||||
}
|
||||
for _, m := range tg.sends {
|
||||
if m.Title == "That answer was not taken" {
|
||||
t.Errorf("a tap on the answer recorded was refused: %+v", m)
|
||||
}
|
||||
}
|
||||
if len(w.of("mesh-delivery")) != 1 || len(tg.edits) != edits {
|
||||
t.Error("the second tap did something more")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user