diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..04fc178 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +testhub diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d81f395 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module git.andreafazzi.eu/andrea/testhub + +go 1.17 + +require ( + github.com/kr/pretty v0.2.1 // indirect + github.com/kr/text v0.1.0 // indirect + github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..84250d7 --- /dev/null +++ b/go.sum @@ -0,0 +1,9 @@ +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8 h1:nRDwTcxV9B3elxMt+1xINX0bwaPdpouqp5fbynexY8U= +github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8/go.mod h1:jOEnp79oIHy5cvQSHeLcgVJk1GHOOHJHQWps/d1N5Yo= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/main.go b/main.go new file mode 100644 index 0000000..9c4e081 --- /dev/null +++ b/main.go @@ -0,0 +1,11 @@ +package main + +import ( + "log" + "net/http" +) + +func main() { + server := &PlayerServer{&InMemoryPlayerStore{}} + log.Fatal(http.ListenAndServe(":3000", server)) +} diff --git a/main_test.go b/main_test.go new file mode 100644 index 0000000..1942236 --- /dev/null +++ b/main_test.go @@ -0,0 +1,82 @@ +package main + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/remogatto/prettytest" +) + +// Start of setup +type testSuite struct { + prettytest.Suite +} + +type StubPlayerStore struct { + scores map[string]int + winCalls []string +} + +func (store *StubPlayerStore) GetPlayerScore(player string) int { + return store.scores[player] +} + +func (s *StubPlayerStore) RecordWin(name string) { + s.winCalls = append(s.winCalls, name) +} + +func TestRunner(t *testing.T) { + prettytest.Run( + t, + new(testSuite), + ) +} + +func (t *testSuite) TestGET() { + tests := []struct { + name string + expectedScore string + expectedHTTPStatus int + }{ + {"Pepper", "20", http.StatusOK}, + {"Floyd", "10", http.StatusOK}, + {"Apollo", "0", http.StatusNotFound}, + } + + store := &StubPlayerStore{ + map[string]int{ + "Pepper": 20, + "Floyd": 10, + }, + nil, + } + + server := &PlayerServer{store} + + for _, test := range tests { + request, _ := http.NewRequest(http.MethodGet, "/players/"+test.name, nil) + response := httptest.NewRecorder() + + server.ServeHTTP(response, request) + t.Equal(test.expectedScore, response.Body.String()) + t.Equal(test.expectedHTTPStatus, response.Code) + } + +} + +func (t *testSuite) TestPOST() { + store := StubPlayerStore{ + map[string]int{}, + nil, + } + + server := &PlayerServer{&store} + + request, _ := http.NewRequest(http.MethodPost, "/players/Pepper", nil) + response := httptest.NewRecorder() + + server.ServeHTTP(response, request) + t.Equal(1, len(store.winCalls)) + t.Equal(http.StatusAccepted, response.Code) +} diff --git a/server.go b/server.go new file mode 100644 index 0000000..e4981a4 --- /dev/null +++ b/server.go @@ -0,0 +1,46 @@ +package main + +import ( + "fmt" + "net/http" + "strings" +) + +type InMemoryPlayerStore struct{} + +type PlayerStore interface { + GetPlayerScore(player string) int + RecordWin(player string) +} + +func (i *InMemoryPlayerStore) GetPlayerScore(player string) int { + return 123 +} + +func (i *InMemoryPlayerStore) RecordWin(player string) { + return +} + +type PlayerServer struct { + store PlayerStore +} + +func (ps *PlayerServer) processWin(w http.ResponseWriter, player string) { + ps.store.RecordWin(player) + w.WriteHeader(http.StatusAccepted) +} + +func (ps *PlayerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + player := strings.TrimPrefix(r.URL.Path, "/players/") + + switch r.Method { + case http.MethodGet: + score := ps.store.GetPlayerScore(player) + if score == 0 { + w.WriteHeader(http.StatusNotFound) + } + fmt.Fprint(w, score) + case http.MethodPost: + ps.processWin(w, player) + } +}