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  }