Skip to content

Commit

Permalink
Add unit tests (#24)
Browse files Browse the repository at this point in the history
* Add test data submodules

* return error instead of log.Fatal

* modify local since variable instead of the glabal one

* create setTimeFlags func

* handle setTimeFlags

* add unit tests

* remove submodules

* update expected results in tests for stats.go

* add script to setup test data

* add test workflow
  • Loading branch information
knbr13 authored Feb 19, 2024
1 parent 8df6933 commit 23a2be3
Show file tree
Hide file tree
Showing 11 changed files with 774 additions and 34 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Go Test

on:
pull_request:
branches:
- main

jobs:
test:
name: Test
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.22

- name: chmod
run: chmod +x ./setup-test.sh

- name: setup tests
run: ./setup-test.sh

- name: Run tests
run: go test ./...
8 changes: 3 additions & 5 deletions input.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,21 @@ package main
import (
"bufio"
"fmt"
"os"
"strings"

"github.com/gookit/color"
)

func getPathFromUser(reader *bufio.Reader) string {
func getPathFromUser(reader *bufio.Reader) (string, error) {
for {
fmt.Print("enter the folder path to scan for Git repositories: ")
input, err := reader.ReadString('\n')
if err != nil {
fmt.Fprintf(os.Stderr, "gitcs: error reading input: %s\n", err.Error())
os.Exit(1)
return "", err
}
input = strings.TrimSpace(input)
if isValidFolderPath(input) {
return input
return input, nil
}
fmt.Println(color.Yellow.Sprintf("gitcs: path %q is not found, please enter a valid folder path", input))
}
Expand Down
43 changes: 43 additions & 0 deletions input_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

import (
"bufio"
"strings"
"testing"
)

func TestGetPathFromUser(t *testing.T) {
testCases := []struct {
description string
input string
expectedPath string
expectedError bool
}{
{
description: "Valid folder path",
input: "./test_data",
expectedPath: "./test_data",
expectedError: false,
},
{
description: "Invalid folder path",
input: "./path/to/invalid/folder",
expectedPath: "./",
expectedError: true,
},
}

for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
reader := bufio.NewReader(strings.NewReader(tc.input + "\n"))
actualPath, err := getPathFromUser(reader)
if err != nil && !tc.expectedError {
t.Errorf("getPathFromUser() error = %v, want %v", err, tc.expectedError)
}

if !tc.expectedError && actualPath != tc.expectedPath {
t.Errorf("Expected path: %s, got: %s", tc.expectedPath, actualPath)
}
})
}
}
35 changes: 10 additions & 25 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bufio"
"flag"
"fmt"
"net/mail"
"os"
"strings"
"time"
Expand All @@ -23,37 +22,23 @@ func main() {
flag.StringVar(&email, "email", strings.TrimSpace(getGlobalEmailFromGit()), "you Git email")
flag.Parse()

var err error
if untilflag != "" {
until, err = time.Parse("2006-01-02", untilflag)
if err != nil {
fmt.Fprintln(os.Stderr, color.Red.Sprintf("gitcs: invalid 'until' date format. please use the format: 2006-01-02"))
os.Exit(1)
}
if until.After(now) {
until = now
}
} else {
until = now
}
if sinceflag != "" {
since, err = time.Parse("2006-01-02", sinceflag)
if err != nil {
fmt.Fprintln(os.Stderr, color.Red.Sprintf("gitcs: invalid 'since' date format. please use the format: 2006-01-02"))
os.Exit(1)
}
} else {
since = time.Date(until.Year(), until.Month(), until.Day(), 0, 0, 0, 0, until.Location()).AddDate(0, 0, -sixMonthsInDays)
err := setTimeFlags(sinceflag, untilflag)
if err != nil {
fmt.Fprint(os.Stderr, color.Red.Sprintf("gitcs: %s\n", err.Error()))
os.Exit(1)
}

_, err = mail.ParseAddress(strings.TrimSpace(email))
if err != nil {
if valid := isValidEmail(email); !valid {
fmt.Fprintln(os.Stderr, color.Red.Sprintf("gitcs: invalid 'email' address"))
os.Exit(1)
}

reader := bufio.NewReader(os.Stdin)
folder := getPathFromUser(reader)
folder, err := getPathFromUser(reader)
if err != nil {
fmt.Fprint(os.Stderr, color.Red.Sprintf("gitcs: error reading input: %s\n", err.Error()))
os.Exit(1)
}

s := spinner.New(spinner.CharSets[6], 100*time.Millisecond, spinner.WithSuffix(" loading..."))

Expand Down
10 changes: 6 additions & 4 deletions print.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,28 @@ func getDay(i int) string {
}

func printTable(commits map[int]int) {
fmt.Printf("%s %s\n", sixEmptySpaces, buildHeader(since, until))
max := getMaxValue(commits)
for since.Weekday() != time.Sunday {
since = since.AddDate(0, 0, -1)
}
for until.Weekday() != time.Saturday {
until = until.AddDate(0, 0, 1)
}

fmt.Printf("%s %s\n", sixEmptySpaces, buildHeader(since, until))
max := getMaxValue(commits)

s := strings.Builder{}
s1 := since

for i := 0; i < 7; i++ {
s.WriteString(fmt.Sprintf("%-5s", getDay(i)))
sn2 := since
sn2 := s1
for !sn2.After(until) {
d := daysAgo(sn2)
s.WriteString(printCell(commits[d], max))
sn2 = sn2.AddDate(0, 0, 7)
}
since = since.AddDate(0, 0, 1)
s1 = s1.AddDate(0, 0, 1)
fmt.Println(s.String())
s.Reset()
}
Expand Down
199 changes: 199 additions & 0 deletions print_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package main

import (
"fmt"
"io"
"os"
"strings"
"testing"
"time"

"github.com/gookit/color"
)

func TestGetDay(t *testing.T) {
tests := []struct {
name string
day int
want string
}{
{
name: "Monday",
day: 1,
want: "Mon",
},
{
name: "Wednesday",
day: 3,
want: "Wed",
},
{
name: "Friday",
day: 5,
want: "Fri",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getDay(tt.day); got != tt.want {
t.Errorf("getDay() = %v, want %v", got, tt.want)
}
})
}
}

func TestBuildHeader(t *testing.T) {
type args struct {
start time.Time
end time.Time
}
tests := []struct {
name string
args args
want string
}{
{
name: "test 1",
args: args{
start: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
end: time.Date(2023, 2, 1, 0, 0, 0, 0, time.UTC),
},
want: "Jan Feb ",
},
{
name: "test 2",
args: args{
start: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
end: time.Date(2023, 3, 1, 0, 0, 0, 0, time.UTC),
},
want: "Jan Feb Mar ",
},
{
name: "test 2",
args: args{
start: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC),
end: time.Date(2023, 5, 1, 0, 0, 0, 0, time.UTC),
},
want: "Jan Feb Mar Apr May ",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := buildHeader(tt.args.start, tt.args.end); got != tt.want {
t.Errorf("buildHeader() = %v, want %v", got, tt.want)
}
})
}
}

func TestPrintCell(t *testing.T) {
testCases := []struct {
description string
val int
maxValue int
expectedMessage string
}{
{
description: "Zero value (/8)",
val: 0,
maxValue: 10,
expectedMessage: color.New(color.FgWhite, color.BgBlack).Sprintf(" - "),
},
{
description: "Lower bound value (/4)",
val: 2,
maxValue: 10,
expectedMessage: color.New(color.FgBlack, color.BgLightCyan).Sprintf(" 2 "),
},
{
description: "Middle value (/2)",
val: 4,
maxValue: 10,
expectedMessage: color.New(color.FgBlack, color.BgHiBlue).Sprintf(" 4 "),
},
{
description: "Upper bound value 1",
val: 8,
maxValue: 10,
expectedMessage: color.New(color.FgBlack, color.BgBlue).Sprintf(" 8 "),
},
{
description: "Upper bound value 2",
val: 10,
maxValue: 10,
expectedMessage: color.New(color.FgBlack, color.BgBlue).Sprintf(" 10 "),
},
}

for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
actualMessage := printCell(tc.val, tc.maxValue)
if actualMessage != tc.expectedMessage {
t.Errorf("Expected message: %s, got: %s", tc.expectedMessage, actualMessage)
}
})
}
}

func TestPrintTable(t *testing.T) {
commits := map[int]int{
0: 5,
1: 8,
2: 12,
3: 3,
4: 0,
5: 10,
6: 7,
7: 4,
8: 6,
9: 9,
10: 2,
11: 15,
12: 1,
13: 0,
}

since = time.Date(2024, 2, 7, 0, 0, 0, 0, time.UTC)
until = time.Date(2024, 2, 19, 0, 0, 0, 0, time.UTC)

oldStdout := os.Stdout
r, w, _ := os.Pipe()
os.Stdout = w

printTable(commits)
w.Close()

dat, err := io.ReadAll(r)
if err != nil {
t.Errorf("Error reading from pipe: %s", err.Error())
}

os.Stdout = oldStdout

var buf strings.Builder
_, _ = fmt.Fprint(&buf, string(dat))

s := strings.Builder{}
s1 := since

s.WriteString(fmt.Sprintf("%s %s\n", sixEmptySpaces, buildHeader(since, until)))

max := getMaxValue(commits)
for i := 0; i < 7; i++ {
s.WriteString(fmt.Sprintf("%-5s", getDay(i)))
sn2 := s1
for !sn2.After(until) {
d := daysAgo(sn2)
s.WriteString(printCell(commits[d], max))
sn2 = sn2.AddDate(0, 0, 7)
}
s1 = s1.AddDate(0, 0, 1)
s.WriteRune('\n')
}

expectedOutput := s.String()
if strings.TrimSpace(buf.String()) != strings.TrimSpace(expectedOutput) {
t.Errorf("Expected output: %q\n\n, got: %q", expectedOutput, buf.String())
}

}
Loading

0 comments on commit 23a2be3

Please sign in to comment.