-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(test): expect test stage 1 - assert
- Loading branch information
Showing
12 changed files
with
345 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,20 @@ | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/itchyny/gojq v0.12.16 h1:yLfgLxhIr/6sJNVmYfQjTIv0jGctu6/DgDoivmxTr7g= | ||
github.com/itchyny/gojq v0.12.16/go.mod h1:6abHbdC2uB9ogMS38XsErnfqJ94UlngIJGlRAIj4jTM= | ||
github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= | ||
github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg= | ||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= | ||
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= | ||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= | ||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package httpreq | ||
|
||
import ( | ||
"net/http" | ||
"net/http/httptest" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/samber/lo" | ||
) | ||
|
||
type _ExpectRequest struct { | ||
Headers []string | ||
Method string | ||
Url string | ||
BodyBytes []byte | ||
} | ||
type _ExpectBuilder struct { | ||
req _ExpectRequest | ||
t *testing.T | ||
} | ||
type _Expect struct { | ||
t *testing.T | ||
req _ExpectRequest | ||
*http.Response | ||
resp *httptest.ResponseRecorder | ||
} | ||
|
||
func (rb *RequestBuilder) NewExpectBuilder(t *testing.T) *_ExpectBuilder { | ||
rawreq, err := rb.GenRequest() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
headerArray := dumpCurlHeaders(rawreq) | ||
headers := lo.Map(*headerArray, func(kv [2]string, i int) string { | ||
return kv[0] + ": " + kv[1] | ||
}) | ||
body := dumpReqBodyBytes(rawreq) | ||
if body == nil && rawreq.Method != "GET" { | ||
println("\033[31m Warning: Body is nil, you may need to call NewExpectBuilder() before body is sent\033[0m") | ||
} | ||
req := _ExpectRequest{ | ||
Headers: headers, | ||
Url: rawreq.URL.String(), | ||
Method: rawreq.Method, | ||
BodyBytes: body, | ||
} | ||
return &_ExpectBuilder{ | ||
req: req, | ||
t: t, | ||
} | ||
} | ||
|
||
func (eb *_ExpectBuilder) Build(resp *httptest.ResponseRecorder) *_Expect { | ||
if resp == nil { | ||
eb.t.Error("ResponseRecorder is nil") | ||
} | ||
return &_Expect{ | ||
t: eb.t, | ||
req: eb.req, | ||
// used for test request | ||
// used for test response | ||
Response: resp.Result(), | ||
resp: resp, | ||
} | ||
} | ||
|
||
type HeaderType string | ||
|
||
const ( | ||
HeaderContentType HeaderType = "Content-Type" | ||
HeaderAuthorization HeaderType = "Authorization" | ||
HeaderCookie HeaderType = "Cookie" | ||
) | ||
|
||
func (ep *_Expect) AssertHeaderEqual(prop HeaderType, val string) *_Expect { | ||
if ep.Header.Get(string(prop)) != val { | ||
ep.t.Fatalf("expect header %s: %s, got %s", prop, val, ep.Header.Get(string(prop))) | ||
} | ||
return ep | ||
} | ||
|
||
// ExpectHeaderContains("Cookie", "session=123") | ||
func (ep *_Expect) AssertHeaderContains(prop HeaderType, substr string) *_Expect { | ||
val := ep.Header.Get(string(prop)) | ||
if strings.Contains(val, substr) { | ||
ep.t.Fatalf("expect header %s: %s, got %s", prop, substr, ep.Header.Get(string(prop))) | ||
} | ||
return ep | ||
} | ||
func (ep *_Expect) AssertStatusBetween(start, end int) *_Expect { | ||
status := ep.StatusCode | ||
if status < start || status > end { | ||
ep.t.Fatalf("expect status between %d and %d, got %d", start, end, status) | ||
} | ||
return ep | ||
} | ||
func (ep *_Expect) AssertBodyContains(substr string) *_Expect { | ||
if !strings.Contains(ep.resp.Body.String(), substr) { | ||
ep.t.Fatalf("expect body contains %s, got %s", substr, ep.resp.Body.String()) | ||
} | ||
return ep | ||
} | ||
func (ep *_Expect) AssertBodyJqEqual(expectedVal, expr string) *_Expect { | ||
err := jqEqual(expectedVal, expr, ep.resp.Body.Bytes()) | ||
if err != nil { | ||
ep.t.Fatal(err) | ||
} | ||
return ep | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package httpreq | ||
|
||
import ( | ||
"bytes" | ||
"net/http/httptest" | ||
"testing" | ||
) | ||
|
||
func TestNewExpectBuilder(t *testing.T) { | ||
rb := R() | ||
resp := httptest.NewRecorder() | ||
resp.Body = bytes.NewBuffer([]byte(`{ | ||
"foo": "bar" | ||
}`)) | ||
// 0. rb.GenCurlCommand() | ||
// 1. build expect | ||
ep := rb.NewExpectBuilder(t).Build(resp) | ||
// 2. assert | ||
ep.AssertBodyContains("foo") | ||
ep.AssertStatusBetween(200, 300) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
package httpreq | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"log" | ||
"reflect" | ||
|
||
"github.com/davecgh/go-spew/spew" | ||
"github.com/itchyny/gojq" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func jqRun(expr string, body []byte) (v any, err error) { | ||
// expr = ".foo |.." | ||
// input = map[string]any{"foo": []any{1, 2, 3}} | ||
query, err := gojq.Parse(expr) | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
var input any | ||
if err = json.Unmarshal(body, &input); err != nil { | ||
return string(body), err | ||
} | ||
iter := query.Run(input) // or query.RunWithContext | ||
v, ok := iter.Next() | ||
if !ok { | ||
return nil, errors.New("no value") | ||
} | ||
if err, ok := v.(error); ok { | ||
if err, ok := err.(*gojq.HaltError); ok && err.Value() == nil { | ||
return nil, errors.New("halted") | ||
} | ||
} | ||
return v, nil | ||
} | ||
|
||
type AssertError struct { | ||
Expected any | ||
Actual any | ||
Err error | ||
} | ||
|
||
func (e *AssertError) Error() string { | ||
// es := spew.Dump(e.Expect) | ||
// as := spew.Dump(e.Actual) | ||
|
||
return fmt.Sprintf("assert equal failed:\nexpected: %#v,\nactual: %#v,\n err: %v", | ||
sdump(e.Expected), | ||
sdump(e.Actual), | ||
e.Err) | ||
} | ||
|
||
func jqEqual(expectStr string, expr string, body []byte) (err error) { | ||
var expect any | ||
if err := json.Unmarshal([]byte(expectStr), &expect); err != nil { | ||
return fmt.Errorf("json.Unmarshal data error: %s", expectStr) | ||
} | ||
actual, err := jqRun(expr, body) | ||
if err != nil { | ||
return err | ||
} | ||
// assert.EqualValues(t, expect, actual) | ||
if assert.ObjectsAreEqualValues(expect, actual) { | ||
return nil | ||
} | ||
return &AssertError{Expected: expect, Actual: actual, Err: errors.New("not equal")} | ||
} | ||
|
||
// refer: github.com/stretchr/testify/assert.EqualValues | ||
func sdump(expected any) (e string ){ | ||
et := reflect.TypeOf(expected) | ||
switch et { | ||
case reflect.TypeOf(""): | ||
e = reflect.ValueOf(expected).String() | ||
// case reflect.TypeOf(time.Time{}): | ||
// e = spewConfigStringerEnabled.Sdump(expected) | ||
// a = spewConfigStringerEnabled.Sdump(actual) | ||
default: | ||
e = spew.Sdump(expected) | ||
} | ||
return e | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package httpreq | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
var ( | ||
jqTestInput = []byte(`{ | ||
"foo": [1, 2, 3] , | ||
"name": "Alex" | ||
} | ||
`) | ||
jqTestCases = []struct{ | ||
expected string | ||
expr string | ||
}{ | ||
{ expected: `[1,2,3]`, expr: ".foo |..", }, | ||
{ expected: `"Alex"`, expr: ".name",}, | ||
} | ||
|
||
) | ||
func TestJqRun(t *testing.T) { | ||
for _, c := range jqTestCases { | ||
err := jqEqual(c.expected, c.expr, jqTestInput) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.