Skip to content

Commit

Permalink
implemented ServerRun(); updated README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
crmejia committed Jun 21, 2022
1 parent cc8a5ba commit c0faf80
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 22 deletions.
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
```
Expand All @@ -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`
Expand Down
36 changes: 35 additions & 1 deletion cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package habit
import (
"flag"
"fmt"

"github.com/mitchellh/go-homedir"
"io"
)
Expand Down Expand Up @@ -59,7 +60,7 @@ Option Flags:`)
}

if flagSet.Args()[0] == "all" {
fmt.Fprint(output, controller.GetAllHabits())
fmt.Fprintln(output, controller.GetAllHabits())
return
}

Expand All @@ -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
Expand Down
68 changes: 68 additions & 0 deletions cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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
}
10 changes: 10 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

import (
"github.com/crmejia/habit"
"os"
)

func main() {
habit.RunServer(os.Args[1:], os.Stdout)
}
20 changes: 3 additions & 17 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"net/http/httptest"
"strings"
"testing"
"time"
)

const (
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit c0faf80

Please sign in to comment.