Repository: cli/cli
File: pkg/iostreams/iostreams_progress_indicator_test.go (Go)

Code before:
		}
	})

	t.Run("multiple indicators with GH_SPINNER_DISABLED shows current label", func(t *testing.T) {
		console := newTestVirtualTerminal(t)
		io := newTestIOStreams(t, console, true)
		progressIndicatorLabel1 := "downloading happiness"
		progressIndicatorLabel2 := "downloading sadness"
		done := make(chan error)
		go func() {
			_, err := console.ExpectString(progressIndicatorLabel1 + "...")
			require.NoError(t, err)
			_, err = console.ExpectString(progressIndicatorLabel2 + "...")
			done <- err
		}()
		io.StartProgressIndicatorWithLabel(progressIndicatorLabel1)
		defer io.StopProgressIndicator()
		io.StartProgressIndicatorWithLabel(progressIndicatorLabel2)

		select {
		case err := <-done:
			require.NoError(t, err)
		case <-time.After(2 * time.Second):
			t.Fatal("Test timed out waiting for progress indicator")
		}
	})
}

func newTestVirtualTerminal(t *testing.T) *expect.Console {
	t.Helper()

	// Create a PTY and hook up a virtual terminal emulator
	ptm, pts, err := pty.Open()
	require.NoError(t, err)

	term := vt10x.New(vt10x.WithWriter(pts))

	// Create a console via Expect that allows scripting against the terminal
	consoleOpts := []expect.ConsoleOpt{
		expect.WithStdin(ptm),
		expect.WithStdout(term),
		expect.WithCloser(ptm, pts),
		failOnExpectError(t),
		failOnSendError(t),
		expect.WithDefaultTimeout(time.Second),
	}

	console, err := expect.NewConsole(consoleOpts...)
	require.NoError(t, err)
	t.Cleanup(func() { testCloser(t, console) })


Review comment (suggestion):
**question:** can there be multiple, concurrent progress indicators or is this really updating / changing the progress indicator?

I ask because the test name made me think maybe concurrent indicators could be happening but I realize `StartProgressIndicatorWithLabel()` returns early and only updates the prefix:

https://github.com/cli/cli/blob/f283d6d11ce1c3d15c3cf55a93d2c1a6fa1fcdd6/pkg/iostreams/iostreams.go#L289-L309

Code after:
		}
	})

	t.Run("multiple calls to start progress indicator with GH_SPINNER_DISABLED prints additional labels", func(t *testing.T) {
		console := newTestVirtualTerminal(t)
		io := newTestIOStreams(t, console, true)
		progressIndicatorLabel1 := "downloading happiness"
		progressIndicatorLabel2 := "downloading sadness"
		done := make(chan error)
		go func() {
			_, err := console.ExpectString(progressIndicatorLabel1 + "...")
			require.NoError(t, err)
			_, err = console.ExpectString(progressIndicatorLabel2 + "...")
			done <- err
		}()
		io.StartProgressIndicatorWithLabel(progressIndicatorLabel1)
		defer io.StopProgressIndicator()
		io.StartProgressIndicatorWithLabel(progressIndicatorLabel2)

		select {
		case err := <-done:
			require.NoError(t, err)
		case <-time.After(2 * time.Second):
			t.Fatal("Test timed out waiting for progress indicator")
		}
	})
}

func newTestVirtualTerminal(t *testing.T) *expect.Console {
	t.Helper()

	// Create a PTY and hook up a virtual terminal emulator
	ptm, pts, err := pty.Open()
	require.NoError(t, err)

	term := vt10x.New(vt10x.WithWriter(pts))

	// Create a console via Expect that allows scripting against the terminal
	consoleOpts := []expect.ConsoleOpt{
		expect.WithStdin(ptm),
		expect.WithStdout(term),
		expect.WithCloser(ptm, pts),
		failOnExpectError(t),
		failOnSendError(t),
		expect.WithDefaultTimeout(time.Second),
	}

	console, err := expect.NewConsole(consoleOpts...)
	require.NoError(t, err)
	t.Cleanup(func() { testCloser(t, console) })