github.com/agilebits/godog@v0.7.9/examples/db/api_test.go (about) 1 package main 2 3 import ( 4 "database/sql" 5 "encoding/json" 6 "fmt" 7 "net/http" 8 "net/http/httptest" 9 "strings" 10 11 txdb "github.com/DATA-DOG/go-txdb" 12 "github.com/DATA-DOG/godog" 13 "github.com/DATA-DOG/godog/gherkin" 14 ) 15 16 func init() { 17 // we register an sql driver txdb 18 txdb.Register("txdb", "mysql", "root@/godog_test") 19 } 20 21 type apiFeature struct { 22 server 23 resp *httptest.ResponseRecorder 24 } 25 26 func (a *apiFeature) resetResponse(interface{}) { 27 a.resp = httptest.NewRecorder() 28 if a.db != nil { 29 a.db.Close() 30 } 31 db, err := sql.Open("txdb", "api") 32 if err != nil { 33 panic(err) 34 } 35 a.db = db 36 } 37 38 func (a *apiFeature) iSendrequestTo(method, endpoint string) (err error) { 39 req, err := http.NewRequest(method, endpoint, nil) 40 if err != nil { 41 return 42 } 43 44 // handle panic 45 defer func() { 46 switch t := recover().(type) { 47 case string: 48 err = fmt.Errorf(t) 49 case error: 50 err = t 51 } 52 }() 53 54 switch endpoint { 55 case "/users": 56 a.users(a.resp, req) 57 default: 58 err = fmt.Errorf("unknown endpoint: %s", endpoint) 59 } 60 return 61 } 62 63 func (a *apiFeature) theResponseCodeShouldBe(code int) error { 64 if code != a.resp.Code { 65 if a.resp.Code >= 400 { 66 return fmt.Errorf("expected response code to be: %d, but actual is: %d, response message: %s", code, a.resp.Code, string(a.resp.Body.Bytes())) 67 } 68 return fmt.Errorf("expected response code to be: %d, but actual is: %d", code, a.resp.Code) 69 } 70 return nil 71 } 72 73 func (a *apiFeature) theResponseShouldMatchJSON(body *gherkin.DocString) (err error) { 74 var expected, actual []byte 75 var data interface{} 76 if err = json.Unmarshal([]byte(body.Content), &data); err != nil { 77 return 78 } 79 if expected, err = json.Marshal(data); err != nil { 80 return 81 } 82 actual = a.resp.Body.Bytes() 83 if string(actual) != string(expected) { 84 err = fmt.Errorf("expected json %s, does not match actual: %s", string(expected), string(actual)) 85 } 86 return 87 } 88 89 func (a *apiFeature) thereAreUsers(users *gherkin.DataTable) error { 90 var fields []string 91 var marks []string 92 head := users.Rows[0].Cells 93 for _, cell := range head { 94 fields = append(fields, cell.Value) 95 marks = append(marks, "?") 96 } 97 98 stmt, err := a.db.Prepare("INSERT INTO users (" + strings.Join(fields, ", ") + ") VALUES(" + strings.Join(marks, ", ") + ")") 99 if err != nil { 100 return err 101 } 102 for i := 1; i < len(users.Rows); i++ { 103 var vals []interface{} 104 for n, cell := range users.Rows[i].Cells { 105 switch head[n].Value { 106 case "username": 107 vals = append(vals, cell.Value) 108 case "email": 109 vals = append(vals, cell.Value) 110 default: 111 return fmt.Errorf("unexpected column name: %s", head[n].Value) 112 } 113 } 114 if _, err = stmt.Exec(vals...); err != nil { 115 return err 116 } 117 } 118 return nil 119 } 120 121 func FeatureContext(s *godog.Suite) { 122 api := &apiFeature{} 123 124 s.BeforeScenario(api.resetResponse) 125 126 s.Step(`^I send "(GET|POST|PUT|DELETE)" request to "([^"]*)"$`, api.iSendrequestTo) 127 s.Step(`^the response code should be (\d+)$`, api.theResponseCodeShouldBe) 128 s.Step(`^the response should match json:$`, api.theResponseShouldMatchJSON) 129 s.Step(`^there are users:$`, api.thereAreUsers) 130 }