Add tests
This commit is contained in:
parent
025ec3f20b
commit
dfd7245a2c
20
main.go
20
main.go
@ -82,6 +82,10 @@ func initialModel(fullscreen bool, colorLeft string, colorRight string) model {
|
|||||||
inputs[2].Placeholder = "Number of intervals"
|
inputs[2].Placeholder = "Number of intervals"
|
||||||
inputs[2].Validate = validateInt
|
inputs[2].Validate = validateInt
|
||||||
|
|
||||||
|
if colorLeft == "" || colorRight == "" {
|
||||||
|
panic("Color values must be provided")
|
||||||
|
}
|
||||||
|
|
||||||
return model{
|
return model{
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
progressBar: progress.New(progress.WithScaledGradient(colorLeft, colorRight)),
|
progressBar: progress.New(progress.WithScaledGradient(colorLeft, colorRight)),
|
||||||
@ -113,18 +117,24 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
switch msg.String() {
|
switch msg.String() {
|
||||||
case "ctrl+c":
|
case "ctrl+c", "esc":
|
||||||
// Gracefully exit
|
// Gracefully exit
|
||||||
return m, tea.Quit
|
return m, tea.Quit
|
||||||
|
|
||||||
case "tab":
|
case "q":
|
||||||
|
// Quit the program if on the timer screen
|
||||||
|
if m.currentScreen == timerScreen {
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
|
||||||
|
case "tab", "ctrl+n", "j", "down":
|
||||||
// Move to the next input field
|
// Move to the next input field
|
||||||
m.focusIndex = (m.focusIndex + 1) % len(m.inputs)
|
m.focusIndex = (m.focusIndex + 1) % len(m.inputs)
|
||||||
m.updateFocus()
|
m.updateFocus()
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
|
|
||||||
case "shift+tab":
|
case "shift+tab", "ctrl+p", "k", "up":
|
||||||
// Move to the previous input field
|
// Move to the previous input field
|
||||||
m.focusIndex = (m.focusIndex - 1 + len(m.inputs)) % len(m.inputs)
|
m.focusIndex = (m.focusIndex - 1 + len(m.inputs)) % len(m.inputs)
|
||||||
m.updateFocus()
|
m.updateFocus()
|
||||||
@ -175,6 +185,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
|
|
||||||
case timeMsg:
|
case timeMsg:
|
||||||
// Handle timer update for each second
|
// Handle timer update for each second
|
||||||
|
// TODO: Use absolute times to tick down remaining time rather than incrementing seconds
|
||||||
m.remaining -= time.Second
|
m.remaining -= time.Second
|
||||||
if m.remaining < 0 {
|
if m.remaining < 0 {
|
||||||
if m.isFocus {
|
if m.isFocus {
|
||||||
@ -389,6 +400,9 @@ func main() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("color-left: %s\n", c.String("color-left"))
|
||||||
|
fmt.Printf("color-right: %s\n", c.String("color-right"))
|
||||||
|
|
||||||
m := initialModel(c.Bool("fullscreen"), c.String("color-left"), c.String("color-right"))
|
m := initialModel(c.Bool("fullscreen"), c.String("color-left"), c.String("color-right"))
|
||||||
|
|
||||||
// Collect command flags
|
// Collect command flags
|
||||||
|
156
main_test.go
Normal file
156
main_test.go
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
)
|
||||||
|
|
||||||
|
// assertEqual checks if two values are equal and reports an error if they are not.
|
||||||
|
func assertEqual(t *testing.T, actual, expected interface{}, msg string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
if actual != expected {
|
||||||
|
t.Errorf("%s: expected %v, got %v", msg, expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// assertNotEqual checks if two values are not equal and reports an error if they are.
|
||||||
|
func assertNotEqual(t *testing.T, actual, expected interface{}, msg string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
if actual == expected {
|
||||||
|
t.Errorf("%s: expected %v to be different from %v", msg, actual, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestParseDuration tests the parseDuration function
|
||||||
|
func TestParseDuration(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
input string
|
||||||
|
expected time.Duration
|
||||||
|
hasError bool
|
||||||
|
}{
|
||||||
|
{"10", 10 * time.Minute, false},
|
||||||
|
{"1h", 1 * time.Hour, false},
|
||||||
|
{"invalid", 0, true},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
result, err := parseDuration(test.input)
|
||||||
|
if test.hasError {
|
||||||
|
assertNotEqual(t, err, nil, "Expected an error for input "+test.input)
|
||||||
|
} else {
|
||||||
|
assertEqual(t, err, nil, "Did not expect an error for input "+test.input)
|
||||||
|
assertEqual(t, result, test.expected, "Expected duration for input "+test.input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestRunCommands tests the runCommands function
|
||||||
|
func TestRunCommands(t *testing.T) {
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect stdout and stderr to the pipe
|
||||||
|
oldStdout := os.Stdout
|
||||||
|
oldStderr := os.Stderr
|
||||||
|
os.Stdout = w
|
||||||
|
os.Stderr = w
|
||||||
|
|
||||||
|
t.Cleanup(func() {
|
||||||
|
os.Stdout = oldStdout
|
||||||
|
os.Stderr = oldStderr
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
m := model{}
|
||||||
|
m.runCommands([]string{"echo Hello, World!"})
|
||||||
|
|
||||||
|
w.Close()
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
if _, err = io.Copy(&buf, r); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := buf.String()
|
||||||
|
assertEqual(t, strings.Contains(output, "Hello, World!"), true, "Expected output to contain 'Hello, World!'")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestInputView tests the Update method of the model for the input view
|
||||||
|
func TestInputView(t *testing.T) {
|
||||||
|
m := initialModel(false, "#ffdd57", "#57ddff")
|
||||||
|
m.View()
|
||||||
|
|
||||||
|
assertEqual(t, m.currentScreen, inputScreen, "Expected currentScreen to be inputScreen")
|
||||||
|
assertEqual(t, m.focusIndex, 0, "Expected focusIndex to be 0")
|
||||||
|
|
||||||
|
m.inputs[m.focusIndex].SetValue("10")
|
||||||
|
|
||||||
|
var msg tea.Msg
|
||||||
|
|
||||||
|
// Test tab key press
|
||||||
|
msg = tea.KeyMsg{Type: tea.KeyTab}
|
||||||
|
updatedModel, _ := m.Update(msg)
|
||||||
|
m = updatedModel.(model)
|
||||||
|
assertEqual(t, m.focusIndex, 1, "Expected focusIndex to be 1")
|
||||||
|
|
||||||
|
// Test shift+tab key press
|
||||||
|
msg = tea.KeyMsg{Type: tea.KeyShiftTab}
|
||||||
|
updatedModel, _ = m.Update(msg)
|
||||||
|
m = updatedModel.(model)
|
||||||
|
assertEqual(t, m.focusIndex, 0, "Expected focusIndex to be 0")
|
||||||
|
|
||||||
|
// Enter last value and test enter key press
|
||||||
|
for i := m.focusIndex; i < 2; i++ {
|
||||||
|
msg = tea.KeyMsg{Type: tea.KeyTab}
|
||||||
|
updatedModel, _ = m.Update(msg)
|
||||||
|
m = updatedModel.(model)
|
||||||
|
m.inputs[m.focusIndex].SetValue("10")
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = tea.KeyMsg{Type: tea.KeyEnter}
|
||||||
|
updatedModel, resultCmd := m.Update(msg)
|
||||||
|
m = updatedModel.(model)
|
||||||
|
|
||||||
|
assertEqual(t, m.err, nil, "Expected no error")
|
||||||
|
assertNotEqual(t, resultCmd, nil, "Expected resultCmd to be not nil")
|
||||||
|
assertEqual(t, m.currentScreen, timerScreen, "Expected currentScreen to be timerScreen")
|
||||||
|
assertEqual(t, m.remaining, 10*time.Minute, "Expected remaining to be 10 minutes")
|
||||||
|
|
||||||
|
// Test timer view
|
||||||
|
m.View()
|
||||||
|
|
||||||
|
oneSec := timeMsg(time.Now().Add(1 * time.Second))
|
||||||
|
updatedModel, _ = m.Update(oneSec)
|
||||||
|
m = updatedModel.(model)
|
||||||
|
|
||||||
|
assertEqual(t, m.state, "Focus", "Expected state to be 'Focus'")
|
||||||
|
assertEqual(t, m.remaining, 9*time.Minute+59*time.Second, "Expected remaining to be 9 minutes 59 seconds")
|
||||||
|
|
||||||
|
// Test switch to break time
|
||||||
|
m.remaining = 0
|
||||||
|
updatedModel, _ = m.Update(oneSec)
|
||||||
|
m = updatedModel.(model)
|
||||||
|
|
||||||
|
assertEqual(t, m.state, "Break", "Expected state to be 'Break'")
|
||||||
|
assertEqual(t, m.remaining, 9*time.Minute+59*time.Second, "Expected remaining to be 9 minutes 59 seconds")
|
||||||
|
|
||||||
|
// Switch back to focus time
|
||||||
|
m.remaining = 0
|
||||||
|
updatedModel, _ = m.Update(oneSec)
|
||||||
|
m = updatedModel.(model)
|
||||||
|
|
||||||
|
assertEqual(t, m.state, "Focus", "Expected state to be 'Focus'")
|
||||||
|
assertEqual(t, m.remaining, 9*time.Minute+59*time.Second, "Expected remaining to be 9 minutes 59 seconds")
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user