github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/hud/prompt/prompt_test.go (about)

     1  package prompt
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"io"
     7  	"net/url"
     8  	"reflect"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  
    14  	"github.com/tilt-dev/tilt/internal/store"
    15  	"github.com/tilt-dev/tilt/internal/testutils"
    16  	"github.com/tilt-dev/tilt/internal/testutils/bufsync"
    17  	"github.com/tilt-dev/tilt/pkg/model"
    18  )
    19  
    20  const FakeURL = "http://localhost:10350/"
    21  
    22  func TestOpenBrowser(t *testing.T) {
    23  	f := newFixture(t)
    24  
    25  	_ = f.prompt.OnChange(f.ctx, f.st, store.LegacyChangeSummary())
    26  
    27  	assert.Contains(t, f.out.String(), "(space) to open the browser")
    28  
    29  	f.input.nextRune <- ' '
    30  	assert.Equal(t, FakeURL, f.b.WaitForURL(t))
    31  }
    32  
    33  func TestOpenStream(t *testing.T) {
    34  	f := newFixture(t)
    35  
    36  	_ = f.prompt.OnChange(f.ctx, f.st, store.LegacyChangeSummary())
    37  
    38  	assert.Contains(t, f.out.String(), "(s) to stream logs")
    39  
    40  	f.input.nextRune <- 's'
    41  
    42  	action := f.st.WaitForAction(t, reflect.TypeOf(SwitchTerminalModeAction{}))
    43  	assert.Equal(t, SwitchTerminalModeAction{Mode: store.TerminalModeStream}, action)
    44  }
    45  
    46  func TestOpenHUD(t *testing.T) {
    47  	f := newFixture(t)
    48  
    49  	_ = f.prompt.OnChange(f.ctx, f.st, store.LegacyChangeSummary())
    50  
    51  	assert.Contains(t, f.out.String(), "(t) to open legacy terminal mode")
    52  
    53  	f.input.nextRune <- 't'
    54  
    55  	action := f.st.WaitForAction(t, reflect.TypeOf(SwitchTerminalModeAction{}))
    56  	assert.Equal(t, SwitchTerminalModeAction{Mode: store.TerminalModeHUD}, action)
    57  }
    58  
    59  func TestInitOutput(t *testing.T) {
    60  	f := newFixture(t)
    61  
    62  	f.prompt.SetInitOutput(bytes.NewBuffer([]byte("this is a warning\n")))
    63  	_ = f.prompt.OnChange(f.ctx, f.st, store.LegacyChangeSummary())
    64  
    65  	assert.Contains(t, f.out.String(), `this is a warning
    66  
    67  (space) to open the browser`)
    68  }
    69  
    70  type fixture struct {
    71  	ctx    context.Context
    72  	cancel func()
    73  	out    *bufsync.ThreadSafeBuffer
    74  	st     *store.TestingStore
    75  	b      *fakeBrowser
    76  	input  *fakeInput
    77  	prompt *TerminalPrompt
    78  }
    79  
    80  func newFixture(t *testing.T) *fixture {
    81  	ctx, _, ta := testutils.CtxAndAnalyticsForTest()
    82  	ctx, cancel := context.WithCancel(ctx)
    83  	out := bufsync.NewThreadSafeBuffer()
    84  	st := store.NewTestingStore()
    85  	st.WithState(func(state *store.EngineState) {
    86  		state.TerminalMode = store.TerminalModePrompt
    87  	})
    88  	i := &fakeInput{ctx: ctx, nextRune: make(chan rune)}
    89  	b := &fakeBrowser{url: make(chan string)}
    90  	openInput := OpenInput(func() (TerminalInput, error) { return i, nil })
    91  
    92  	url, _ := url.Parse(FakeURL)
    93  
    94  	prompt := NewTerminalPrompt(ta, openInput, b.OpenURL, out, "localhost", model.WebURL(*url))
    95  	ret := &fixture{
    96  		ctx:    ctx,
    97  		cancel: cancel,
    98  		out:    out,
    99  		st:     st,
   100  		input:  i,
   101  		b:      b,
   102  		prompt: prompt,
   103  	}
   104  
   105  	t.Cleanup(ret.TearDown)
   106  
   107  	return ret
   108  }
   109  
   110  func (f *fixture) TearDown() {
   111  	f.cancel()
   112  }
   113  
   114  type fakeInput struct {
   115  	ctx      context.Context
   116  	nextRune chan rune
   117  }
   118  
   119  func (i *fakeInput) Close() error { return nil }
   120  
   121  func (i *fakeInput) ReadRune() (rune, error) {
   122  	select {
   123  	case r := <-i.nextRune:
   124  		return r, nil
   125  	case <-i.ctx.Done():
   126  		return 0, i.ctx.Err()
   127  	}
   128  }
   129  
   130  type fakeBrowser struct {
   131  	url chan string
   132  }
   133  
   134  func (b *fakeBrowser) WaitForURL(t *testing.T) string {
   135  	select {
   136  	case <-time.After(time.Second):
   137  		t.Fatal("timeout waiting for url")
   138  		return ""
   139  	case url := <-b.url:
   140  		return url
   141  	}
   142  }
   143  
   144  func (b *fakeBrowser) OpenURL(url string, w io.Writer) error {
   145  	b.url <- url
   146  	return nil
   147  }