test http POST api/questions/QID/answers

master
Bel LaPointe 2023-04-07 13:44:42 -06:00
parent c76da12b1a
commit 7a464c2f09
2 changed files with 73 additions and 1 deletions

34
http.go
View File

@ -7,7 +7,10 @@ import (
"fmt"
"net/http"
"os"
"os/signal"
"path"
"strings"
"syscall"
"time"
)
@ -17,6 +20,9 @@ type Context struct {
}
func HTTP(port int, db DB) error {
ctx, can := signal.NotifyContext(context.Background(), syscall.SIGINT)
defer can()
foo := func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
httpGUI(w, r)
@ -28,7 +34,12 @@ func HTTP(port int, db DB) error {
}
foo = withAuth(foo)
foo = withDB(foo, db)
return http.ListenAndServe(fmt.Sprintf(":%d", port), http.HandlerFunc(foo))
foo = withCtx(foo, ctx)
go func() {
http.ListenAndServe(fmt.Sprintf(":%d", port), http.HandlerFunc(foo))
}()
<-ctx.Done()
return nil
}
func extract(ctx context.Context) Context {
@ -41,6 +52,13 @@ func inject(ctx context.Context, v Context) context.Context {
return context.WithValue(ctx, "__context", v)
}
func withCtx(foo http.HandlerFunc, ctx context.Context) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
r = r.WithContext(ctx)
foo(w, r)
}
}
func withDB(foo http.HandlerFunc, db DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
c := extract(r.Context())
@ -100,4 +118,18 @@ func httpAssignments(ctx context.Context) (interface{}, error) {
}
func httpPostQuestionAnswers(w http.ResponseWriter, r *http.Request) {
idq := IDQ(path.Base(strings.Split(r.URL.Path, "/answers")[0]))
var payload struct {
Answer string `json:"answer"`
Passed bool `json:"passed"`
}
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
ctx := extract(r.Context())
if err := ctx.DB.PushAnswer(ctx.User, idq, Renderable(payload.Answer), payload.Passed); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
}

40
http_test.go Normal file
View File

@ -0,0 +1,40 @@
package main
import (
"net/http"
"net/http/httptest"
"os"
"path"
"strings"
"testing"
)
func TestHTTPPostQuestionAnswers(t *testing.T) {
p := path.Join(t.TempDir(), "db.yaml")
os.WriteFile(p, []byte("{}"), os.ModePerm)
db, err := newYamlDB(p)
if err != nil {
t.Fatal(err)
}
w := httptest.NewRecorder()
r := httptest.NewRequest(
http.MethodPost,
"/api/questions/QID/answers",
strings.NewReader(`{"answer":"a", "passed": false}`),
)
r.SetBasicAuth("u", "")
withAuth(withDB(httpPostQuestionAnswers, db))(w, r)
if w.Code != http.StatusOK {
t.Error(w.Code)
}
t.Logf("response: %s", w.Body.Bytes())
_, got := db.LastAnswer("u", "QID")
if got == (Answer{}) {
t.Error("no answer pushed:", got)
}
t.Logf("answer pushed: %+v", got)
}