diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..35b9f6b --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,21 @@ +name: test +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout branch + uses: actions/checkout@v4 + + - name: Setup go + uses: actions/setup-go@v5 + + - name: Install dependencies + run: go get . + + - name: Run test cases + run: go test ./... -v diff --git a/internal/on-going.go b/internal/on_going.go similarity index 97% rename from internal/on-going.go rename to internal/on_going.go index d10f7ff..2780db6 100644 --- a/internal/on-going.go +++ b/internal/on_going.go @@ -8,7 +8,6 @@ import ( "github.com/bruhtus/simo/utils" ) -// TODO: add test case. func OnGoing( statusPath string, duration time.Duration, diff --git a/internal/on_going_test.go b/internal/on_going_test.go new file mode 100644 index 0000000..78afec9 --- /dev/null +++ b/internal/on_going_test.go @@ -0,0 +1,239 @@ +package scmd_test + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "testing" + "time" + + scmd "github.com/bruhtus/simo/internal" + "github.com/bruhtus/simo/utils" +) + +func TestOnGoingEndTime(t *testing.T) { + durationCases := []time.Duration{ + time.Duration(0 * time.Second), + time.Duration(1 * time.Second), + time.Duration(1 * time.Minute), + time.Duration(1 * time.Hour), + } + + endTimeCases := []struct { + duration time.Duration + output time.Time + }{ + { + durationCases[0], + time. + Now(). + Add(durationCases[0]). + Round(time.Second), + }, + { + durationCases[1], + time. + Now(). + Add(durationCases[1]). + Round(time.Second), + }, + { + durationCases[2], + time. + Now(). + Add(durationCases[2]). + Round(time.Second), + }, + { + durationCases[3], + time. + Now(). + Add(durationCases[3]). + Round(time.Second), + }, + } + + t.Run("Status file exist", func(t *testing.T) { + var ( + dirPath = t.TempDir() + file = utils.TestSetupTempFile(t, dirPath) + ) + + t.Cleanup(func() { + err := file.Close() + if err != nil { + t.Fatalf( + "Failed to close file: %v", + err, + ) + } + }) + + for _, tt := range endTimeCases { + t.Run( + tt.duration.String(), + func(t *testing.T) { + status := utils.Status{ + State: utils.StateFocus, + IsNotify: true, + PausePoint: nil, + } + + utils.TestSetupStatusFile(t, status, file) + + scmd.OnGoing( + file.Name(), + tt.duration, + utils.StateFocus, + true, + true, + ) + + resultJSON := utils.ReadStatusFile(file.Name()) + endTime := resultJSON.EndTime.Round(time.Second) + + comparation := endTime.Compare(tt.output) + + if comparation != 0 { + t.Errorf( + "Got %v, want %v. Compare result: %d", + endTime, + tt.output, + comparation, + ) + } + }, + ) + } + }) + + t.Run("Status file not exist", func(t *testing.T) { + dirPath := t.TempDir() + + filePath := fmt.Sprintf( + "%s/simo-%d.json", + dirPath, + time.Now().UnixMilli(), + ) + + for _, tt := range endTimeCases { + t.Run( + tt.duration.String(), + func(t *testing.T) { + _, err := os.Stat(filePath) + + if err != nil && !errors.Is(err, os.ErrNotExist) { + t.Fatalf( + "Error read status file: %v", + err, + ) + } + + scmd.OnGoing( + filePath, + tt.duration, + utils.StateFocus, + true, + true, + ) + + resultJSON := utils.ReadStatusFile(filePath) + endTime := resultJSON.EndTime.Round(time.Second) + + t.Cleanup(func() { + // Reset the end time so that it become expired. + if !errors.Is(err, os.ErrNotExist) { + resultJSON.EndTime = time.Now() + statusJSON, err := json.Marshal(resultJSON) + + if err != nil { + t.Fatalf( + "Error json marshal existing status file: %v", + err, + ) + } + + utils.WriteStatusFile(filePath, statusJSON) + } + }) + + comparation := endTime.Compare(tt.output) + + if comparation != 0 { + t.Errorf( + "Got %v, want %v. Compare result: %d", + endTime, + tt.output, + comparation, + ) + } + }, + ) + } + }) +} + +func TestOnGoingIsNotify(t *testing.T) { + isNotifyCases := []struct { + inputUseNotify bool + inputNotifyCmdExist bool + output bool + }{ + {true, true, true}, + {false, true, false}, + {true, false, false}, + {false, false, false}, + } + + var ( + dirPath = t.TempDir() + file = utils.TestSetupTempFile(t, dirPath) + ) + + t.Cleanup(func() { + err := file.Close() + if err != nil { + t.Fatalf( + "Failed to close file: %v", + err, + ) + } + }) + + for _, tt := range isNotifyCases { + t.Run( + fmt.Sprintf( + "isUseNotify %t, isNotifyCmdExist %t", + tt.inputUseNotify, tt.inputNotifyCmdExist, + ), + func(t *testing.T) { + status := utils.Status{ + State: utils.StateFocus, + IsNotify: true, + PausePoint: nil, + } + + utils.TestSetupStatusFile(t, status, file) + + scmd.OnGoing( + file.Name(), + time.Duration(0*time.Second), + utils.StateFocus, + tt.inputUseNotify, + tt.inputNotifyCmdExist, + ) + + resultJSON := utils.ReadStatusFile(file.Name()) + + if resultJSON.IsNotify != tt.output { + t.Errorf( + "Got %v, want %v", + resultJSON.IsNotify, + tt.output, + ) + } + }, + ) + } +} diff --git a/internal/pause.go b/internal/pause.go index e119604..63b0c18 100644 --- a/internal/pause.go +++ b/internal/pause.go @@ -8,7 +8,6 @@ import ( "github.com/bruhtus/simo/utils" ) -// TODO: add test case. func Pause(statusPath string) { var ( status = utils.ReadStatusFile(statusPath) diff --git a/internal/pause_test.go b/internal/pause_test.go new file mode 100644 index 0000000..ae70aea --- /dev/null +++ b/internal/pause_test.go @@ -0,0 +1,77 @@ +package scmd_test + +import ( + "testing" + "time" + + scmd "github.com/bruhtus/simo/internal" + "github.com/bruhtus/simo/utils" +) + +func TestPause(t *testing.T) { + dirPath := t.TempDir() + file := utils.TestSetupTempFile(t, dirPath) + + t.Cleanup(func() { + err := file.Close() + if err != nil { + t.Fatalf( + "Failed to close file: %v", + err, + ) + } + }) + + remainingDurationCases := []struct { + duration time.Duration + remainingDurationOutput string + isNotifyInput bool + isNotifyOutput bool + }{ + { + time.Duration(1 * time.Second), "0m1s", + true, true, + }, + { + time.Duration(1 * time.Minute), "1m0s", + false, false, + }, + { + time.Duration(1 * time.Hour), "60m0s", + true, true, + }, + } + + for _, tt := range remainingDurationCases { + t.Run( + tt.duration.String(), + func(t *testing.T) { + status := utils.Status{ + State: utils.StateFocus, + IsNotify: tt.isNotifyInput, + PausePoint: nil, + EndTime: time.Now().Add(tt.duration), + } + + utils.TestSetupStatusFile(t, status, file) + scmd.Pause(file.Name()) + + resultJSON := utils.ReadStatusFile(file.Name()) + if resultJSON.PausePoint == nil { + t.Errorf( + "Got nil, want %s", + tt.remainingDurationOutput, + ) + } + + if resultJSON.IsNotify != tt.isNotifyOutput { + t.Errorf( + "Got %t, want %t", + tt.isNotifyInput, + tt.isNotifyOutput, + ) + } + }, + ) + } +} diff --git a/internal/reset.go b/internal/reset.go index 886436c..3d40963 100644 --- a/internal/reset.go +++ b/internal/reset.go @@ -5,7 +5,6 @@ import ( "os" ) -// TODO: add test case. func Reset(statusPath string) error { err := os.Remove(statusPath) diff --git a/internal/status_test.go b/internal/status_test.go new file mode 100644 index 0000000..4544c23 --- /dev/null +++ b/internal/status_test.go @@ -0,0 +1,118 @@ +package scmd_test + +import ( + "testing" + "time" + + scmd "github.com/bruhtus/simo/internal" + "github.com/bruhtus/simo/utils" +) + +func TestStatusPause(t *testing.T) { + dirPath := t.TempDir() + file := utils.TestSetupTempFile(t, dirPath) + + t.Cleanup(func() { + err := file.Close() + if err != nil { + t.Fatalf( + "Failed to close file: %v", + err, + ) + } + }) + + pausePointCases := []struct { + input string + output string + }{ + {"0m1s", "PF00:01"}, + {"1m0s", "PF01:00"}, + {"60m0s", "PF60:00"}, + } + + for _, tt := range pausePointCases { + t.Run( + tt.input, + func(t *testing.T) { + remainingDuration, err := time.ParseDuration( + tt.input, + ) + + if err != nil { + t.Fatalf( + "Error parsing duration: %v", + err, + ) + } + + status := utils.Status{ + State: utils.StateFocus, + IsNotify: false, + PausePoint: &tt.input, + EndTime: time.Now().Add(remainingDuration), + } + + utils.TestSetupStatusFile(t, status, file) + currentStatus := scmd.Status(file.Name(), "notify-send") + + if currentStatus != tt.output { + t.Errorf( + "Got %s, want %s", + currentStatus, tt.output, + ) + } + }, + ) + } +} + +func TestStatusRemainingDuration(t *testing.T) { + dirPath := t.TempDir() + file := utils.TestSetupTempFile(t, dirPath) + + t.Cleanup(func() { + err := file.Close() + if err != nil { + t.Fatalf( + "Failed to close file: %v", + err, + ) + } + }) + + remainingDurationCases := []struct { + duration time.Duration + output string + }{ + {time.Duration(-1 * time.Second), "--:--"}, + {time.Duration(0 * time.Second), "--:--"}, + {time.Duration(1 * time.Second), "F00:01"}, + {time.Duration(1 * time.Minute), "F01:00"}, + {time.Duration(1 * time.Hour), "F60:00"}, + } + + for _, tt := range remainingDurationCases { + t.Run( + tt.duration.String(), + func(t *testing.T) { + status := utils.Status{ + State: utils.StateFocus, + IsNotify: false, + PausePoint: nil, + EndTime: time.Now().Add(tt.duration), + } + + utils.TestSetupStatusFile(t, status, file) + currentStatus := scmd.Status(file.Name(), "notify-send") + + if currentStatus != tt.output { + t.Errorf( + "Got %s, want %s", + currentStatus, tt.output, + ) + } + }, + ) + } +} diff --git a/utils/test.go b/utils/test.go new file mode 100644 index 0000000..034fed8 --- /dev/null +++ b/utils/test.go @@ -0,0 +1,66 @@ +package utils + +import ( + "encoding/json" + "os" + "testing" +) + +func TestSetupTempFile( + t *testing.T, + dirPath string, +) *os.File { + t.Helper() + + file, err := os.CreateTemp(dirPath, "simo-*.json") + if err != nil { + t.Fatalf( + "Failed to create temporary file: %v", + err, + ) + } + + return file +} + +func TestSetupStatusFile( + t *testing.T, + status Status, + file *os.File, +) { + t.Helper() + + statusJSON, err := json.Marshal(status) + if err != nil { + t.Fatalf( + "Failed to marshal status json: %v", + err, + ) + } + + _, err = file.Write(statusJSON) + if err != nil { + t.Fatalf( + "Failed to write data into temporary file: %v", + err, + ) + } + + t.Cleanup(func() { + err := file.Truncate(0) + if err != nil { + t.Fatalf( + "Failed to truncate file: %v", + err, + ) + } + + _, err = file.Seek(0, 0) // Seek the beginning of the file. + if err != nil { + t.Fatalf( + "Failed to seek the begining of file: %v", + err, + ) + } + }) +} diff --git a/utils/time_test.go b/utils/time_test.go index 28745bc..bac762a 100644 --- a/utils/time_test.go +++ b/utils/time_test.go @@ -31,7 +31,7 @@ func TestIsExpired(t *testing.T) { output := utils.DetermineIsExpired(tt.endTime) if output != tt.output { t.Errorf( - "got %t, want %t", + "Got %t, want %t", output, tt.output, ) } @@ -67,7 +67,7 @@ func TestGetDurationMinutesAndSeconds(t *testing.T) { if output != tt.output { t.Errorf( - "got %s, want %s", + "Got %s, want %s", output, tt.output, ) } @@ -100,7 +100,7 @@ func TestRemainingDuration(t *testing.T) { if output != tt.output { t.Errorf( - "got %s, want %s", + "Got %s, want %s", output, tt.output, ) }