From c0faf8009fd42f56490d573b575497ee1ea7266d Mon Sep 17 00:00:00 2001 From: Crismar Mejia Date: Mon, 20 Jun 2022 22:40:45 -0500 Subject: [PATCH] implemented ServerRun(); updated README.md --- README.md | 21 +++++++++++--- cli.go | 36 +++++++++++++++++++++++- cli_test.go | 68 ++++++++++++++++++++++++++++++++++++++++++++++ cmd/server/main.go | 10 +++++++ server_test.go | 20 ++------------ 5 files changed, 133 insertions(+), 22 deletions(-) create mode 100644 cmd/server/main.go diff --git a/README.md b/README.md index fbc2da1..17fe74a 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,17 @@ Is a simple tool to keep track of your habits. It can be run from the command-li Install by running `go install github.com/crmejia/habit/cmd/habit@latest` ### Usage -To start a new habit, for example a daily piano habit, simply type `habit piano` on your terminal. As you repeat your habit daily, -retype `habit piano`. You can have multiple habits at the same time, simply type `habit surfing` to start a new surfing +To start a new habit, for example a daily piano habit, fire up your terminal and type: +``` +$habit piano +Good luck with your new habit 'piano'! Don't forget to do it again tomorrow. +``` +As you repeat your daily habit, log your activity with: +``` +$habit piano +Nice work: you've done the habit 'piano' for 1 days in a row now. Keep it up! +``` +You can have multiple habits at the same time, simply type `habit surfing` to start a new surfing habit. You can list all your streaks with `habit all`. Also, you can create a weekly habit by passing the `weekly` option like so `habit -f weekly piano` ``` @@ -27,8 +36,12 @@ Option Flags: Install by running `go install github.com/crmejia/habit/cmd/server@latest` ### Usage -To start Habit as a server type `habit -s 127.0.0.1:8080`. If no address is provided `127.0.0.1:8080` is set as the -default. Use your browser to talk to the server as follows: +To start Habit as a server type: +``` +$ habit 127.0.0.1:8080 +Starting HTTP server +``` +Use your browser to talk to the server as follows: * To create a new habit or continue your streak type `http://127.0.0.1:8080/?habit=HabitName`. * To list all habits go to `http://127.0.0.1:8080/all`. * By default, habits are created as daily habits. You can specify a weekly habit by passing the `interval=weekly` diff --git a/cli.go b/cli.go index dbb38c8..86fc058 100644 --- a/cli.go +++ b/cli.go @@ -3,6 +3,7 @@ package habit import ( "flag" "fmt" + "github.com/mitchellh/go-homedir" "io" ) @@ -59,7 +60,7 @@ Option Flags:`) } if flagSet.Args()[0] == "all" { - fmt.Fprint(output, controller.GetAllHabits()) + fmt.Fprintln(output, controller.GetAllHabits()) return } @@ -78,6 +79,39 @@ Option Flags:`) fmt.Fprintln(output, h) } +func RunServer(args []string, output io.Writer) { + if len(args) == 0 { + fmt.Fprintln(output, "no address provided") + return + } + if len(args) > 1 { + fmt.Fprintln(output, "too many args provided") + return + } + homeDir, err := homedir.Dir() + if err != nil { + fmt.Fprintln(output, err) + return + } + store, err := OpenDBStore(homeDir + "/.habitTracker.db") + if err != nil { + fmt.Fprintln(output, err) + return + } + controller, err := NewController(store) + if err != nil { + fmt.Fprintln(output, err) + return + } + server, err := NewServer(&controller, args[0]) + if err != nil { + fmt.Fprintln(output, err) + return + } + fmt.Fprintln(output, "Starting HTTP server") + server.Run() +} + func storeFactory(storeType string, dir string) (*Store, error) { var opener func(string) (Store, error) var source string diff --git a/cli_test.go b/cli_test.go index d1b9c21..f7aa228 100644 --- a/cli_test.go +++ b/cli_test.go @@ -2,9 +2,14 @@ package habit_test import ( "bytes" + "fmt" "github.com/crmejia/habit" + "github.com/phayes/freeport" + "io/ioutil" + "net/http" "strings" "testing" + "time" ) func TestRunCLIShowsUsageHelpNoArgs(t *testing.T) { @@ -132,3 +137,66 @@ func TestRunCLIShowsErrorUsageHelpInvalidStoreType(t *testing.T) { t.Errorf("Invalid frecuency should print usage Message got: %s", got) } } + +func TestRunServerShowsErrorOnWrongArgs(t *testing.T) { + t.Parallel() + const noAddressError = "no address provided" + const tooManyArgsError = "too many args provided" + testCases := []struct { + name string + args []string + want string + }{ + {name: "nil args", args: nil, want: noAddressError}, + {name: "empty args", args: []string{}, want: noAddressError}, + {name: "too many args", args: []string{"blah", "blah"}, want: tooManyArgsError}, + } + + for _, tc := range testCases { + got := bytes.Buffer{} + habit.RunServer(tc.args, &got) + if got.String() != tc.want { + t.Errorf("%s should fail with %s, got: %s", tc.name, noAddressError, got.String()) + } + } +} +func TestRunServerStartsServer(t *testing.T) { + t.Parallel() + freePort, err := freeport.GetFreePort() + address := fmt.Sprintf("%s:%d", localHostAddress, freePort) + args := []string{address} + output := bytes.Buffer{} + go habit.RunServer(args, &output) + + address = "http://" + address + "?habit=piano" + resp, err := retryHttpGet(address) + if err != nil { + t.Fatal(err) + } + if resp.StatusCode != http.StatusOK { + t.Errorf("Want Status %d, got: %d", http.StatusNotFound, resp.StatusCode) + } + + want := "piano" + got, err := ioutil.ReadAll(resp.Body) + if err != nil { + t.Errorf("Not able to parse response") + } + if !strings.Contains(string(got), want) { + t.Errorf("want response body to be:\n %s \ngot:\n %s", want, got) + } +} +func retryHttpGet(address string) (*http.Response, error) { + resp, err := http.Get(address) + for err != nil { + switch { + //todo identify correct error or maybe http response code? since it's unavailable API + case strings.Contains(err.Error(), "connection refused"): + time.Sleep(5 * time.Millisecond) + resp, err = http.Get(address) + default: + return resp, err + } + } + return resp, nil +} diff --git a/cmd/server/main.go b/cmd/server/main.go new file mode 100644 index 0000000..eadd497 --- /dev/null +++ b/cmd/server/main.go @@ -0,0 +1,10 @@ +package main + +import ( + "github.com/crmejia/habit" + "os" +) + +func main() { + habit.RunServer(os.Args[1:], os.Stdout) +} diff --git a/server_test.go b/server_test.go index 98908ad..3338c9d 100644 --- a/server_test.go +++ b/server_test.go @@ -9,7 +9,6 @@ import ( "net/http/httptest" "strings" "testing" - "time" ) const ( @@ -231,16 +230,10 @@ func TestServer_RunReturnsBadRequest(t *testing.T) { t.Fatal(err) } go server.Run() - resp, err := http.Get("http://" + address) - for err != nil { - time.Sleep(5 * time.Millisecond) - resp, err = http.Get("http://" + address) - } - if err != nil { - t.Fatal(err) - } + resp, err := retryHttpGet("http://" + address) if err != nil { t.Fatal(err) + } if resp.StatusCode != http.StatusBadRequest { t.Errorf("Want Status %d, got: %d", http.StatusNotFound, resp.StatusCode) @@ -273,15 +266,8 @@ func TestServer_RunReturnsHabit(t *testing.T) { t.Fatal(err) } go server.Run() - resp, err := http.Get("http://" + address + "?habit=piano") + resp, err := retryHttpGet("http://" + address + "?habit=piano") for err != nil { - time.Sleep(5 * time.Millisecond) - resp, err = http.Get("http://" + address) - } - if err != nil { - t.Fatal(err) - } - if err != nil { t.Fatal(err) } if resp.StatusCode != http.StatusOK {