mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
Removed some dead code
This commit is contained in:
parent
50a6eb64ec
commit
e3f6f59890
11 changed files with 438 additions and 1135 deletions
1086
coverage.txt
1086
coverage.txt
File diff suppressed because it is too large
Load diff
|
|
@ -56,17 +56,6 @@ func (app *App) Run() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes any resources
|
|
||||||
func (app *App) Close() error {
|
|
||||||
for _, closer := range app.closers {
|
|
||||||
err := closer.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type errorMapping struct {
|
type errorMapping struct {
|
||||||
originalError string
|
originalError string
|
||||||
newError string
|
newError string
|
||||||
|
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"unicode/utf8"
|
|
||||||
|
|
||||||
"github.com/go-errors/errors"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/pty"
|
|
||||||
"github.com/mgutz/str"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RunCommandWithOutputLiveWrapper runs a command and return every word that gets written in stdout
|
|
||||||
// Output is a function that executes by every word that gets read by bufio
|
|
||||||
// As return of output you need to give a string that will be written to stdin
|
|
||||||
// NOTE: If the return data is empty it won't written anything to stdin
|
|
||||||
func RunCommandWithOutputLiveWrapper(c *OSCommand, command string, output func(string) string) error {
|
|
||||||
splitCmd := str.ToArgv(command)
|
|
||||||
cmd := c.command(splitCmd[0], splitCmd[1:]...)
|
|
||||||
|
|
||||||
cmd.Env = os.Environ()
|
|
||||||
cmd.Env = append(cmd.Env, "LANG=en_US.UTF-8", "LC_ALL=en_US.UTF-8")
|
|
||||||
|
|
||||||
var stderr bytes.Buffer
|
|
||||||
cmd.Stderr = &stderr
|
|
||||||
|
|
||||||
ptmx, err := pty.Start(cmd)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
scanner := bufio.NewScanner(ptmx)
|
|
||||||
scanner.Split(scanWordsWithNewLines)
|
|
||||||
for scanner.Scan() {
|
|
||||||
toOutput := strings.Trim(scanner.Text(), " ")
|
|
||||||
_, _ = ptmx.WriteString(output(toOutput))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
err = cmd.Wait()
|
|
||||||
ptmx.Close()
|
|
||||||
if err != nil {
|
|
||||||
return errors.New(stderr.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// scanWordsWithNewLines is a copy of bufio.ScanWords but this also captures new lines
|
|
||||||
// For specific comments about this function take a look at: bufio.ScanWords
|
|
||||||
func scanWordsWithNewLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
|
||||||
start := 0
|
|
||||||
for width := 0; start < len(data); start += width {
|
|
||||||
var r rune
|
|
||||||
r, width = utf8.DecodeRune(data[start:])
|
|
||||||
if !isSpace(r) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for width, i := 0, start; i < len(data); i += width {
|
|
||||||
var r rune
|
|
||||||
r, width = utf8.DecodeRune(data[i:])
|
|
||||||
if isSpace(r) {
|
|
||||||
return i + width, data[start:i], nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if atEOF && len(data) > start {
|
|
||||||
return len(data), data[start:], nil
|
|
||||||
}
|
|
||||||
return start, nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// isSpace is also copied from the bufio package and has been modified to also captures new lines
|
|
||||||
// For specific comments about this function take a look at: bufio.isSpace
|
|
||||||
func isSpace(r rune) bool {
|
|
||||||
if r <= '\u00FF' {
|
|
||||||
switch r {
|
|
||||||
case ' ', '\t', '\v', '\f':
|
|
||||||
return true
|
|
||||||
case '\u0085', '\u00A0':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if '\u2000' <= r && r <= '\u200a' {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
switch r {
|
|
||||||
case '\u1680', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package commands
|
|
||||||
|
|
||||||
// RunCommandWithOutputLiveWrapper runs a command live but because of windows compatibility this command can't be ran there
|
|
||||||
// TODO: Remove this hack and replace it with a proper way to run commands live on windows
|
|
||||||
func RunCommandWithOutputLiveWrapper(c *OSCommand, command string, output func(string) string) error {
|
|
||||||
return c.RunCommand(command)
|
|
||||||
}
|
|
||||||
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
@ -87,36 +86,6 @@ func (c *OSCommand) ExecutableFromString(commandStr string) *exec.Cmd {
|
||||||
return c.command(splitCmd[0], splitCmd[1:]...)
|
return c.command(splitCmd[0], splitCmd[1:]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunCommandWithOutputLive runs RunCommandWithOutputLiveWrapper
|
|
||||||
func (c *OSCommand) RunCommandWithOutputLive(command string, output func(string) string) error {
|
|
||||||
return RunCommandWithOutputLiveWrapper(c, command, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DetectUnamePass detect a username / password question in a command
|
|
||||||
// ask is a function that gets executen when this function detect you need to fillin a password
|
|
||||||
// The ask argument will be "username" or "password" and expects the user's password or username back
|
|
||||||
func (c *OSCommand) DetectUnamePass(command string, ask func(string) string) error {
|
|
||||||
ttyText := ""
|
|
||||||
errMessage := c.RunCommandWithOutputLive(command, func(word string) string {
|
|
||||||
ttyText = ttyText + " " + word
|
|
||||||
|
|
||||||
prompts := map[string]string{
|
|
||||||
"password": `Password\s*for\s*'.+':`,
|
|
||||||
"username": `Username\s*for\s*'.+':`,
|
|
||||||
}
|
|
||||||
|
|
||||||
for askFor, pattern := range prompts {
|
|
||||||
if match, _ := regexp.MatchString(pattern, ttyText); match {
|
|
||||||
ttyText = ""
|
|
||||||
return ask(askFor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
})
|
|
||||||
return errMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunCommand runs a command and just returns the error
|
// RunCommand runs a command and just returns the error
|
||||||
func (c *OSCommand) RunCommand(command string) error {
|
func (c *OSCommand) RunCommand(command string) error {
|
||||||
_, err := c.RunCommandWithOutput(command)
|
_, err := c.RunCommandWithOutput(command)
|
||||||
|
|
|
||||||
|
|
@ -98,10 +98,6 @@ func (gui *Gui) onNewPopupPanel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) createLoaderPanel(g *gocui.Gui, currentView *gocui.View, prompt string) error {
|
|
||||||
return gui.createPopupPanel(g, currentView, "", prompt, true, nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// it is very important that within this function we never include the original prompt in any error messages, because it may contain e.g. a user password
|
// it is very important that within this function we never include the original prompt in any error messages, because it may contain e.g. a user password
|
||||||
func (gui *Gui) createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error {
|
func (gui *Gui) createConfirmationPanel(g *gocui.Gui, currentView *gocui.View, title, prompt string, handleConfirm, handleClose func(*gocui.Gui, *gocui.View) error) error {
|
||||||
return gui.createPopupPanel(g, currentView, title, prompt, false, handleConfirm, handleClose)
|
return gui.createPopupPanel(g, currentView, title, prompt, false, handleConfirm, handleClose)
|
||||||
|
|
@ -148,10 +144,6 @@ func (gui *Gui) setKeyBindings(g *gocui.Gui, handleConfirm, handleClose func(*go
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) createMessagePanel(g *gocui.Gui, currentView *gocui.View, title, prompt string) error {
|
|
||||||
return gui.createPopupPanel(g, currentView, title, prompt, false, nil, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// createSpecificErrorPanel allows you to create an error popup, specifying the
|
// createSpecificErrorPanel allows you to create an error popup, specifying the
|
||||||
// view to be focused when the user closes the popup, and a boolean specifying
|
// view to be focused when the user closes the popup, and a boolean specifying
|
||||||
// whether we will log the error. If the message may include a user password,
|
// whether we will log the error. If the message may include a user password,
|
||||||
|
|
|
||||||
|
|
@ -177,10 +177,6 @@ func NewGui(log *logrus.Entry, dockerCommand *commands.DockerCommand, oSCommand
|
||||||
return gui, nil
|
return gui, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleRefresh(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
return gui.refreshSidePanels(g)
|
|
||||||
}
|
|
||||||
|
|
||||||
func max(a, b int) int {
|
func max(a, b int) int {
|
||||||
if a > b {
|
if a > b {
|
||||||
return a
|
return a
|
||||||
|
|
|
||||||
|
|
@ -144,11 +144,6 @@ func (gui *Gui) switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error {
|
||||||
return gui.newLineFocused(newView)
|
return gui.newLineFocused(newView)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) resetOrigin(v *gocui.View) error {
|
|
||||||
_ = v.SetCursor(0, 0)
|
|
||||||
return v.SetOrigin(0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the cursor down past the last item, move it to the last line
|
// if the cursor down past the last item, move it to the last line
|
||||||
func (gui *Gui) focusPoint(selectedX int, selectedY int, lineCount int, v *gocui.View) error {
|
func (gui *Gui) focusPoint(selectedX int, selectedY int, lineCount int, v *gocui.View) error {
|
||||||
if selectedY < 0 || selectedY > lineCount {
|
if selectedY < 0 || selectedY > lineCount {
|
||||||
|
|
@ -317,28 +312,6 @@ func (gui *Gui) changeSelectedLine(line *int, total int, up bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) refreshSelectedLine(line *int, total int) {
|
|
||||||
if *line == -1 && total > 0 {
|
|
||||||
*line = 0
|
|
||||||
} else if total-1 < *line {
|
|
||||||
*line = total - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) renderListPanel(v *gocui.View, items interface{}) error {
|
|
||||||
gui.g.Update(func(g *gocui.Gui) error {
|
|
||||||
isFocused := gui.g.CurrentView().Name() == v.Name()
|
|
||||||
list, err := utils.RenderList(items, utils.IsFocused(isFocused))
|
|
||||||
if err != nil {
|
|
||||||
return gui.createErrorPanel(gui.g, err.Error())
|
|
||||||
}
|
|
||||||
v.Clear()
|
|
||||||
fmt.Fprint(v, list)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) renderPanelOptions() error {
|
func (gui *Gui) renderPanelOptions() error {
|
||||||
currentView := gui.g.CurrentView()
|
currentView := gui.g.CurrentView()
|
||||||
switch currentView.Name() {
|
switch currentView.Name() {
|
||||||
|
|
@ -348,11 +321,6 @@ func (gui *Gui) renderPanelOptions() error {
|
||||||
return gui.renderGlobalOptions()
|
return gui.renderGlobalOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) handleFocusView(g *gocui.Gui, v *gocui.View) error {
|
|
||||||
_, err := gui.g.SetCurrentView(v.Name())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) isPopupPanel(viewName string) bool {
|
func (gui *Gui) isPopupPanel(viewName string) bool {
|
||||||
return viewName == "confirmation" || viewName == "menu"
|
return viewName == "confirmation" || viewName == "menu"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/mgutz/str"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CommandSwapper takes a command, verifies that it is what it's expected to be
|
|
||||||
// and then returns a replacement command that will actually be called by the os
|
|
||||||
type CommandSwapper struct {
|
|
||||||
Expect string
|
|
||||||
Replace string
|
|
||||||
}
|
|
||||||
|
|
||||||
// SwapCommand verifies the command is what we expected, and swaps it out for a different command
|
|
||||||
func (i *CommandSwapper) SwapCommand(t *testing.T, cmd string, args []string) *exec.Cmd {
|
|
||||||
splitCmd := str.ToArgv(i.Expect)
|
|
||||||
assert.EqualValues(t, splitCmd[0], cmd, fmt.Sprintf("received command: %s %s", cmd, strings.Join(args, " ")))
|
|
||||||
if len(splitCmd) > 1 {
|
|
||||||
assert.EqualValues(t, splitCmd[1:], args, fmt.Sprintf("received command: %s %s", cmd, strings.Join(args, " ")))
|
|
||||||
}
|
|
||||||
|
|
||||||
splitCmd = str.ToArgv(i.Replace)
|
|
||||||
return exec.Command(splitCmd[0], splitCmd[1:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateMockCommand creates a command function that will verify its receiving the right sequence of commands from lazydocker
|
|
||||||
func CreateMockCommand(t *testing.T, swappers []*CommandSwapper) func(cmd string, args ...string) *exec.Cmd {
|
|
||||||
commandIndex := 0
|
|
||||||
|
|
||||||
return func(cmd string, args ...string) *exec.Cmd {
|
|
||||||
var command *exec.Cmd
|
|
||||||
if commandIndex > len(swappers)-1 {
|
|
||||||
assert.Fail(t, fmt.Sprintf("too many commands run. This command was (%s %s)", cmd, strings.Join(args, " ")))
|
|
||||||
}
|
|
||||||
command = swappers[commandIndex].SwapCommand(t, cmd, args)
|
|
||||||
commandIndex++
|
|
||||||
return command
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,6 @@ package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"math"
|
"math"
|
||||||
|
|
@ -59,15 +58,6 @@ func ColoredStringDirect(str string, colour *color.Color) string {
|
||||||
return colour.SprintFunc()(fmt.Sprint(str))
|
return colour.SprintFunc()(fmt.Sprint(str))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TrimTrailingNewline - Trims the trailing newline
|
|
||||||
// TODO: replace with `chomp` after refactor
|
|
||||||
func TrimTrailingNewline(str string) string {
|
|
||||||
if strings.HasSuffix(str, "\n") {
|
|
||||||
return str[:len(str)-1]
|
|
||||||
}
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
// NormalizeLinefeeds - Removes all Windows and Mac style line feeds
|
// NormalizeLinefeeds - Removes all Windows and Mac style line feeds
|
||||||
func NormalizeLinefeeds(str string) string {
|
func NormalizeLinefeeds(str string) string {
|
||||||
str = strings.Replace(str, "\r\n", "\n", -1)
|
str = strings.Replace(str, "\r\n", "\n", -1)
|
||||||
|
|
@ -92,14 +82,6 @@ func ResolvePlaceholderString(str string, arguments map[string]string) string {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
// Min returns the minimum of two integers
|
|
||||||
func Min(x, y int) int {
|
|
||||||
if x < y {
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max returns the maximum of two integers
|
// Max returns the maximum of two integers
|
||||||
func Max(x, y int) int {
|
func Max(x, y int) int {
|
||||||
if x > y {
|
if x > y {
|
||||||
|
|
@ -240,42 +222,6 @@ func getDisplayStringArrays(displayables []Displayable, isFocused bool) [][]stri
|
||||||
return stringArrays
|
return stringArrays
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncludesString if the list contains the string
|
|
||||||
func IncludesString(list []string, a string) bool {
|
|
||||||
for _, b := range list {
|
|
||||||
if b == a {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// NextIndex returns the index of the element that comes after the given number
|
|
||||||
func NextIndex(numbers []int, currentNumber int) int {
|
|
||||||
for index, number := range numbers {
|
|
||||||
if number > currentNumber {
|
|
||||||
return index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrevIndex returns the index that comes before the given number, cycling if we reach the end
|
|
||||||
func PrevIndex(numbers []int, currentNumber int) int {
|
|
||||||
end := len(numbers) - 1
|
|
||||||
for i := end; i >= 0; i -= 1 {
|
|
||||||
if numbers[i] < currentNumber {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return end
|
|
||||||
}
|
|
||||||
|
|
||||||
func AsJson(i interface{}) string {
|
|
||||||
bytes, _ := json.MarshalIndent(i, "", " ")
|
|
||||||
return string(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatBinaryBytes(b int) string {
|
func FormatBinaryBytes(b int) string {
|
||||||
n := float64(b)
|
n := float64(b)
|
||||||
units := []string{"B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
|
units := []string{"B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
|
||||||
|
|
|
||||||
|
|
@ -62,29 +62,6 @@ func TestWithPadding(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestTrimTrailingNewline is a function.
|
|
||||||
func TestTrimTrailingNewline(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
str string
|
|
||||||
expected string
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
"hello world !\n",
|
|
||||||
"hello world !",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"hello world !",
|
|
||||||
"hello world !",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
assert.EqualValues(t, s.expected, TrimTrailingNewline(s.str))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestNormalizeLinefeeds is a function.
|
// TestNormalizeLinefeeds is a function.
|
||||||
func TestNormalizeLinefeeds(t *testing.T) {
|
func TestNormalizeLinefeeds(t *testing.T) {
|
||||||
type scenario struct {
|
type scenario struct {
|
||||||
|
|
@ -403,173 +380,3 @@ func TestGetPadWidths(t *testing.T) {
|
||||||
assert.EqualValues(t, s.expected, getPadWidths(s.stringArrays))
|
assert.EqualValues(t, s.expected, getPadWidths(s.stringArrays))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestMin is a function.
|
|
||||||
func TestMin(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
a int
|
|
||||||
b int
|
|
||||||
expected int
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
2,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
assert.EqualValues(t, s.expected, Min(s.a, s.b))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestIncludesString is a function.
|
|
||||||
func TestIncludesString(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
list []string
|
|
||||||
element string
|
|
||||||
expected bool
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
[]string{"a", "b"},
|
|
||||||
"a",
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
[]string{"a", "b"},
|
|
||||||
"c",
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
[]string{"a", "b"},
|
|
||||||
"",
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
[]string{""},
|
|
||||||
"",
|
|
||||||
true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
assert.EqualValues(t, s.expected, IncludesString(s.list, s.element))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNextIndex(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
testName string
|
|
||||||
list []int
|
|
||||||
element int
|
|
||||||
expected int
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
// I'm not really fussed about how it behaves here
|
|
||||||
"no elements",
|
|
||||||
[]int{},
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"one element",
|
|
||||||
[]int{1},
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"two elements",
|
|
||||||
[]int{1, 2},
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"two elements, giving second one",
|
|
||||||
[]int{1, 2},
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"three elements, giving second one",
|
|
||||||
[]int{1, 2, 3},
|
|
||||||
2,
|
|
||||||
2,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
|
||||||
assert.EqualValues(t, s.expected, NextIndex(s.list, s.element))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrevIndex(t *testing.T) {
|
|
||||||
type scenario struct {
|
|
||||||
testName string
|
|
||||||
list []int
|
|
||||||
element int
|
|
||||||
expected int
|
|
||||||
}
|
|
||||||
|
|
||||||
scenarios := []scenario{
|
|
||||||
{
|
|
||||||
// I'm not really fussed about how it behaves here
|
|
||||||
"no elements",
|
|
||||||
[]int{},
|
|
||||||
1,
|
|
||||||
-1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"one element",
|
|
||||||
[]int{1},
|
|
||||||
1,
|
|
||||||
0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"two elements",
|
|
||||||
[]int{1, 2},
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"three elements, giving second one",
|
|
||||||
[]int{1, 2, 3},
|
|
||||||
2,
|
|
||||||
0,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range scenarios {
|
|
||||||
t.Run(s.testName, func(t *testing.T) {
|
|
||||||
assert.EqualValues(t, s.expected, PrevIndex(s.list, s.element))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAsJson(t *testing.T) {
|
|
||||||
type myStruct struct {
|
|
||||||
a string
|
|
||||||
}
|
|
||||||
|
|
||||||
output := AsJson(&myStruct{a: "foo"})
|
|
||||||
|
|
||||||
// no idea why this is returning empty hashes but it's works in the app ¯\_(ツ)_/¯
|
|
||||||
assert.EqualValues(t, "{}", output)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue