Download
56 lines 2 KiBGoModified 2026-10-31 raw
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
package tui

import (
	"context"
	"strings"
	"testing"
	"time"

	"charm.land/bubbles/v2/textarea"
	tea "charm.land/bubbletea/v2"

	"blinker/internal/tools"
)

// The turn's clock leaves out the time a question waited for the user.
func TestCloseQuestionPausesClock(t *testing.T) {
	start := time.Now().Add(-10 * time.Second)
	m := &Model{started: start, question: &question{shown: time.Now().Add(-4 * time.Second)}}
	m.closeQuestion()
	if m.question != nil {
		t.Error("the question is still up")
	}
	if got := time.Since(m.started).Round(time.Second); got != 6*time.Second {
		t.Errorf("the clock shows %s, want 6s", got)
	}
}

// A question asked while another is up waits, and comes up when that one
// is answered; one whose call has ended meanwhile is denied, not shown.
func TestQuestionsWait(t *testing.T) {
	ask := func(ctx context.Context, title string) questionMsg {
		return questionMsg{ctx: ctx, q: tools.Question{Title: title, Opts: []tools.Option{{Label: "Allow", Allow: true}}}, reply: make(chan tools.Answer, 1)}
	}
	ended, cancel := context.WithCancel(context.Background())
	first, stale, second := ask(context.Background(), "first"), ask(ended, "stale"), ask(context.Background(), "second")
	var m tea.Model = Model{input: textarea.New(), reply: &strings.Builder{}, reasoning: &strings.Builder{}, width: 80}
	for _, q := range []questionMsg{first, stale, second} {
		m, _ = m.Update(q)
	}
	if mm := m.(Model); mm.question == nil || mm.question.q.Title != "first" || len(mm.waiting) != 2 {
		t.Fatalf("question %+v, %d waiting", mm.question, len(mm.waiting))
	}
	cancel()
	mm := m.(Model)
	mm.question.shown = time.Now().Add(-time.Minute) // past questionGrace
	m, _ = mm.Update(tea.KeyPressMsg{Code: tea.KeyEnter})
	if a := <-first.reply; !a.Option.Allow {
		t.Errorf("first answered %+v", a)
	}
	if a := <-stale.reply; a.Option.Allow {
		t.Errorf("the ended question was answered %+v", a)
	}
	if mm := m.(Model); mm.question == nil || mm.question.q.Title != "second" || len(mm.waiting) != 0 {
		t.Errorf("then question %+v, %d waiting", mm.question, len(mm.waiting))
	}
}