Hide cursor and fix dots (#217)

* Hide cursor and fix dots spinner

* Allow restarting of spinner

* Don't spin on non TTY output

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2022-10-21 14:26:42 +02:00 committed by GitHub
parent 56981a709e
commit c82d5ccba9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 118 additions and 102 deletions

View file

@ -10,7 +10,6 @@ import (
"bytes"
"fmt"
"strings"
"sync/atomic"
"testing"
"time"
@ -18,90 +17,91 @@ import (
)
const (
baseWait = 1
baseWait = 100
baseText = "Loading"
)
func TestSpinnerInitialState(t *testing.T) {
assert := assert.New(t)
cmd := NewInitCmd()
var out bytes.Buffer
cmd.SetOut(&out)
var errOut bytes.Buffer
cmd.SetErr(&errOut)
out := &bytes.Buffer{}
s, _ := newSpinner(cmd, nil)
s := newSpinner(out)
s.delay = time.Millisecond * 10
s.spinFunc = spinTTY
s.Start(baseText, true)
time.Sleep(baseWait * time.Second)
time.Sleep(baseWait * time.Millisecond)
s.Stop()
assert.True(out.Len() > 0)
assert.True(errOut.Len() == 0)
assert.Greater(out.Len(), 0)
outStr := out.String()
assert.True(strings.HasPrefix(outStr, generateAllStatesAsString(baseText, true)))
assert.True(strings.HasPrefix(outStr, hideCursor+generateAllStatesAsString(t, baseText, true)))
}
func TestSpinnerFinalState(t *testing.T) {
assert := assert.New(t)
out := &bytes.Buffer{}
cmd := NewInitCmd()
var out bytes.Buffer
cmd.SetOut(&out)
var errOut bytes.Buffer
cmd.SetErr(&errOut)
s, _ := newSpinner(cmd, nil)
s := newSpinner(out)
s.delay = time.Millisecond * 10
s.spinFunc = spinTTY
s.Start(baseText, true)
time.Sleep(baseWait * time.Second)
time.Sleep(baseWait * time.Millisecond)
s.Stop()
assert.True(out.Len() > 0)
assert.True(errOut.Len() == 0)
assert.Greater(out.Len(), 0)
outStr := out.String()
assert.True(strings.HasSuffix(outStr, baseText+"... \n"))
assert.True(strings.HasSuffix(outStr, baseText+"... \n"+showCursor))
}
func TestSpinnerDisabledShowDotsFlag(t *testing.T) {
assert := assert.New(t)
out := &bytes.Buffer{}
cmd := NewInitCmd()
var out bytes.Buffer
cmd.SetOut(&out)
var errOut bytes.Buffer
cmd.SetErr(&errOut)
s, _ := newSpinner(cmd, nil)
s := newSpinner(out)
s.delay = time.Millisecond * 10
s.spinFunc = spinTTY
s.Start(baseText, false)
time.Sleep(baseWait * time.Second)
time.Sleep(baseWait * time.Millisecond)
s.Stop()
assert.True(out.Len() > 0)
assert.True(errOut.Len() == 0)
outStr := out.String()
assert.True(strings.HasPrefix(outStr, generateAllStatesAsString(baseText, false)))
assert.True(strings.HasSuffix(outStr, baseText+" \n"))
assert.True(strings.HasPrefix(outStr, hideCursor+generateAllStatesAsString(t, baseText, false)))
assert.True(strings.HasSuffix(outStr, baseText+" \n"+showCursor))
}
func TestSpinnerInterruptWriter(t *testing.T) {
assert := assert.New(t)
cmd := NewInitCmd()
var out bytes.Buffer
cmd.SetOut(&out)
var errOut bytes.Buffer
cmd.SetErr(&errOut)
out := &bytes.Buffer{}
s, interruptWriter := newSpinner(cmd, &out)
s := newSpinner(out)
s.spinFunc = spinTTY
s.Start(baseText, false)
time.Sleep(200 * time.Millisecond)
_, err := interruptWriter.Write([]byte("test"))
_, err := s.Write([]byte("test"))
assert.NoError(err)
assert.Equal(int32(1), atomic.LoadInt32(&s.stop))
assert.True(strings.HasSuffix(out.String(), "test"))
}
func generateAllStatesAsString(text string, showDots bool) string {
func TestSpinNoTTY(t *testing.T) {
assert := assert.New(t)
out := &bytes.Buffer{}
s := newSpinner(out)
s.spinFunc = spinNoTTY
s.Start(baseText, true)
time.Sleep(baseWait * time.Millisecond)
s.Stop()
assert.Greater(out.Len(), 0)
assert.Equal(baseText+"...\n", out.String())
}
func generateAllStatesAsString(t *testing.T, text string, showDots bool) string {
t.Helper()
var builder strings.Builder
for i := 0; i < len(spinnerStates); i++ {