Update go dependencies

This commit is contained in:
Manuel Alejandro de Brito Fontes 2020-02-19 00:10:16 -03:00
parent f9624cbe46
commit 307bf76454
280 changed files with 54728 additions and 2991 deletions

9
vendor/gopkg.in/gavv/httpexpect.v2/.golangci.yml generated vendored Normal file
View file

@ -0,0 +1,9 @@
linters-settings:
lll:
line-length: 90
linters:
enable:
- golint
- lll
- misspell

17
vendor/gopkg.in/gavv/httpexpect.v2/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,17 @@
language: go
sudo: false
go:
- 1.12.x
before_install:
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
- go get github.com/golangci/golangci-lint/cmd/golangci-lint
script:
- go get -v -t . ./_examples
- go test -coverprofile profile.cov .
- go test ./_examples
- ${GOPATH}/bin/golangci-lint run ./...
- ${GOPATH}/bin/goveralls -coverprofile profile.cov -service=travis-ci

21
vendor/gopkg.in/gavv/httpexpect.v2/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Victor Gaydov
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

13
vendor/gopkg.in/gavv/httpexpect.v2/Makefile generated vendored Normal file
View file

@ -0,0 +1,13 @@
all: update test check
update:
go get -u -t . ./_examples
test:
go test . ./_examples
check:
golangci-lint run ./...
fmt:
gofmt -s -w . ./_examples

503
vendor/gopkg.in/gavv/httpexpect.v2/README.md generated vendored Normal file
View file

@ -0,0 +1,503 @@
# httpexpect [![GoDoc](https://godoc.org/github.com/gavv/httpexpect?status.svg)](https://godoc.org/github.com/gavv/httpexpect) [![Gitter](https://badges.gitter.im/gavv/httpexpect.svg)](https://gitter.im/gavv/httpexpect?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Travis](https://img.shields.io/travis/gavv/httpexpect.svg)](https://travis-ci.org/gavv/httpexpect) [![Coveralls](https://coveralls.io/repos/github/gavv/httpexpect/badge.svg?branch=master)](https://coveralls.io/github/gavv/httpexpect?branch=master)
Concise, declarative, and easy to use end-to-end HTTP and REST API testing for Go (golang).
Basically, httpexpect is a set of chainable *builders* for HTTP requests and *assertions* for HTTP responses and payload, on top of net/http and several utility packages.
Workflow:
* Incrementally build HTTP requests.
* Inspect HTTP responses.
* Inspect response payload recursively.
## Features
##### Request builder
* URL path construction, with simple string interpolation provided by [`go-interpol`](https://github.com/imkira/go-interpol) package.
* URL query parameters (encoding using [`go-querystring`](https://github.com/google/go-querystring) package).
* Headers, cookies, payload: JSON, urlencoded or multipart forms (encoding using [`form`](https://github.com/ajg/form) package), plain text.
* Custom reusable [request builders](#reusable-builders).
##### Response assertions
* Response status, predefined status ranges.
* Headers, cookies, payload: JSON, JSONP, forms, text.
* Round-trip time.
* Custom reusable [response matchers](#reusable-matchers).
##### Payload assertions
* Type-specific assertions, supported types: object, array, string, number, boolean, null, datetime.
* Regular expressions.
* Simple JSON queries (using subset of [JSONPath](http://goessner.net/articles/JsonPath/)), provided by [`jsonpath`](https://github.com/yalp/jsonpath) package.
* [JSON Schema](http://json-schema.org/) validation, provided by [`gojsonschema`](https://github.com/xeipuuv/gojsonschema) package.
##### WebSocket support (thanks to [@tyranron](https://github.com/tyranron))
* Upgrade an HTTP connection to a WebSocket connection (we use [`gorilla/websocket`](https://github.com/gorilla/websocket) internally).
* Interact with the WebSocket server.
* Inspect WebSocket connection parameters and WebSocket messages.
##### Pretty printing
* Verbose error messages.
* JSON diff is produced on failure using [`gojsondiff`](https://github.com/yudai/gojsondiff/) package.
* Failures are reported using [`testify`](https://github.com/stretchr/testify/) (`assert` or `require` package) or standard `testing` package.
* Dumping requests and responses in various formats, using [`httputil`](https://golang.org/pkg/net/http/httputil/), [`http2curl`](https://github.com/moul/http2curl), or simple compact logger.
##### Tuning
* Tests can communicate with server via real HTTP client or invoke `net/http` or [`fasthttp`](https://github.com/valyala/fasthttp/) handler directly.
* Custom HTTP client, logger, printer, and failure reporter may be provided by user.
* Custom HTTP request factory may be provided, e.g. from the Google App Engine testing.
## Status
Stable branches are available on [`gopkg.in`](http://labix.org/gopkg.in) and will not introduce backward-incompatible changes.
Current stable branch is [`v2`](http://gopkg.in/gavv/httpexpect.v2):
```go
import "gopkg.in/gavv/httpexpect.v2"
```
Development is done in `master` branch on github:
```go
import "github.com/gavv/httpexpect"
```
When the master is merged into a stable branch, a new version tag is assigned to the branch head. The versions are selected according to the [semantic versioning](https://semver.org/) scheme.
## Documentation
Documentation is available on [GoDoc](https://godoc.org/github.com/gavv/httpexpect). It contains an overview and reference.
## Examples
See [`_examples`](_examples) directory for complete standalone examples.
* [`fruits_test.go`](_examples/fruits_test.go)
Testing a simple CRUD server made with bare `net/http`.
* [`iris_test.go`](_examples/iris_test.go)
Testing a server made with [`iris`](https://github.com/kataras/iris/) framework. Example includes JSON queries and validation, URL and form parameters, basic auth, sessions, and streaming. Tests invoke the `http.Handler` directly.
* [`echo_test.go`](_examples/echo_test.go)
Testing a server with JWT authentication made with [`echo`](https://github.com/labstack/echo/) framework. Tests use either HTTP client or invoke the `http.Handler` directly.
* [`fasthttp_test.go`](_examples/fasthttp_test.go)
Testing a server made with [`fasthttp`](https://github.com/valyala/fasthttp) package. Tests invoke the `fasthttp.RequestHandler` directly.
* [`websocket_test.go`](_examples/websocket_test.go)
Testing a WebSocket server based on [`gorilla/websocket`](https://github.com/gorilla/websocket). Tests invoke the `http.Handler` or `fasthttp.RequestHandler` directly.
* [`gae_test.go`](_examples/gae_test.go)
Testing a server running under the [Google App Engine](https://en.wikipedia.org/wiki/Google_App_Engine).
## Quick start
##### Hello, world!
```go
package example
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/gavv/httpexpect"
)
func TestFruits(t *testing.T) {
// create http.Handler
handler := FruitsHandler()
// run server using httptest
server := httptest.NewServer(handler)
defer server.Close()
// create httpexpect instance
e := httpexpect.New(t, server.URL)
// is it working?
e.GET("/fruits").
Expect().
Status(http.StatusOK).JSON().Array().Empty()
}
```
##### JSON
```go
orange := map[string]interface{}{
"weight": 100,
}
e.PUT("/fruits/orange").WithJSON(orange).
Expect().
Status(http.StatusNoContent).NoContent()
e.GET("/fruits/orange").
Expect().
Status(http.StatusOK).
JSON().Object().ContainsKey("weight").ValueEqual("weight", 100)
apple := map[string]interface{}{
"colors": []interface{}{"green", "red"},
"weight": 200,
}
e.PUT("/fruits/apple").WithJSON(apple).
Expect().
Status(http.StatusNoContent).NoContent()
obj := e.GET("/fruits/apple").
Expect().
Status(http.StatusOK).JSON().Object()
obj.Keys().ContainsOnly("colors", "weight")
obj.Value("colors").Array().Elements("green", "red")
obj.Value("colors").Array().Element(0).String().Equal("green")
obj.Value("colors").Array().Element(1).String().Equal("red")
obj.Value("colors").Array().First().String().Equal("green")
obj.Value("colors").Array().Last().String().Equal("red")
```
##### JSON Schema and JSON Path
```go
schema := `{
"type": "array",
"items": {
"type": "object",
"properties": {
...
"private": {
"type": "boolean"
}
}
}
}`
repos := e.GET("/repos/octocat").
Expect().
Status(http.StatusOK).JSON()
// validate JSON schema
repos.Schema(schema)
// run JSONPath query and iterate results
for _, private := range repos.Path("$..private").Array().Iter() {
private.Boolean().False()
}
```
##### Forms
```go
// post form encoded from struct or map
e.POST("/form").WithForm(structOrMap).
Expect().
Status(http.StatusOK)
// set individual fields
e.POST("/form").WithFormField("foo", "hello").WithFormField("bar", 123).
Expect().
Status(http.StatusOK)
// multipart form
e.POST("/form").WithMultipart().
WithFile("avatar", "./john.png").WithFormField("username", "john").
Expect().
Status(http.StatusOK)
```
##### URL construction
```go
// construct path using ordered parameters
e.GET("/repos/{user}/{repo}", "octocat", "hello-world").
Expect().
Status(http.StatusOK)
// construct path using named parameters
e.GET("/repos/{user}/{repo}").
WithPath("user", "octocat").WithPath("repo", "hello-world").
Expect().
Status(http.StatusOK)
// set query parameters
e.GET("/repos/{user}", "octocat").WithQuery("sort", "asc").
Expect().
Status(http.StatusOK) // "/repos/octocat?sort=asc"
```
##### Headers
```go
// set If-Match
e.POST("/users/john").WithHeader("If-Match", etag).WithJSON(john).
Expect().
Status(http.StatusOK)
// check ETag
e.GET("/users/john").
Expect().
Status(http.StatusOK).Header("ETag").NotEmpty()
// check Date
t := time.Now()
e.GET("/users/john").
Expect().
Status(http.StatusOK).Header("Date").DateTime().InRange(t, time.Now())
```
##### Cookies
```go
// set cookie
t := time.Now()
e.POST("/users/john").WithCookie("session", sessionID).WithJSON(john).
Expect().
Status(http.StatusOK)
// check cookies
c := e.GET("/users/john").
Expect().
Status(http.StatusOK).Cookie("session")
c.Value().Equal(sessionID)
c.Domain().Equal("example.com")
c.Path().Equal("/")
c.Expires().InRange(t, t.Add(time.Hour * 24))
```
##### Regular expressions
```go
// simple match
e.GET("/users/john").
Expect().
Header("Location").
Match("http://(.+)/users/(.+)").Values("example.com", "john")
// check capture groups by index or name
m := e.GET("/users/john").
Expect().
Header("Location").Match("http://(?P<host>.+)/users/(?P<user>.+)")
m.Index(0).Equal("http://example.com/users/john")
m.Index(1).Equal("example.com")
m.Index(2).Equal("john")
m.Name("host").Equal("example.com")
m.Name("user").Equal("john")
```
##### Subdomains and per-request URL
```go
e.GET("/path").WithURL("http://example.com").
Expect().
Status(http.StatusOK)
e.GET("/path").WithURL("http://subdomain.example.com").
Expect().
Status(http.StatusOK)
```
##### WebSocket support
```go
ws := e.GET("/mysocket").WithWebsocketUpgrade().
Expect().
Status(http.StatusSwitchingProtocols).
Websocket()
defer ws.Disconnect()
ws.WriteText("some request").
Expect().
TextMessage().Body().Equal("some response")
ws.CloseWithText("bye").
Expect().
CloseMessage().NoContent()
```
##### Reusable builders
```go
e := httpexpect.New(t, "http://example.com")
r := e.POST("/login").WithForm(Login{"ford", "betelgeuse7"}).
Expect().
Status(http.StatusOK).JSON().Object()
token := r.Value("token").String().Raw()
auth := e.Builder(func (req *httpexpect.Request) {
req.WithHeader("Authorization", "Bearer "+token)
})
auth.GET("/restricted").
Expect().
Status(http.StatusOK)
e.GET("/restricted").
Expect().
Status(http.StatusUnauthorized)
```
##### Reusable matchers
```go
e := httpexpect.New(t, "http://example.com")
// every response should have this header
m := e.Matcher(func (resp *httpexpect.Response) {
resp.Header("API-Version").NotEmpty()
})
m.GET("/some-path").
Expect().
Status(http.StatusOK)
m.GET("/bad-path").
Expect().
Status(http.StatusNotFound)
```
##### Custom config
```go
e := httpexpect.WithConfig(httpexpect.Config{
// prepend this url to all requests
BaseURL: "http://example.com",
// use http.Client with a cookie jar and timeout
Client: &http.Client{
Jar: httpexpect.NewJar(),
Timeout: time.Second * 30,
},
// use fatal failures
Reporter: httpexpect.NewRequireReporter(t),
// use verbose logging
Printers: []httpexpect.Printer{
httpexpect.NewCurlPrinter(t),
httpexpect.NewDebugPrinter(t, true),
},
})
```
##### Session support
```go
// cookie jar is used to store cookies from server
e := httpexpect.WithConfig(httpexpect.Config{
Reporter: httpexpect.NewAssertReporter(t),
Client: &http.Client{
Jar: httpexpect.NewJar(), // used by default if Client is nil
},
})
// cookies are disabled
e := httpexpect.WithConfig(httpexpect.Config{
Reporter: httpexpect.NewAssertReporter(t),
Client: &http.Client{
Jar: nil,
},
})
```
##### Use HTTP handler directly
```go
// invoke http.Handler directly using httpexpect.Binder
var handler http.Handler = MyHandler()
e := httpexpect.WithConfig(httpexpect.Config{
Reporter: httpexpect.NewAssertReporter(t),
Client: &http.Client{
Transport: httpexpect.NewBinder(handler),
Jar: httpexpect.NewJar(),
},
})
// invoke fasthttp.RequestHandler directly using httpexpect.FastBinder
var handler fasthttp.RequestHandler = myHandler()
e := httpexpect.WithConfig(httpexpect.Config{
Reporter: httpexpect.NewAssertReporter(t),
Client: &http.Client{
Transport: httpexpect.NewFastBinder(handler),
Jar: httpexpect.NewJar(),
},
})
```
##### Per-request client or handler
```go
e := httpexpect.New(t, server.URL)
client := &http.Client{
Transport: &http.Transport{
DisableCompression: true,
},
}
// overwrite client
e.GET("/path").WithClient(client).
Expect().
Status(http.StatusOK)
// construct client that invokes a handler directly and overwrite client
e.GET("/path").WithHandler(handler).
Expect().
Status(http.StatusOK)
```
## Similar packages
* [`gorequest`](https://github.com/parnurzeal/gorequest)
* [`baloo`](https://github.com/h2non/baloo)
* [`gofight`](https://github.com/appleboy/gofight)
* [`frisby`](https://github.com/verdverm/frisby)
* [`forest`](https://github.com/emicklei/forest)
* [`restit`](https://github.com/go-restit/restit)
* [`http-test`](https://github.com/vsco/http-test)
* [`go-json-rest`](https://github.com/ant0ine/go-json-rest)
## Contributing
Feel free to report bugs, suggest improvements, and send pull requests! Please add documentation and tests for new features.
Update dependencies, build code, and run tests and linters:
```
$ make
```
Format code:
```
$ make fmt
```
## License
[MIT](LICENSE)

299
vendor/gopkg.in/gavv/httpexpect.v2/array.go generated vendored Normal file
View file

@ -0,0 +1,299 @@
package httpexpect
import (
"reflect"
)
// Array provides methods to inspect attached []interface{} object
// (Go representation of JSON array).
type Array struct {
chain chain
value []interface{}
}
// NewArray returns a new Array given a reporter used to report failures
// and value to be inspected.
//
// Both reporter and value should not be nil. If value is nil, failure is
// reported.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
func NewArray(reporter Reporter, value []interface{}) *Array {
chain := makeChain(reporter)
if value == nil {
chain.fail("expected non-nil array value")
} else {
value, _ = canonArray(&chain, value)
}
return &Array{chain, value}
}
// Raw returns underlying value attached to Array.
// This is the value originally passed to NewArray, converted to canonical form.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// assert.Equal(t, []interface{}{"foo", 123.0}, array.Raw())
func (a *Array) Raw() []interface{} {
return a.value
}
// Path is similar to Value.Path.
func (a *Array) Path(path string) *Value {
return getPath(&a.chain, a.value, path)
}
// Schema is similar to Value.Schema.
func (a *Array) Schema(schema interface{}) *Array {
checkSchema(&a.chain, a.value, schema)
return a
}
// Length returns a new Number object that may be used to inspect array length.
//
// Example:
// array := NewArray(t, []interface{}{1, 2, 3})
// array.Length().Equal(3)
func (a *Array) Length() *Number {
return &Number{a.chain, float64(len(a.value))}
}
// Element returns a new Value object that may be used to inspect array element
// for given index.
//
// If index is out of array bounds, Element reports failure and returns empty
// (but non-nil) value.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.Element(0).String().Equal("foo")
// array.Element(1).Number().Equal(123)
func (a *Array) Element(index int) *Value {
if index < 0 || index >= len(a.value) {
a.chain.fail(
"\narray index out of bounds:\n index %d\n\n bounds [%d; %d)",
index,
0,
len(a.value))
return &Value{a.chain, nil}
}
return &Value{a.chain, a.value[index]}
}
// First returns a new Value object that may be used to inspect first element
// of given array.
//
// If given array is empty, First reports failure and returns empty
// (but non-nil) value.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.First().String().Equal("foo")
func (a *Array) First() *Value {
if len(a.value) < 1 {
a.chain.fail("\narray is empty")
return &Value{a.chain, nil}
}
return &Value{a.chain, a.value[0]}
}
// Last returns a new Value object that may be used to inspect last element
// of given array.
//
// If given array is empty, Last reports failure and returns empty
// (but non-nil) value.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.Last().Number().Equal(123)
func (a *Array) Last() *Value {
if len(a.value) < 1 {
a.chain.fail("\narray is empty")
return &Value{a.chain, nil}
}
return &Value{a.chain, a.value[len(a.value)-1]}
}
// Iter returns a new slice of Values attached to array elements.
//
// Example:
// strings := []interface{}{"foo", "bar"}
// array := NewArray(t, strings)
//
// for n, val := range array.Iter() {
// val.String().Equal(strings[n])
// }
func (a *Array) Iter() []Value {
if a.chain.failed() {
return []Value{}
}
ret := []Value{}
for n := range a.value {
ret = append(ret, Value{a.chain, a.value[n]})
}
return ret
}
// Empty succeeds if array is empty.
//
// Example:
// array := NewArray(t, []interface{}{})
// array.Empty()
func (a *Array) Empty() *Array {
return a.Equal([]interface{}{})
}
// NotEmpty succeeds if array is non-empty.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.NotEmpty()
func (a *Array) NotEmpty() *Array {
return a.NotEqual([]interface{}{})
}
// Equal succeeds if array is equal to given Go slice.
// Before comparison, both array and value are converted to canonical form.
//
// value should be a slice of any type.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.Equal([]interface{}{"foo", 123})
//
// array := NewArray(t, []interface{}{"foo", "bar"})
// array.Equal([]string{}{"foo", "bar"})
//
// array := NewArray(t, []interface{}{123, 456})
// array.Equal([]int{}{123, 456})
func (a *Array) Equal(value interface{}) *Array {
expected, ok := canonArray(&a.chain, value)
if !ok {
return a
}
if !reflect.DeepEqual(expected, a.value) {
a.chain.fail("\nexpected array equal to:\n%s\n\nbut got:\n%s\n\ndiff:\n%s",
dumpValue(expected),
dumpValue(a.value),
diffValues(expected, a.value))
}
return a
}
// NotEqual succeeds if array is not equal to given Go slice.
// Before comparison, both array and value are converted to canonical form.
//
// value should be a slice of any type.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.NotEqual([]interface{}{123, "foo"})
func (a *Array) NotEqual(value interface{}) *Array {
expected, ok := canonArray(&a.chain, value)
if !ok {
return a
}
if reflect.DeepEqual(expected, a.value) {
a.chain.fail("\nexpected array not equal to:\n%s",
dumpValue(expected))
}
return a
}
// Elements succeeds if array contains all given elements, in given order, and only
// them. Before comparison, array and all elements are converted to canonical form.
//
// For partial or unordered comparison, see Contains and ContainsOnly.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.Elements("foo", 123)
//
// This calls are equivalent:
// array.Elelems("a", "b")
// array.Equal([]interface{}{"a", "b"})
func (a *Array) Elements(values ...interface{}) *Array {
return a.Equal(values)
}
// Contains succeeds if array contains all given elements (in any order).
// Before comparison, array and all elements are converted to canonical form.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.Contains(123, "foo")
func (a *Array) Contains(values ...interface{}) *Array {
elements, ok := canonArray(&a.chain, values)
if !ok {
return a
}
for _, e := range elements {
if !a.containsElement(e) {
a.chain.fail("\nexpected array containing element:\n%s\n\nbut got:\n%s",
dumpValue(e), dumpValue(a.value))
}
}
return a
}
// NotContains succeeds if array contains none of given elements.
// Before comparison, array and all elements are converted to canonical form.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.NotContains("bar") // success
// array.NotContains("bar", "foo") // failure (array contains "foo")
func (a *Array) NotContains(values ...interface{}) *Array {
elements, ok := canonArray(&a.chain, values)
if !ok {
return a
}
for _, e := range elements {
if a.containsElement(e) {
a.chain.fail("\nexpected array not containing element:\n%s\n\nbut got:\n%s",
dumpValue(e), dumpValue(a.value))
}
}
return a
}
// ContainsOnly succeeds if array contains all given elements, in any order, and only
// them. Before comparison, array and all elements are converted to canonical form.
//
// Example:
// array := NewArray(t, []interface{}{"foo", 123})
// array.ContainsOnly(123, "foo")
//
// This calls are equivalent:
// array.ContainsOnly("a", "b")
// array.ContainsOnly("b", "a")
func (a *Array) ContainsOnly(values ...interface{}) *Array {
elements, ok := canonArray(&a.chain, values)
if !ok {
return a
}
if len(elements) != len(a.value) {
a.chain.fail("\nexpected array of length == %d:\n%s\n\n"+
"but got array of length %d:\n%s",
len(elements), dumpValue(elements),
len(a.value), dumpValue(a.value))
return a
}
for _, e := range elements {
if !a.containsElement(e) {
a.chain.fail("\nexpected array containing element:\n%s\n\nbut got:\n%s",
dumpValue(e), dumpValue(a.value))
}
}
return a
}
func (a *Array) containsElement(expected interface{}) bool {
for _, e := range a.value {
if reflect.DeepEqual(expected, e) {
return true
}
}
return false
}

218
vendor/gopkg.in/gavv/httpexpect.v2/binder.go generated vendored Normal file
View file

@ -0,0 +1,218 @@
package httpexpect
import (
"bytes"
"crypto/tls"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httptest"
"github.com/valyala/fasthttp"
)
// Binder implements networkless http.RoundTripper attached directly to
// http.Handler.
//
// Binder emulates network communication by invoking given http.Handler
// directly. It passes httptest.ResponseRecorder as http.ResponseWriter
// to the handler, and then constructs http.Response from recorded data.
type Binder struct {
// HTTP handler invoked for every request.
Handler http.Handler
// TLS connection state used for https:// requests.
TLS *tls.ConnectionState
}
// NewBinder returns a new Binder given a http.Handler.
//
// Example:
// client := &http.Client{
// Transport: NewBinder(handler),
// }
func NewBinder(handler http.Handler) Binder {
return Binder{Handler: handler}
}
// RoundTrip implements http.RoundTripper.RoundTrip.
func (binder Binder) RoundTrip(req *http.Request) (*http.Response, error) {
if req.Proto == "" {
req.Proto = fmt.Sprintf("HTTP/%d.%d", req.ProtoMajor, req.ProtoMinor)
}
if req.Body != nil {
if req.ContentLength == -1 {
req.TransferEncoding = []string{"chunked"}
}
} else {
req.Body = ioutil.NopCloser(bytes.NewReader(nil))
}
if req.URL != nil && req.URL.Scheme == "https" && binder.TLS != nil {
req.TLS = binder.TLS
}
if req.RequestURI == "" {
req.RequestURI = req.URL.RequestURI()
}
recorder := httptest.NewRecorder()
binder.Handler.ServeHTTP(recorder, req)
resp := http.Response{
Request: req,
StatusCode: recorder.Code,
Status: http.StatusText(recorder.Code),
Header: recorder.Result().Header,
}
if recorder.Flushed {
resp.TransferEncoding = []string{"chunked"}
}
if recorder.Body != nil {
resp.Body = ioutil.NopCloser(recorder.Body)
}
return &resp, nil
}
// FastBinder implements networkless http.RoundTripper attached directly
// to fasthttp.RequestHandler.
//
// FastBinder emulates network communication by invoking given fasthttp.RequestHandler
// directly. It converts http.Request to fasthttp.Request, invokes handler, and then
// converts fasthttp.Response to http.Response.
type FastBinder struct {
// FastHTTP handler invoked for every request.
Handler fasthttp.RequestHandler
// TLS connection state used for https:// requests.
TLS *tls.ConnectionState
}
// NewFastBinder returns a new FastBinder given a fasthttp.RequestHandler.
//
// Example:
// client := &http.Client{
// Transport: NewFastBinder(fasthandler),
// }
func NewFastBinder(handler fasthttp.RequestHandler) FastBinder {
return FastBinder{Handler: handler}
}
// RoundTrip implements http.RoundTripper.RoundTrip.
func (binder FastBinder) RoundTrip(stdreq *http.Request) (*http.Response, error) {
fastreq := std2fast(stdreq)
var conn net.Conn
if stdreq.URL != nil && stdreq.URL.Scheme == "https" && binder.TLS != nil {
conn = connTLS{state: binder.TLS}
} else {
conn = connNonTLS{}
}
ctx := fasthttp.RequestCtx{}
ctx.Init2(conn, fastLogger{}, true)
fastreq.CopyTo(&ctx.Request)
if stdreq.ContentLength >= 0 {
ctx.Request.Header.SetContentLength(int(stdreq.ContentLength))
} else {
ctx.Request.Header.Add("Transfer-Encoding", "chunked")
}
if stdreq.Body != nil {
b, err := ioutil.ReadAll(stdreq.Body)
if err == nil {
ctx.Request.SetBody(b)
}
}
binder.Handler(&ctx)
return fast2std(stdreq, &ctx.Response), nil
}
func std2fast(stdreq *http.Request) *fasthttp.Request {
fastreq := &fasthttp.Request{}
fastreq.SetRequestURI(stdreq.URL.String())
fastreq.Header.SetMethod(stdreq.Method)
for k, a := range stdreq.Header {
for n, v := range a {
if n == 0 {
fastreq.Header.Set(k, v)
} else {
fastreq.Header.Add(k, v)
}
}
}
return fastreq
}
func fast2std(stdreq *http.Request, fastresp *fasthttp.Response) *http.Response {
status := fastresp.Header.StatusCode()
body := fastresp.Body()
stdresp := &http.Response{
Request: stdreq,
StatusCode: status,
Status: http.StatusText(status),
}
fastresp.Header.VisitAll(func(k, v []byte) {
sk := string(k)
sv := string(v)
if stdresp.Header == nil {
stdresp.Header = make(http.Header)
}
stdresp.Header.Add(sk, sv)
})
if fastresp.Header.ContentLength() == -1 {
stdresp.TransferEncoding = []string{"chunked"}
}
if body != nil {
stdresp.Body = ioutil.NopCloser(bytes.NewReader(body))
} else {
stdresp.Body = ioutil.NopCloser(bytes.NewReader(nil))
}
return stdresp
}
type fastLogger struct{}
func (fastLogger) Printf(format string, args ...interface{}) {
_, _ = format, args
}
type connNonTLS struct {
net.Conn
}
func (connNonTLS) RemoteAddr() net.Addr {
return &net.TCPAddr{IP: net.IPv4zero}
}
func (connNonTLS) LocalAddr() net.Addr {
return &net.TCPAddr{IP: net.IPv4zero}
}
type connTLS struct {
connNonTLS
state *tls.ConnectionState
}
func (c connTLS) Handshake() error {
return nil
}
func (c connTLS) ConnectionState() tls.ConnectionState {
return *c.state
}

82
vendor/gopkg.in/gavv/httpexpect.v2/boolean.go generated vendored Normal file
View file

@ -0,0 +1,82 @@
package httpexpect
// Boolean provides methods to inspect attached bool value
// (Go representation of JSON boolean).
type Boolean struct {
chain chain
value bool
}
// NewBoolean returns a new Boolean given a reporter used to report
// failures and value to be inspected.
//
// reporter should not be nil.
//
// Example:
// boolean := NewBoolean(t, true)
func NewBoolean(reporter Reporter, value bool) *Boolean {
return &Boolean{makeChain(reporter), value}
}
// Raw returns underlying value attached to Boolean.
// This is the value originally passed to NewBoolean.
//
// Example:
// boolean := NewBoolean(t, true)
// assert.Equal(t, true, boolean.Raw())
func (b *Boolean) Raw() bool {
return b.value
}
// Path is similar to Value.Path.
func (b *Boolean) Path(path string) *Value {
return getPath(&b.chain, b.value, path)
}
// Schema is similar to Value.Schema.
func (b *Boolean) Schema(schema interface{}) *Boolean {
checkSchema(&b.chain, b.value, schema)
return b
}
// Equal succeeds if boolean is equal to given value.
//
// Example:
// boolean := NewBoolean(t, true)
// boolean.Equal(true)
func (b *Boolean) Equal(value bool) *Boolean {
if !(b.value == value) {
b.chain.fail("expected boolean == %v, but got %v", value, b.value)
}
return b
}
// NotEqual succeeds if boolean is not equal to given value.
//
// Example:
// boolean := NewBoolean(t, true)
// boolean.NotEqual(false)
func (b *Boolean) NotEqual(value bool) *Boolean {
if !(b.value != value) {
b.chain.fail("expected boolean != %v, but got %v", value, b.value)
}
return b
}
// True succeeds if boolean is true.
//
// Example:
// boolean := NewBoolean(t, true)
// boolean.True()
func (b *Boolean) True() *Boolean {
return b.Equal(true)
}
// False succeeds if boolean is false.
//
// Example:
// boolean := NewBoolean(t, false)
// boolean.False()
func (b *Boolean) False() *Boolean {
return b.Equal(false)
}

38
vendor/gopkg.in/gavv/httpexpect.v2/chain.go generated vendored Normal file
View file

@ -0,0 +1,38 @@
package httpexpect
type chain struct {
reporter Reporter
failbit bool
}
func makeChain(reporter Reporter) chain {
return chain{reporter, false}
}
func (c *chain) failed() bool {
return c.failbit
}
func (c *chain) fail(message string, args ...interface{}) {
if c.failbit {
return
}
c.failbit = true
c.reporter.Errorf(message, args...)
}
func (c *chain) reset() {
c.failbit = false
}
func (c *chain) assertFailed(r Reporter) {
if !c.failbit {
r.Errorf("expected chain is failed, but it's ok")
}
}
func (c *chain) assertOK(r Reporter) {
if c.failbit {
r.Errorf("expected chain is ok, but it's failed")
}
}

133
vendor/gopkg.in/gavv/httpexpect.v2/cookie.go generated vendored Normal file
View file

@ -0,0 +1,133 @@
package httpexpect
import (
"net/http"
"time"
)
// Cookie provides methods to inspect attached http.Cookie value.
type Cookie struct {
chain chain
value *http.Cookie
}
// NewCookie returns a new Cookie object given a reporter used to report
// failures and cookie value to be inspected.
//
// reporter and value should not be nil.
//
// Example:
// cookie := NewCookie(reporter, &http.Cookie{...})
// cookie.Domain().Equal("example.com")
// cookie.Path().Equal("/")
// cookie.Expires().InRange(time.Now(), time.Now().Add(time.Hour * 24))
func NewCookie(reporter Reporter, value *http.Cookie) *Cookie {
chain := makeChain(reporter)
if value == nil {
chain.fail("expected non-nil cookie")
}
return &Cookie{chain, value}
}
// Raw returns underlying http.Cookie value attached to Cookie.
// This is the value originally passed to NewCookie.
//
// Example:
// cookie := NewCookie(t, c)
// assert.Equal(t, c, cookie.Raw())
func (c *Cookie) Raw() *http.Cookie {
return c.value
}
// Name returns a new String object that may be used to inspect
// cookie name.
//
// Example:
// cookie := NewCookie(t, &http.Cookie{...})
// cookie.Name().Equal("session")
func (c *Cookie) Name() *String {
if c.chain.failed() {
return &String{c.chain, ""}
}
return &String{c.chain, c.value.Name}
}
// Value returns a new String object that may be used to inspect
// cookie value.
//
// Example:
// cookie := NewCookie(t, &http.Cookie{...})
// cookie.Value().Equal("gH6z7Y")
func (c *Cookie) Value() *String {
if c.chain.failed() {
return &String{c.chain, ""}
}
return &String{c.chain, c.value.Value}
}
// Domain returns a new String object that may be used to inspect
// cookie domain.
//
// Example:
// cookie := NewCookie(t, &http.Cookie{...})
// cookie.Domain().Equal("example.com")
func (c *Cookie) Domain() *String {
if c.chain.failed() {
return &String{c.chain, ""}
}
return &String{c.chain, c.value.Domain}
}
// Path returns a new String object that may be used to inspect
// cookie path.
//
// Example:
// cookie := NewCookie(t, &http.Cookie{...})
// cookie.Path().Equal("/foo")
func (c *Cookie) Path() *String {
if c.chain.failed() {
return &String{c.chain, ""}
}
return &String{c.chain, c.value.Path}
}
// Expires returns a new DateTime object that may be used to inspect
// cookie expiration date.
//
// Example:
// cookie := NewCookie(t, &http.Cookie{...})
// cookie.Expires().InRange(time.Now(), time.Now().Add(time.Hour * 24))
func (c *Cookie) Expires() *DateTime {
if c.chain.failed() {
return &DateTime{c.chain, time.Unix(0, 0)}
}
return &DateTime{c.chain, c.value.Expires}
}
// MaxAge returns a new Duration object that may be used to inspect
// cookie Max-age field.
//
// If MaxAge is not set, the returned Duration is unset. Whether a Duration
// is set or not can be chacked using its IsSet and NotSet methods.
//
// If MaxAge is zero (which means delete cookie now), the returned Duration
// is set and equals to zero.
//
// Example:
// cookie := NewCookie(t, &http.Cookie{...})
// cookie.MaxAge().IsSet()
// cookie.MaxAge().InRange(time.Minute, time.Minute*10)
func (c *Cookie) MaxAge() *Duration {
if c.chain.failed() {
return &Duration{c.chain, nil}
}
if c.value.MaxAge == 0 {
return &Duration{c.chain, nil}
}
if c.value.MaxAge < 0 {
var zero time.Duration
return &Duration{c.chain, &zero}
}
d := time.Duration(c.value.MaxAge) * time.Second
return &Duration{c.chain, &d}
}

129
vendor/gopkg.in/gavv/httpexpect.v2/datetime.go generated vendored Normal file
View file

@ -0,0 +1,129 @@
package httpexpect
import (
"time"
)
// DateTime provides methods to inspect attached time.Time value.
type DateTime struct {
chain chain
value time.Time
}
// NewDateTime returns a new DateTime object given a reporter used to report
// failures and time.Time value to be inspected.
//
// reporter should not be nil.
//
// Example:
// dt := NewDateTime(reporter, time.Now())
// dt.Le(time.Now())
//
// time.Sleep(time.Second)
// dt.Lt(time.Now())
func NewDateTime(reporter Reporter, value time.Time) *DateTime {
return &DateTime{makeChain(reporter), value}
}
// Raw returns underlying time.Time value attached to DateTime.
// This is the value originally passed to NewDateTime.
//
// Example:
// dt := NewDateTime(t, timestamp)
// assert.Equal(t, timestamp, dt.Raw())
func (dt *DateTime) Raw() time.Time {
return dt.value
}
// Equal succeeds if DateTime is equal to given value.
//
// Example:
// dt := NewDateTime(t, time.Unix(0, 1))
// dt.Equal(time.Unix(0, 1))
func (dt *DateTime) Equal(value time.Time) *DateTime {
if !dt.value.Equal(value) {
dt.chain.fail("\nexpected datetime equal to:\n %s\n\nbut got:\n %s",
value, dt.value)
}
return dt
}
// NotEqual succeeds if DateTime is not equal to given value.
//
// Example:
// dt := NewDateTime(t, time.Unix(0, 1))
// dt.NotEqual(time.Unix(0, 2))
func (dt *DateTime) NotEqual(value time.Time) *DateTime {
if dt.value.Equal(value) {
dt.chain.fail("\nexpected datetime not equal to:\n %s", value)
}
return dt
}
// Gt succeeds if DateTime is greater than given value.
//
// Example:
// dt := NewDateTime(t, time.Unix(0, 2))
// dt.Gt(time.Unix(0, 1))
func (dt *DateTime) Gt(value time.Time) *DateTime {
if !dt.value.After(value) {
dt.chain.fail("\nexpected datetime > then:\n %s\n\nbut got:\n %s",
value, dt.value)
}
return dt
}
// Ge succeeds if DateTime is greater than or equal to given value.
//
// Example:
// dt := NewDateTime(t, time.Unix(0, 2))
// dt.Ge(time.Unix(0, 1))
func (dt *DateTime) Ge(value time.Time) *DateTime {
if !(dt.value.After(value) || dt.value.Equal(value)) {
dt.chain.fail("\nexpected datetime >= then:\n %s\n\nbut got:\n %s",
value, dt.value)
}
return dt
}
// Lt succeeds if DateTime is lesser than given value.
//
// Example:
// dt := NewDateTime(t, time.Unix(0, 1))
// dt.Lt(time.Unix(0, 2))
func (dt *DateTime) Lt(value time.Time) *DateTime {
if !dt.value.Before(value) {
dt.chain.fail("\nexpected datetime < then:\n %s\n\nbut got:\n %s",
value, dt.value)
}
return dt
}
// Le succeeds if DateTime is lesser than or equal to given value.
//
// Example:
// dt := NewDateTime(t, time.Unix(0, 1))
// dt.Le(time.Unix(0, 2))
func (dt *DateTime) Le(value time.Time) *DateTime {
if !(dt.value.Before(value) || dt.value.Equal(value)) {
dt.chain.fail("\nexpected datetime <= then:\n %s\n\nbut got:\n %s",
value, dt.value)
}
return dt
}
// InRange succeeds if DateTime is in given range [min; max].
//
// Example:
// dt := NewDateTime(t, time.Unix(0, 2))
// dt.InRange(time.Unix(0, 1), time.Unix(0, 3))
// dt.InRange(time.Unix(0, 2), time.Unix(0, 2))
func (dt *DateTime) InRange(min, max time.Time) *DateTime {
if !((dt.value.After(min) || dt.value.Equal(min)) &&
(dt.value.Before(max) || dt.value.Equal(max))) {
dt.chain.fail(
"\nexpected datetime in range:\n min: %s\n max: %s\n\nbut got: %s",
min, max, dt.value)
}
return dt
}

176
vendor/gopkg.in/gavv/httpexpect.v2/duration.go generated vendored Normal file
View file

@ -0,0 +1,176 @@
package httpexpect
import (
"time"
)
// Duration provides methods to inspect attached time.Duration value.
type Duration struct {
chain chain
value *time.Duration
}
// NewDuration returns a new Duration object given a reporter used to report
// failures and time.Duration value to be inspected.
//
// reporter should not be nil.
//
// Example:
// d := NewDuration(reporter, time.Second)
// d.Le(time.Minute)
func NewDuration(reporter Reporter, value time.Duration) *Duration {
return &Duration{makeChain(reporter), &value}
}
// Raw returns underlying time.Duration value attached to Duration.
// This is the value originally passed to NewDuration.
//
// Example:
// d := NewDuration(t, duration)
// assert.Equal(t, timestamp, d.Raw())
func (d *Duration) Raw() time.Duration {
if d.value == nil {
return 0
}
return *d.value
}
// IsSet succeeds if Duration is set.
//
// Example:
// d := NewDuration(t, time.Second)
// d.IsSet()
func (d *Duration) IsSet() *Duration {
if d.value == nil {
d.chain.fail("expected duration is set, but it is not")
}
return d
}
// NotSet succeeds if Duration is not set.
func (d *Duration) NotSet() *Duration {
if d.value != nil {
d.chain.fail("expected duration is not set, but it is")
}
return d
}
// Equal succeeds if Duration is equal to given value.
//
// Example:
// d := NewDuration(t, time.Second)
// d.Equal(time.Second)
func (d *Duration) Equal(value time.Duration) *Duration {
if d.value == nil {
d.chain.fail("expected duration is set, but it is not")
return d
}
if !(*d.value == value) {
d.chain.fail("\nexpected duration equal to:\n %s\n\nbut got:\n %s",
value, *d.value)
}
return d
}
// NotEqual succeeds if Duration is not equal to given value.
//
// Example:
// d := NewDuration(t, time.Second)
// d.NotEqual(time.Minute)
func (d *Duration) NotEqual(value time.Duration) *Duration {
if d.value == nil {
d.chain.fail("expected duration is set, but it is not")
return d
}
if !(*d.value != value) {
d.chain.fail("\nexpected duration not equal to:\n %s", value)
}
return d
}
// Gt succeeds if Duration is greater than given value.
//
// Example:
// d := NewDuration(t, time.Minute)
// d.Gt(time.Second)
func (d *Duration) Gt(value time.Duration) *Duration {
if d.value == nil {
d.chain.fail("expected duration is set, but it is not")
return d
}
if !(*d.value > value) {
d.chain.fail("\nexpected duration > then:\n %s\n\nbut got:\n %s",
value, *d.value)
}
return d
}
// Ge succeeds if Duration is greater than or equal to given value.
//
// Example:
// d := NewDuration(t, time.Minute)
// d.Ge(time.Second)
func (d *Duration) Ge(value time.Duration) *Duration {
if d.value == nil {
d.chain.fail("expected duration is set, but it is not")
return d
}
if !(*d.value >= value) {
d.chain.fail("\nexpected duration >= then:\n %s\n\nbut got:\n %s",
value, *d.value)
}
return d
}
// Lt succeeds if Duration is lesser than given value.
//
// Example:
// d := NewDuration(t, time.Second)
// d.Lt(time.Minute)
func (d *Duration) Lt(value time.Duration) *Duration {
if d.value == nil {
d.chain.fail("expected duration is set, but it is not")
return d
}
if !(*d.value < value) {
d.chain.fail("\nexpected duration < then:\n %s\n\nbut got:\n %s",
value, *d.value)
}
return d
}
// Le succeeds if Duration is lesser than or equal to given value.
//
// Example:
// d := NewDuration(t, time.Second)
// d.Le(time.Minute)
func (d *Duration) Le(value time.Duration) *Duration {
if d.value == nil {
d.chain.fail("expected duration is set, but it is not")
return d
}
if !(*d.value <= value) {
d.chain.fail("\nexpected duration <= then:\n %s\n\nbut got:\n %s",
value, *d.value)
}
return d
}
// InRange succeeds if Duration is in given range [min; max].
//
// Example:
// d := NewDuration(t, time.Minute)
// d.InRange(time.Second, time.Hour)
// d.InRange(time.Minute, time.Minute)
func (d *Duration) InRange(min, max time.Duration) *Duration {
if d.value == nil {
d.chain.fail("expected duration is set, but it is not")
return d
}
if !(*d.value >= min && *d.value <= max) {
d.chain.fail(
"\nexpected duration in range:\n min: %s\n max: %s\n\nbut got: %s",
min, max, *d.value)
}
return d
}

463
vendor/gopkg.in/gavv/httpexpect.v2/expect.go generated vendored Normal file
View file

@ -0,0 +1,463 @@
// Package httpexpect helps with end-to-end HTTP and REST API testing.
//
// Usage examples
//
// See example directory:
// - https://godoc.org/github.com/gavv/httpexpect/_examples
// - https://github.com/gavv/httpexpect/tree/master/_examples
//
// Communication mode
//
// There are two common ways to test API with httpexpect:
// - start HTTP server and instruct httpexpect to use HTTP client for communication
// - don't start server and instruct httpexpect to invoke http handler directly
//
// The second approach works only if the server is a Go module and its handler can
// be imported in tests.
//
// Concrete behaviour is determined by Client implementation passed to Config struct.
// If you're using http.Client, set its Transport field (http.RoundTriper) to one of
// the following:
// 1. default (nil) - use HTTP transport from net/http (you should start server)
// 2. httpexpect.Binder - invoke given http.Handler directly
// 3. httpexpect.FastBinder - invoke given fasthttp.RequestHandler directly
//
// Note that http handler can be usually obtained from http framework you're using.
// E.g., echo framework provides either http.Handler or fasthttp.RequestHandler.
//
// You can also provide your own implementation of RequestFactory (creates http.Request),
// or Client (gets http.Request and returns http.Response).
//
// If you're starting server from tests, it's very handy to use net/http/httptest.
//
// Value equality
//
// Whenever values are checked for equality in httpexpect, they are converted
// to "canonical form":
// - structs are converted to map[string]interface{}
// - type aliases are removed
// - numeric types are converted to float64
// - non-nil interfaces pointing to nil slices and maps are replaced with
// nil interfaces
//
// This is equivalent to subsequently json.Marshal() and json.Unmarshal() the value
// and currently is implemented so.
//
// Failure handling
//
// When some check fails, failure is reported. If non-fatal failures are used
// (see Reporter interface), execution is continued and instance that was checked
// is marked as failed.
//
// If specific instance is marked as failed, all subsequent checks are ignored
// for this instance and for any child instances retrieved after failure.
//
// Example:
// array := NewArray(NewAssertReporter(t), []interface{}{"foo", 123})
//
// e0 := array.Element(0) // success
// e1 := array.Element(1) // success
//
// s0 := e0.String() // success
// s1 := e1.String() // failure; e1 and s1 are marked as failed, e0 and s0 are not
//
// s0.Equal("foo") // success
// s1.Equal("bar") // this check is ignored because s1 is marked as failed
package httpexpect
import (
"io"
"net/http"
"net/http/cookiejar"
"time"
"github.com/gorilla/websocket"
"golang.org/x/net/publicsuffix"
)
// Expect is a toplevel object that contains user Config and allows
// to construct Request objects.
type Expect struct {
config Config
builders []func(*Request)
matchers []func(*Response)
}
// Config contains various settings.
type Config struct {
// BaseURL is a URL to prepended to all request. My be empty. If
// non-empty, trailing slash is allowed but not required and is
// appended automatically.
BaseURL string
// RequestFactory is used to pass in a custom *http.Request generation func.
// May be nil.
//
// You can use DefaultRequestFactory, or provide custom implementation.
// Useful for Google App Engine testing for example.
RequestFactory RequestFactory
// Client is used to send http.Request and receive http.Response.
// Should not be nil.
//
// You can use http.DefaultClient or http.Client, or provide
// custom implementation.
Client Client
// WebsocketDialer is used to establish websocket.Conn and receive
// http.Response of handshake result.
// Should not be nil.
//
// You can use websocket.DefaultDialer or websocket.Dialer, or provide
// custom implementation.
WebsocketDialer WebsocketDialer
// Reporter is used to report failures.
// Should not be nil.
//
// You can use AssertReporter, RequireReporter (they use testify),
// or testing.TB, or provide custom implementation.
Reporter Reporter
// Printers are used to print requests and responses.
// May be nil.
//
// You can use CompactPrinter, DebugPrinter, CurlPrinter, or provide
// custom implementation.
//
// You can also use builtin printers with alternative Logger if
// you're happy with their format, but want to send logs somewhere
// else instead of testing.TB.
Printers []Printer
}
// RequestFactory is used to create all http.Request objects.
// aetest.Instance from the Google App Engine implements this interface.
type RequestFactory interface {
NewRequest(method, urlStr string, body io.Reader) (*http.Request, error)
}
// Client is used to send http.Request and receive http.Response.
// http.Client implements this interface.
//
// Binder and FastBinder may be used to obtain this interface implementation.
//
// Example:
// httpBinderClient := &http.Client{
// Transport: httpexpect.NewBinder(HTTPHandler),
// }
// fastBinderClient := &http.Client{
// Transport: httpexpect.NewFastBinder(FastHTTPHandler),
// }
type Client interface {
// Do sends request and returns response.
Do(*http.Request) (*http.Response, error)
}
// WebsocketDialer is used to establish websocket.Conn and receive http.Response
// of handshake result.
// websocket.Dialer implements this interface.
//
// NewWebsocketDialer and NewFastWebsocketDialer may be used to obtain this
// interface implementation.
//
// Example:
// e := httpexpect.WithConfig(httpexpect.Config{
// BaseURL: "http://example.com",
// WebsocketDialer: httpexpect.NewWebsocketDialer(myHandler),
// })
type WebsocketDialer interface {
// Dial establishes new WebSocket connection and returns response
// of handshake result.
Dial(url string, reqH http.Header) (*websocket.Conn, *http.Response, error)
}
// Printer is used to print requests and responses.
// CompactPrinter, DebugPrinter, and CurlPrinter implement this interface.
type Printer interface {
// Request is called before request is sent.
Request(*http.Request)
// Response is called after response is received.
Response(*http.Response, time.Duration)
}
// WebsocketPrinter is used to print writes and reads of WebSocket connection.
//
// If WebSocket connection is used, all Printers that also implement WebsocketPrinter
// are invoked on every WebSocket message read or written.
//
// DebugPrinter implements this interface.
type WebsocketPrinter interface {
Printer
// WebsocketWrite is called before writes to WebSocket connection.
WebsocketWrite(typ int, content []byte, closeCode int)
// WebsocketRead is called after reads from WebSocket connection.
WebsocketRead(typ int, content []byte, closeCode int)
}
// Logger is used as output backend for Printer.
// testing.TB implements this interface.
type Logger interface {
// Logf writes message to log.
Logf(fmt string, args ...interface{})
}
// Reporter is used to report failures.
// testing.TB, AssertReporter, and RequireReporter implement this interface.
type Reporter interface {
// Errorf reports failure.
// Allowed to return normally or terminate test using t.FailNow().
Errorf(message string, args ...interface{})
}
// LoggerReporter combines Logger and Reporter interfaces.
type LoggerReporter interface {
Logger
Reporter
}
// DefaultRequestFactory is the default RequestFactory implementation which just
// calls http.NewRequest.
type DefaultRequestFactory struct{}
// NewRequest implements RequestFactory.NewRequest.
func (DefaultRequestFactory) NewRequest(
method, urlStr string, body io.Reader) (*http.Request, error) {
return http.NewRequest(method, urlStr, body)
}
// New returns a new Expect object.
//
// baseURL specifies URL to prepended to all request. My be empty. If non-empty,
// trailing slash is allowed but not required and is appended automatically.
//
// New is a shorthand for WithConfig. It uses:
// - CompactPrinter as Printer, with testing.TB as Logger
// - AssertReporter as Reporter
// - DefaultRequestFactory as RequestFactory
//
// Client is set to a default client with a non-nil Jar:
// &http.Client{
// Jar: httpexpect.NewJar(),
// }
//
// Example:
// func TestSomething(t *testing.T) {
// e := httpexpect.New(t, "http://example.com/")
//
// e.GET("/path").
// Expect().
// Status(http.StatusOK)
// }
func New(t LoggerReporter, baseURL string) *Expect {
return WithConfig(Config{
BaseURL: baseURL,
Reporter: NewAssertReporter(t),
Printers: []Printer{
NewCompactPrinter(t),
},
})
}
// WithConfig returns a new Expect object with given config.
//
// Reporter should not be nil.
//
// If RequestFactory is nil, it's set to a DefaultRequestFactory instance.
//
// If Client is nil, it's set to a default client with a non-nil Jar:
// &http.Client{
// Jar: httpexpect.NewJar(),
// }
//
// If WebsocketDialer is nil, it's set to a default dialer:
// &websocket.Dialer{}
//
// Example:
// func TestSomething(t *testing.T) {
// e := httpexpect.WithConfig(httpexpect.Config{
// BaseURL: "http://example.com/",
// Client: &http.Client{
// Transport: httpexpect.NewBinder(myHandler()),
// Jar: httpexpect.NewJar(),
// },
// Reporter: httpexpect.NewAssertReporter(t),
// Printers: []httpexpect.Printer{
// httpexpect.NewCurlPrinter(t),
// httpexpect.NewDebugPrinter(t, true)
// },
// })
//
// e.GET("/path").
// Expect().
// Status(http.StatusOK)
// }
func WithConfig(config Config) *Expect {
if config.Reporter == nil {
panic("config.Reporter is nil")
}
if config.RequestFactory == nil {
config.RequestFactory = DefaultRequestFactory{}
}
if config.Client == nil {
config.Client = &http.Client{
Jar: NewJar(),
}
}
if config.WebsocketDialer == nil {
config.WebsocketDialer = &websocket.Dialer{}
}
return &Expect{
config: config,
}
}
// NewJar returns a new http.CookieJar.
//
// Returned jar is implemented in net/http/cookiejar. PublicSuffixList is
// implemented in golang.org/x/net/publicsuffix.
//
// Note that this jar ignores cookies when request url is empty.
func NewJar() http.CookieJar {
jar, err := cookiejar.New(&cookiejar.Options{
PublicSuffixList: publicsuffix.List,
})
if err != nil {
panic(err)
}
return jar
}
// Builder returns a copy of Expect instance with given builder attached to it.
// Returned copy contains all previously attached builders plus a new one.
// Builders are invoked from Request method, after constructing every new request.
//
// Example:
// e := httpexpect.New(t, "http://example.com")
//
// token := e.POST("/login").WithForm(Login{"ford", "betelgeuse7"}).
// Expect().
// Status(http.StatusOK).JSON().Object().Value("token").String().Raw()
//
// auth := e.Builder(func (req *httpexpect.Request) {
// req.WithHeader("Authorization", "Bearer "+token)
// })
//
// auth.GET("/restricted").
// Expect().
// Status(http.StatusOK)
func (e *Expect) Builder(builder func(*Request)) *Expect {
ret := *e
ret.builders = append(e.builders, builder)
return &ret
}
// Matcher returns a copy of Expect instance with given matcher attached to it.
// Returned copy contains all previously attached matchers plus a new one.
// Matchers are invoked from Request.Expect method, after retrieving a new response.
//
// Example:
// e := httpexpect.New(t, "http://example.com")
//
// m := e.Matcher(func (resp *httpexpect.Response) {
// resp.Header("API-Version").NotEmpty()
// })
//
// m.GET("/some-path").
// Expect().
// Status(http.StatusOK)
//
// m.GET("/bad-path").
// Expect().
// Status(http.StatusNotFound)
func (e *Expect) Matcher(matcher func(*Response)) *Expect {
ret := *e
ret.matchers = append(e.matchers, matcher)
return &ret
}
// Request returns a new Request object.
// Arguments a similar to NewRequest.
// After creating request, all builders attached to Expect object are invoked.
// See Builder.
func (e *Expect) Request(method, path string, pathargs ...interface{}) *Request {
req := NewRequest(e.config, method, path, pathargs...)
for _, builder := range e.builders {
builder(req)
}
for _, matcher := range e.matchers {
req.WithMatcher(matcher)
}
return req
}
// OPTIONS is a shorthand for e.Request("OPTIONS", path, pathargs...).
func (e *Expect) OPTIONS(path string, pathargs ...interface{}) *Request {
return e.Request("OPTIONS", path, pathargs...)
}
// HEAD is a shorthand for e.Request("HEAD", path, pathargs...).
func (e *Expect) HEAD(path string, pathargs ...interface{}) *Request {
return e.Request("HEAD", path, pathargs...)
}
// GET is a shorthand for e.Request("GET", path, pathargs...).
func (e *Expect) GET(path string, pathargs ...interface{}) *Request {
return e.Request("GET", path, pathargs...)
}
// POST is a shorthand for e.Request("POST", path, pathargs...).
func (e *Expect) POST(path string, pathargs ...interface{}) *Request {
return e.Request("POST", path, pathargs...)
}
// PUT is a shorthand for e.Request("PUT", path, pathargs...).
func (e *Expect) PUT(path string, pathargs ...interface{}) *Request {
return e.Request("PUT", path, pathargs...)
}
// PATCH is a shorthand for e.Request("PATCH", path, pathargs...).
func (e *Expect) PATCH(path string, pathargs ...interface{}) *Request {
return e.Request("PATCH", path, pathargs...)
}
// DELETE is a shorthand for e.Request("DELETE", path, pathargs...).
func (e *Expect) DELETE(path string, pathargs ...interface{}) *Request {
return e.Request("DELETE", path, pathargs...)
}
// Value is a shorthand for NewValue(e.config.Reporter, value).
func (e *Expect) Value(value interface{}) *Value {
return NewValue(e.config.Reporter, value)
}
// Object is a shorthand for NewObject(e.config.Reporter, value).
func (e *Expect) Object(value map[string]interface{}) *Object {
return NewObject(e.config.Reporter, value)
}
// Array is a shorthand for NewArray(e.config.Reporter, value).
func (e *Expect) Array(value []interface{}) *Array {
return NewArray(e.config.Reporter, value)
}
// String is a shorthand for NewString(e.config.Reporter, value).
func (e *Expect) String(value string) *String {
return NewString(e.config.Reporter, value)
}
// Number is a shorthand for NewNumber(e.config.Reporter, value).
func (e *Expect) Number(value float64) *Number {
return NewNumber(e.config.Reporter, value)
}
// Boolean is a shorthand for NewBoolean(e.config.Reporter, value).
func (e *Expect) Boolean(value bool) *Boolean {
return NewBoolean(e.config.Reporter, value)
}

184
vendor/gopkg.in/gavv/httpexpect.v2/helpers.go generated vendored Normal file
View file

@ -0,0 +1,184 @@
package httpexpect
import (
"encoding/json"
"fmt"
"reflect"
"regexp"
"github.com/xeipuuv/gojsonschema"
"github.com/yalp/jsonpath"
"github.com/yudai/gojsondiff"
"github.com/yudai/gojsondiff/formatter"
)
func toString(str interface{}) (s string, ok bool) {
ok = true
defer func() {
if err := recover(); err != nil {
ok = false
}
}()
s = reflect.ValueOf(str).Convert(reflect.TypeOf("")).String()
return
}
func getPath(chain *chain, value interface{}, path string) *Value {
if chain.failed() {
return &Value{*chain, nil}
}
result, err := jsonpath.Read(value, path)
if err != nil {
chain.fail(err.Error())
return &Value{*chain, nil}
}
return &Value{*chain, result}
}
func checkSchema(chain *chain, value, schema interface{}) {
if chain.failed() {
return
}
valueLoader := gojsonschema.NewGoLoader(value)
var schemaLoader gojsonschema.JSONLoader
if str, ok := toString(schema); ok {
if ok, _ := regexp.MatchString(`^\w+://`, str); ok {
schemaLoader = gojsonschema.NewReferenceLoader(str)
} else {
schemaLoader = gojsonschema.NewStringLoader(str)
}
} else {
schemaLoader = gojsonschema.NewGoLoader(schema)
}
result, err := gojsonschema.Validate(schemaLoader, valueLoader)
if err != nil {
chain.fail("\n%s\n\nschema:\n%s\n\nvalue:\n%s",
err.Error(),
dumpSchema(schema),
dumpValue(value))
return
}
if !result.Valid() {
errors := ""
for _, err := range result.Errors() {
errors += fmt.Sprintf(" %s\n", err)
}
chain.fail(
"\njson schema validation failed, schema:\n%s\n\nvalue:%s\n\nerrors:\n%s",
dumpSchema(schema),
dumpValue(value),
errors)
return
}
}
func dumpSchema(schema interface{}) string {
if s, ok := toString(schema); ok {
schema = s
}
return regexp.MustCompile(`(?m:^)`).
ReplaceAllString(fmt.Sprintf("%v", schema), " ")
}
func canonNumber(chain *chain, number interface{}) (f float64, ok bool) {
ok = true
defer func() {
if err := recover(); err != nil {
chain.fail("%v", err)
ok = false
}
}()
f = reflect.ValueOf(number).Convert(reflect.TypeOf(float64(0))).Float()
return
}
func canonArray(chain *chain, in interface{}) ([]interface{}, bool) {
var out []interface{}
data, ok := canonValue(chain, in)
if ok {
out, ok = data.([]interface{})
if !ok {
chain.fail("expected array, got %v", out)
}
}
return out, ok
}
func canonMap(chain *chain, in interface{}) (map[string]interface{}, bool) {
var out map[string]interface{}
data, ok := canonValue(chain, in)
if ok {
out, ok = data.(map[string]interface{})
if !ok {
chain.fail("expected map, got %v", out)
}
}
return out, ok
}
func canonValue(chain *chain, in interface{}) (interface{}, bool) {
b, err := json.Marshal(in)
if err != nil {
chain.fail(err.Error())
return nil, false
}
var out interface{}
if err := json.Unmarshal(b, &out); err != nil {
chain.fail(err.Error())
return nil, false
}
return out, true
}
func dumpValue(value interface{}) string {
b, err := json.MarshalIndent(value, " ", " ")
if err != nil {
return " " + fmt.Sprintf("%#v", value)
}
return " " + string(b)
}
func diffValues(expected, actual interface{}) string {
differ := gojsondiff.New()
var diff gojsondiff.Diff
if ve, ok := expected.(map[string]interface{}); ok {
if va, ok := actual.(map[string]interface{}); ok {
diff = differ.CompareObjects(ve, va)
} else {
return " (unavailable)"
}
} else if ve, ok := expected.([]interface{}); ok {
if va, ok := actual.([]interface{}); ok {
diff = differ.CompareArrays(ve, va)
} else {
return " (unavailable)"
}
} else {
return " (unavailable)"
}
config := formatter.AsciiFormatterConfig{
ShowArrayIndex: true,
}
f := formatter.NewAsciiFormatter(expected, config)
str, err := f.Format(diff)
if err != nil {
return " (unavailable)"
}
return "--- expected\n+++ actual\n" + str
}

198
vendor/gopkg.in/gavv/httpexpect.v2/match.go generated vendored Normal file
View file

@ -0,0 +1,198 @@
package httpexpect
import (
"reflect"
)
// Match provides methods to inspect attached regexp match results.
type Match struct {
chain chain
submatches []string
names map[string]int
}
// NewMatch returns a new Match object given a reporter used to report
// failures and submatches to be inspected.
//
// reporter should not be nil. submatches and names may be nil.
//
// Example:
// s := "http://example.com/users/john"
// r := regexp.MustCompile(`http://(?P<host>.+)/users/(?P<user>.+)`)
// m := NewMatch(reporter, r.FindStringSubmatch(s), r.SubexpNames())
//
// m.NotEmpty()
// m.Length().Equal(3)
//
// m.Index(0).Equal("http://example.com/users/john")
// m.Index(1).Equal("example.com")
// m.Index(2).Equal("john")
//
// m.Name("host").Equal("example.com")
// m.Name("user").Equal("john")
func NewMatch(reporter Reporter, submatches []string, names []string) *Match {
return makeMatch(makeChain(reporter), submatches, names)
}
func makeMatch(chain chain, submatches []string, names []string) *Match {
if submatches == nil {
submatches = []string{}
}
namemap := map[string]int{}
for n, name := range names {
if name != "" {
namemap[name] = n
}
}
return &Match{chain, submatches, namemap}
}
// Raw returns underlying submatches attached to Match.
// This is the value originally passed to NewMatch.
//
// Example:
// m := NewMatch(t, submatches, names)
// assert.Equal(t, submatches, m.Raw())
func (m *Match) Raw() []string {
return m.submatches
}
// Length returns a new Number object that may be used to inspect
// number of submatches.
//
// Example:
// m := NewMatch(t, submatches, names)
// m.Length().Equal(len(submatches))
func (m *Match) Length() *Number {
return &Number{m.chain, float64(len(m.submatches))}
}
// Index returns a new String object that may be used to inspect submatch
// with given index.
//
// Note that submatch with index 0 contains the whole match. If index is out
// of bounds, Index reports failure and returns empty (but non-nil) value.
//
// Example:
// s := "http://example.com/users/john"
//
// r := regexp.MustCompile(`http://(.+)/users/(.+)`)
// m := NewMatch(t, r.FindStringSubmatch(s), nil)
//
// m.Index(0).Equal("http://example.com/users/john")
// m.Index(1).Equal("example.com")
// m.Index(2).Equal("john")
func (m *Match) Index(index int) *String {
if index < 0 || index >= len(m.submatches) {
m.chain.fail(
"\nsubmatch index out of bounds:\n index %d\n\n bounds [%d; %d)",
index,
0,
len(m.submatches))
return &String{m.chain, ""}
}
return &String{m.chain, m.submatches[index]}
}
// Name returns a new String object that may be used to inspect submatch
// with given name.
//
// If there is no submatch with given name, Name reports failure and returns
// empty (but non-nil) value.
//
// Example:
// s := "http://example.com/users/john"
//
// r := regexp.MustCompile(`http://(?P<host>.+)/users/(?P<user>.+)`)
// m := NewMatch(t, r.FindStringSubmatch(s), r.SubexpNames())
//
// m.Name("host").Equal("example.com")
// m.Name("user").Equal("john")
func (m *Match) Name(name string) *String {
index, ok := m.names[name]
if !ok {
m.chain.fail(
"\nsubmatch name not found:\n %q\n\navailable names:\n%s",
name,
dumpValue(m.names))
return &String{m.chain, ""}
}
return m.Index(index)
}
// Empty succeeds if submatches array is empty.
//
// Example:
// m := NewMatch(t, submatches, names)
// m.Empty()
func (m *Match) Empty() *Match {
if len(m.submatches) != 0 {
m.chain.fail("\nexpected zero submatches, but got:\n %s",
dumpValue(m.submatches))
}
return m
}
// NotEmpty succeeds if submatches array is non-empty.
//
// Example:
// m := NewMatch(t, submatches, names)
// m.NotEmpty()
func (m *Match) NotEmpty() *Match {
if len(m.submatches) == 0 {
m.chain.fail("expected non-zero submatches")
}
return m
}
// Values succeeds if submatches array, starting from index 1, is equal to
// given array.
//
// Note that submatch with index 0 contains the whole match and is not
// included into this check.
//
// Example:
// s := "http://example.com/users/john"
// r := regexp.MustCompile(`http://(.+)/users/(.+)`)
// m := NewMatch(t, r.FindStringSubmatch(s), nil)
// m.Values("example.com", "john")
func (m *Match) Values(values ...string) *Match {
if values == nil {
values = []string{}
}
if !reflect.DeepEqual(values, m.getValues()) {
m.chain.fail("\nexpected submatches equal to:\n%s\n\nbut got:\n%s",
dumpValue(values),
dumpValue(m.getValues()))
}
return m
}
// NotValues succeeds if submatches array, starting from index 1, is not
// equal to given array.
//
// Note that submatch with index 0 contains the whole match and is not
// included into this check.
//
// Example:
// s := "http://example.com/users/john"
// r := regexp.MustCompile(`http://(.+)/users/(.+)`)
// m := NewMatch(t, r.FindStringSubmatch(s), nil)
// m.NotValues("example.com", "bob")
func (m *Match) NotValues(values ...string) *Match {
if values == nil {
values = []string{}
}
if reflect.DeepEqual(values, m.getValues()) {
m.chain.fail("\nexpected submatches not equal to:\n%s",
dumpValue(values))
}
return m
}
func (m *Match) getValues() []string {
if len(m.submatches) > 1 {
return m.submatches[1:]
}
return []string{}
}

244
vendor/gopkg.in/gavv/httpexpect.v2/number.go generated vendored Normal file
View file

@ -0,0 +1,244 @@
package httpexpect
import (
"math"
)
// Number provides methods to inspect attached float64 value
// (Go representation of JSON number).
type Number struct {
chain chain
value float64
}
// NewNumber returns a new Number given a reporter used to report
// failures and value to be inspected.
//
// reporter should not be nil.
//
// Example:
// number := NewNumber(t, 123.4)
func NewNumber(reporter Reporter, value float64) *Number {
return &Number{makeChain(reporter), value}
}
// Raw returns underlying value attached to Number.
// This is the value originally passed to NewNumber.
//
// Example:
// number := NewNumber(t, 123.4)
// assert.Equal(t, 123.4, number.Raw())
func (n *Number) Raw() float64 {
return n.value
}
// Path is similar to Value.Path.
func (n *Number) Path(path string) *Value {
return getPath(&n.chain, n.value, path)
}
// Schema is similar to Value.Schema.
func (n *Number) Schema(schema interface{}) *Number {
checkSchema(&n.chain, n.value, schema)
return n
}
// Equal succeeds if number is equal to given value.
//
// value should have numeric type convertible to float64. Before comparison,
// it is converted to float64.
//
// Example:
// number := NewNumber(t, 123)
// number.Equal(float64(123))
// number.Equal(int32(123))
func (n *Number) Equal(value interface{}) *Number {
v, ok := canonNumber(&n.chain, value)
if !ok {
return n
}
if !(n.value == v) {
n.chain.fail("\nexpected number equal to:\n %v\n\nbut got:\n %v",
v, n.value)
}
return n
}
// NotEqual succeeds if number is not equal to given value.
//
// value should have numeric type convertible to float64. Before comparison,
// it is converted to float64.
//
// Example:
// number := NewNumber(t, 123)
// number.NotEqual(float64(321))
// number.NotEqual(int32(321))
func (n *Number) NotEqual(value interface{}) *Number {
v, ok := canonNumber(&n.chain, value)
if !ok {
return n
}
if !(n.value != v) {
n.chain.fail("\nexpected number not equal to:\n %v\n\nbut got:\n %v",
v, n.value)
}
return n
}
// EqualDelta succeeds if two numerals are within delta of each other.
//
// Example:
// number := NewNumber(t, 123.0)
// number.EqualDelta(123.2, 0.3)
func (n *Number) EqualDelta(value, delta float64) *Number {
if math.IsNaN(n.value) || math.IsNaN(value) || math.IsNaN(delta) {
n.chain.fail("\nexpected number equal to:\n %v\n\nbut got:\n %v\n\ndelta:\n %v",
value, n.value, delta)
return n
}
diff := (n.value - value)
if diff < -delta || diff > delta {
n.chain.fail("\nexpected number equal to:\n %v\n\nbut got:\n %v\n\ndelta:\n %v",
value, n.value, delta)
return n
}
return n
}
// NotEqualDelta succeeds if two numerals are not within delta of each other.
//
// Example:
// number := NewNumber(t, 123.0)
// number.NotEqualDelta(123.2, 0.1)
func (n *Number) NotEqualDelta(value, delta float64) *Number {
if math.IsNaN(n.value) || math.IsNaN(value) || math.IsNaN(delta) {
n.chain.fail(
"\nexpected number not equal to:\n %v\n\nbut got:\n %v\n\ndelta:\n %v",
value, n.value, delta)
return n
}
diff := (n.value - value)
if !(diff < -delta || diff > delta) {
n.chain.fail(
"\nexpected number not equal to:\n %v\n\nbut got:\n %v\n\ndelta:\n %v",
value, n.value, delta)
return n
}
return n
}
// Gt succeeds if number is greater than given value.
//
// value should have numeric type convertible to float64. Before comparison,
// it is converted to float64.
//
// Example:
// number := NewNumber(t, 123)
// number.Gt(float64(122))
// number.Gt(int32(122))
func (n *Number) Gt(value interface{}) *Number {
v, ok := canonNumber(&n.chain, value)
if !ok {
return n
}
if !(n.value > v) {
n.chain.fail("\nexpected number > then:\n %v\n\nbut got:\n %v",
v, n.value)
}
return n
}
// Ge succeeds if number is greater than or equal to given value.
//
// value should have numeric type convertible to float64. Before comparison,
// it is converted to float64.
//
// Example:
// number := NewNumber(t, 123)
// number.Ge(float64(122))
// number.Ge(int32(122))
func (n *Number) Ge(value interface{}) *Number {
v, ok := canonNumber(&n.chain, value)
if !ok {
return n
}
if !(n.value >= v) {
n.chain.fail("\nexpected number >= then:\n %v\n\nbut got:\n %v",
v, n.value)
}
return n
}
// Lt succeeds if number is lesser than given value.
//
// value should have numeric type convertible to float64. Before comparison,
// it is converted to float64.
//
// Example:
// number := NewNumber(t, 123)
// number.Lt(float64(124))
// number.Lt(int32(124))
func (n *Number) Lt(value interface{}) *Number {
v, ok := canonNumber(&n.chain, value)
if !ok {
return n
}
if !(n.value < v) {
n.chain.fail("\nexpected number < then:\n %v\n\nbut got:\n %v",
v, n.value)
}
return n
}
// Le succeeds if number is lesser than or equal to given value.
//
// value should have numeric type convertible to float64. Before comparison,
// it is converted to float64.
//
// Example:
// number := NewNumber(t, 123)
// number.Le(float64(124))
// number.Le(int32(124))
func (n *Number) Le(value interface{}) *Number {
v, ok := canonNumber(&n.chain, value)
if !ok {
return n
}
if !(n.value <= v) {
n.chain.fail("\nexpected number <= then:\n %v\n\nbut got:\n %v",
v, n.value)
}
return n
}
// InRange succeeds if number is in given range [min; max].
//
// min and max should have numeric type convertible to float64. Before comparison,
// they are converted to float64.
//
// Example:
// number := NewNumber(t, 123)
// number.InRange(float32(100), int32(200)) // success
// number.InRange(100, 200) // success
// number.InRange(123, 123) // success
func (n *Number) InRange(min, max interface{}) *Number {
a, ok := canonNumber(&n.chain, min)
if !ok {
return n
}
b, ok := canonNumber(&n.chain, max)
if !ok {
return n
}
if !(n.value >= a && n.value <= b) {
n.chain.fail("\nexpected number in range:\n [%v; %v]\n\nbut got:\n %v",
a, b, n.value)
}
return n
}

329
vendor/gopkg.in/gavv/httpexpect.v2/object.go generated vendored Normal file
View file

@ -0,0 +1,329 @@
package httpexpect
import (
"reflect"
)
// Object provides methods to inspect attached map[string]interface{} object
// (Go representation of JSON object).
type Object struct {
chain chain
value map[string]interface{}
}
// NewObject returns a new Object given a reporter used to report failures
// and value to be inspected.
//
// Both reporter and value should not be nil. If value is nil, failure is
// reported.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
func NewObject(reporter Reporter, value map[string]interface{}) *Object {
chain := makeChain(reporter)
if value == nil {
chain.fail("expected non-nil map value")
} else {
value, _ = canonMap(&chain, value)
}
return &Object{chain, value}
}
// Raw returns underlying value attached to Object.
// This is the value originally passed to NewObject, converted to canonical form.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
// assert.Equal(t, map[string]interface{}{"foo": 123.0}, object.Raw())
func (o *Object) Raw() map[string]interface{} {
return o.value
}
// Path is similar to Value.Path.
func (o *Object) Path(path string) *Value {
return getPath(&o.chain, o.value, path)
}
// Schema is similar to Value.Schema.
func (o *Object) Schema(schema interface{}) *Object {
checkSchema(&o.chain, o.value, schema)
return o
}
// Keys returns a new Array object that may be used to inspect objects keys.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123, "bar": 456})
// object.Keys().ContainsOnly("foo", "bar")
func (o *Object) Keys() *Array {
keys := []interface{}{}
for k := range o.value {
keys = append(keys, k)
}
return &Array{o.chain, keys}
}
// Values returns a new Array object that may be used to inspect objects values.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123, "bar": 456})
// object.Values().ContainsOnly(123, 456)
func (o *Object) Values() *Array {
values := []interface{}{}
for _, v := range o.value {
values = append(values, v)
}
return &Array{o.chain, values}
}
// Value returns a new Value object that may be used to inspect single value
// for given key.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
// object.Value("foo").Number().Equal(123)
func (o *Object) Value(key string) *Value {
value, ok := o.value[key]
if !ok {
o.chain.fail("\nexpected object containing key '%s', but got:\n%s",
key, dumpValue(o.value))
return &Value{o.chain, nil}
}
return &Value{o.chain, value}
}
// Empty succeeds if object is empty.
//
// Example:
// object := NewObject(t, map[string]interface{}{})
// object.Empty()
func (o *Object) Empty() *Object {
return o.Equal(map[string]interface{}{})
}
// NotEmpty succeeds if object is non-empty.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
// object.NotEmpty()
func (o *Object) NotEmpty() *Object {
return o.NotEqual(map[string]interface{}{})
}
// Equal succeeds if object is equal to given Go map or struct.
// Before comparison, both object and value are converted to canonical form.
//
// value should be map[string]interface{} or struct.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
// object.Equal(map[string]interface{}{"foo": 123})
func (o *Object) Equal(value interface{}) *Object {
expected, ok := canonMap(&o.chain, value)
if !ok {
return o
}
if !reflect.DeepEqual(expected, o.value) {
o.chain.fail("\nexpected object equal to:\n%s\n\nbut got:\n%s\n\ndiff:\n%s",
dumpValue(expected),
dumpValue(o.value),
diffValues(expected, o.value))
}
return o
}
// NotEqual succeeds if object is not equal to given Go map or struct.
// Before comparison, both object and value are converted to canonical form.
//
// value should be map[string]interface{} or struct.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
// object.Equal(map[string]interface{}{"bar": 123})
func (o *Object) NotEqual(v interface{}) *Object {
expected, ok := canonMap(&o.chain, v)
if !ok {
return o
}
if reflect.DeepEqual(expected, o.value) {
o.chain.fail("\nexpected object not equal to:\n%s",
dumpValue(expected))
}
return o
}
// ContainsKey succeeds if object contains given key.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
// object.ContainsKey("foo")
func (o *Object) ContainsKey(key string) *Object {
if !o.containsKey(key) {
o.chain.fail("\nexpected object containing key '%s', but got:\n%s",
key, dumpValue(o.value))
}
return o
}
// NotContainsKey succeeds if object doesn't contain given key.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
// object.NotContainsKey("bar")
func (o *Object) NotContainsKey(key string) *Object {
if o.containsKey(key) {
o.chain.fail(
"\nexpected object not containing key '%s', but got:\n%s", key,
dumpValue(o.value))
}
return o
}
// ContainsMap succeeds if object contains given Go value.
// Before comparison, both object and value are converted to canonical form.
//
// value should be map[string]interface{} or struct.
//
// Example:
// object := NewObject(t, map[string]interface{}{
// "foo": 123,
// "bar": []interface{}{"x", "y"},
// "bar": map[string]interface{}{
// "a": true,
// "b": false,
// },
// })
//
// object.ContainsMap(map[string]interface{}{ // success
// "foo": 123,
// "bar": map[string]interface{}{
// "a": true,
// },
// })
//
// object.ContainsMap(map[string]interface{}{ // failure
// "foo": 123,
// "qux": 456,
// })
//
// object.ContainsMap(map[string]interface{}{ // failure, slices should match exactly
// "bar": []interface{}{"x"},
// })
func (o *Object) ContainsMap(value interface{}) *Object {
if !o.containsMap(value) {
o.chain.fail("\nexpected object containing sub-object:\n%s\n\nbut got:\n%s",
dumpValue(value), dumpValue(o.value))
}
return o
}
// NotContainsMap succeeds if object doesn't contain given Go value.
// Before comparison, both object and value are converted to canonical form.
//
// value should be map[string]interface{} or struct.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123, "bar": 456})
// object.NotContainsMap(map[string]interface{}{"foo": 123, "bar": "no-no-no"})
func (o *Object) NotContainsMap(value interface{}) *Object {
if o.containsMap(value) {
o.chain.fail("\nexpected object not containing sub-object:\n%s\n\nbut got:\n%s",
dumpValue(value), dumpValue(o.value))
}
return o
}
// ValueEqual succeeds if object's value for given key is equal to given Go value.
// Before comparison, both values are converted to canonical form.
//
// value should be map[string]interface{} or struct.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
// object.ValueEqual("foo", 123)
func (o *Object) ValueEqual(key string, value interface{}) *Object {
if !o.containsKey(key) {
o.chain.fail("\nexpected object containing key '%s', but got:\n%s",
key, dumpValue(o.value))
return o
}
expected, ok := canonValue(&o.chain, value)
if !ok {
return o
}
if !reflect.DeepEqual(expected, o.value[key]) {
o.chain.fail(
"\nexpected value for key '%s' equal to:\n%s\n\nbut got:\n%s\n\ndiff:\n%s",
key,
dumpValue(expected),
dumpValue(o.value[key]),
diffValues(expected, o.value[key]))
}
return o
}
// ValueNotEqual succeeds if object's value for given key is not equal to given
// Go value. Before comparison, both values are converted to canonical form.
//
// value should be map[string]interface{} or struct.
//
// If object doesn't contain any value for given key, failure is reported.
//
// Example:
// object := NewObject(t, map[string]interface{}{"foo": 123})
// object.ValueNotEqual("foo", "bad value") // success
// object.ValueNotEqual("bar", "bad value") // failure! (key is missing)
func (o *Object) ValueNotEqual(key string, value interface{}) *Object {
if !o.containsKey(key) {
o.chain.fail("\nexpected object containing key '%s', but got:\n%s",
key, dumpValue(o.value))
return o
}
expected, ok := canonValue(&o.chain, value)
if !ok {
return o
}
if reflect.DeepEqual(expected, o.value[key]) {
o.chain.fail("\nexpected value for key '%s' not equal to:\n%s",
key, dumpValue(expected))
}
return o
}
func (o *Object) containsKey(key string) bool {
for k := range o.value {
if k == key {
return true
}
}
return false
}
func (o *Object) containsMap(sm interface{}) bool {
submap, ok := canonMap(&o.chain, sm)
if !ok {
return false
}
return checkContainsMap(o.value, submap)
}
func checkContainsMap(outer, inner map[string]interface{}) bool {
for k, iv := range inner {
ov, ok := outer[k]
if !ok {
return false
}
if ovm, ok := ov.(map[string]interface{}); ok {
if ivm, ok := iv.(map[string]interface{}); ok {
if !checkContainsMap(ovm, ivm) {
return false
}
continue
}
}
if !reflect.DeepEqual(ov, iv) {
return false
}
}
return true
}

141
vendor/gopkg.in/gavv/httpexpect.v2/printer.go generated vendored Normal file
View file

@ -0,0 +1,141 @@
package httpexpect
import (
"bytes"
"fmt"
"net/http"
"net/http/httputil"
"strings"
"time"
"github.com/gorilla/websocket"
"github.com/moul/http2curl"
)
// CurlPrinter implements Printer. Uses http2curl to dump requests as
// curl commands.
type CurlPrinter struct {
logger Logger
}
// NewCurlPrinter returns a new CurlPrinter given a logger.
func NewCurlPrinter(logger Logger) CurlPrinter {
return CurlPrinter{logger}
}
// Request implements Printer.Request.
func (p CurlPrinter) Request(req *http.Request) {
if req != nil {
cmd, err := http2curl.GetCurlCommand(req)
if err != nil {
panic(err)
}
p.logger.Logf("%s", cmd.String())
}
}
// Response implements Printer.Response.
func (CurlPrinter) Response(*http.Response, time.Duration) {
}
// CompactPrinter implements Printer. It prints requests in compact form.
type CompactPrinter struct {
logger Logger
}
// NewCompactPrinter returns a new CompactPrinter given a logger.
func NewCompactPrinter(logger Logger) CompactPrinter {
return CompactPrinter{logger}
}
// Request implements Printer.Request.
func (p CompactPrinter) Request(req *http.Request) {
if req != nil {
p.logger.Logf("%s %s", req.Method, req.URL)
}
}
// Response implements Printer.Response.
func (CompactPrinter) Response(*http.Response, time.Duration) {
}
// DebugPrinter implements Printer. Uses net/http/httputil to dump
// both requests and responses.
type DebugPrinter struct {
logger Logger
body bool
}
// NewDebugPrinter returns a new DebugPrinter given a logger and body
// flag. If body is true, request and response body is also printed.
func NewDebugPrinter(logger Logger, body bool) DebugPrinter {
return DebugPrinter{logger, body}
}
// Request implements Printer.Request.
func (p DebugPrinter) Request(req *http.Request) {
if req == nil {
return
}
dump, err := httputil.DumpRequest(req, p.body)
if err != nil {
panic(err)
}
p.logger.Logf("%s", dump)
}
// Response implements Printer.Response.
func (p DebugPrinter) Response(resp *http.Response, duration time.Duration) {
if resp == nil {
return
}
dump, err := httputil.DumpResponse(resp, p.body)
if err != nil {
panic(err)
}
text := strings.Replace(string(dump), "\r\n", "\n", -1)
lines := strings.SplitN(text, "\n", 2)
p.logger.Logf("%s %s\n%s", lines[0], duration, lines[1])
}
// WebsocketWrite implements WebsocketPrinter.WebsocketWrite.
func (p DebugPrinter) WebsocketWrite(typ int, content []byte, closeCode int) {
b := &bytes.Buffer{}
fmt.Fprintf(b, "-> Sent: %s", wsMessageTypeName(typ))
if typ == websocket.CloseMessage {
fmt.Fprintf(b, " (%d)", closeCode)
}
fmt.Fprint(b, "\n")
if len(content) > 0 {
if typ == websocket.BinaryMessage {
fmt.Fprintf(b, "%v\n", content)
} else {
fmt.Fprintf(b, "%s\n", content)
}
}
fmt.Fprintf(b, "\n")
p.logger.Logf(b.String())
}
// WebsocketRead implements WebsocketPrinter.WebsocketRead.
func (p DebugPrinter) WebsocketRead(typ int, content []byte, closeCode int) {
b := &bytes.Buffer{}
fmt.Fprintf(b, "<- Received: %s", wsMessageTypeName(typ))
if typ == websocket.CloseMessage {
fmt.Fprintf(b, " (%d)", closeCode)
}
fmt.Fprint(b, "\n")
if len(content) > 0 {
if typ == websocket.BinaryMessage {
fmt.Fprintf(b, "%v\n", content)
} else {
fmt.Fprintf(b, "%s\n", content)
}
}
fmt.Fprintf(b, "\n")
p.logger.Logf(b.String())
}

40
vendor/gopkg.in/gavv/httpexpect.v2/reporter.go generated vendored Normal file
View file

@ -0,0 +1,40 @@
package httpexpect
import (
"fmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// AssertReporter implements Reporter interface using `testify/assert'
// package. Failures are non-fatal with this reporter.
type AssertReporter struct {
backend *assert.Assertions
}
// NewAssertReporter returns a new AssertReporter object.
func NewAssertReporter(t assert.TestingT) *AssertReporter {
return &AssertReporter{assert.New(t)}
}
// Errorf implements Reporter.Errorf.
func (r *AssertReporter) Errorf(message string, args ...interface{}) {
r.backend.Fail(fmt.Sprintf(message, args...))
}
// RequireReporter implements Reporter interface using `testify/require'
// package. Failures fatal with this reporter.
type RequireReporter struct {
backend *require.Assertions
}
// NewRequireReporter returns a new RequireReporter object.
func NewRequireReporter(t require.TestingT) *RequireReporter {
return &RequireReporter{require.New(t)}
}
// Errorf implements Reporter.Errorf.
func (r *RequireReporter) Errorf(message string, args ...interface{}) {
r.backend.FailNow(fmt.Sprintf(message, args...))
}

1071
vendor/gopkg.in/gavv/httpexpect.v2/request.go generated vendored Normal file

File diff suppressed because it is too large Load diff

588
vendor/gopkg.in/gavv/httpexpect.v2/response.go generated vendored Normal file
View file

@ -0,0 +1,588 @@
package httpexpect
import (
"bytes"
"encoding/json"
"io/ioutil"
"mime"
"net/http"
"reflect"
"regexp"
"strconv"
"strings"
"time"
"github.com/ajg/form"
"github.com/gorilla/websocket"
)
// StatusRange is enum for response status ranges.
type StatusRange int
const (
// Status1xx defines "Informational" status codes.
Status1xx StatusRange = 100
// Status2xx defines "Success" status codes.
Status2xx StatusRange = 200
// Status3xx defines "Redirection" status codes.
Status3xx StatusRange = 300
// Status4xx defines "Client Error" status codes.
Status4xx StatusRange = 400
// Status5xx defines "Server Error" status codes.
Status5xx StatusRange = 500
)
// Response provides methods to inspect attached http.Response object.
type Response struct {
config Config
chain chain
resp *http.Response
content []byte
cookies []*http.Cookie
websocket *websocket.Conn
rtt *time.Duration
}
// NewResponse returns a new Response given a reporter used to report
// failures and http.Response to be inspected.
//
// Both reporter and response should not be nil. If response is nil,
// failure is reported.
//
// If rtt is given, it defines response round-trip time to be reported
// by response.RoundTripTime().
func NewResponse(
reporter Reporter, response *http.Response, rtt ...time.Duration,
) *Response {
var rttPtr *time.Duration
if len(rtt) > 0 {
rttPtr = &rtt[0]
}
return makeResponse(responseOpts{
chain: makeChain(reporter),
response: response,
rtt: rttPtr,
})
}
type responseOpts struct {
config Config
chain chain
response *http.Response
websocket *websocket.Conn
rtt *time.Duration
}
func makeResponse(opts responseOpts) *Response {
var content []byte
var cookies []*http.Cookie
if opts.response != nil {
content = getContent(&opts.chain, opts.response)
cookies = opts.response.Cookies()
} else {
opts.chain.fail("expected non-nil response")
}
return &Response{
config: opts.config,
chain: opts.chain,
resp: opts.response,
content: content,
cookies: cookies,
websocket: opts.websocket,
rtt: opts.rtt,
}
}
func getContent(chain *chain, resp *http.Response) []byte {
if resp.Body == nil {
return []byte{}
}
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
chain.fail(err.Error())
return nil
}
return content
}
// Raw returns underlying http.Response object.
// This is the value originally passed to NewResponse.
func (r *Response) Raw() *http.Response {
return r.resp
}
// RoundTripTime returns a new Duration object that may be used to inspect
// the round-trip time.
//
// The returned duration is a time interval starting just before request is
// sent and ending right after response is received (handshake finished for
// WebSocket request), retrieved from a monotonic clock source.
//
// Example:
// resp := NewResponse(t, response, time.Duration(10000000))
// resp.RoundTripTime().Lt(10 * time.Millisecond)
func (r *Response) RoundTripTime() *Duration {
return &Duration{r.chain, r.rtt}
}
// Deprecated: use RoundTripTime instead.
func (r *Response) Duration() *Number {
if r.rtt == nil {
return &Number{r.chain, 0}
}
return &Number{r.chain, float64(*r.rtt)}
}
// Status succeeds if response contains given status code.
//
// Example:
// resp := NewResponse(t, response)
// resp.Status(http.StatusOK)
func (r *Response) Status(status int) *Response {
if r.chain.failed() {
return r
}
r.checkEqual("status", statusCodeText(status), statusCodeText(r.resp.StatusCode))
return r
}
// StatusRange succeeds if response status belongs to given range.
//
// Supported ranges:
// - Status1xx - Informational
// - Status2xx - Success
// - Status3xx - Redirection
// - Status4xx - Client Error
// - Status5xx - Server Error
//
// See https://en.wikipedia.org/wiki/List_of_HTTP_status_codes.
//
// Example:
// resp := NewResponse(t, response)
// resp.StatusRange(Status2xx)
func (r *Response) StatusRange(rn StatusRange) *Response {
if r.chain.failed() {
return r
}
status := statusCodeText(r.resp.StatusCode)
actual := statusRangeText(r.resp.StatusCode)
expected := statusRangeText(int(rn))
if actual == "" || actual != expected {
if actual == "" {
r.chain.fail("\nexpected status from range:\n %q\n\nbut got:\n %q",
expected, status)
} else {
r.chain.fail(
"\nexpected status from range:\n %q\n\nbut got:\n %q (%q)",
expected, actual, status)
}
}
return r
}
func statusCodeText(code int) string {
if s := http.StatusText(code); s != "" {
return strconv.Itoa(code) + " " + s
}
return strconv.Itoa(code)
}
func statusRangeText(code int) string {
switch {
case code >= 100 && code < 200:
return "1xx Informational"
case code >= 200 && code < 300:
return "2xx Success"
case code >= 300 && code < 400:
return "3xx Redirection"
case code >= 400 && code < 500:
return "4xx Client Error"
case code >= 500 && code < 600:
return "5xx Server Error"
default:
return ""
}
}
// Headers returns a new Object that may be used to inspect header map.
//
// Example:
// resp := NewResponse(t, response)
// resp.Headers().Value("Content-Type").String().Equal("application-json")
func (r *Response) Headers() *Object {
var value map[string]interface{}
if !r.chain.failed() {
value, _ = canonMap(&r.chain, r.resp.Header)
}
return &Object{r.chain, value}
}
// Header returns a new String object that may be used to inspect given header.
//
// Example:
// resp := NewResponse(t, response)
// resp.Header("Content-Type").Equal("application-json")
// resp.Header("Date").DateTime().Le(time.Now())
func (r *Response) Header(header string) *String {
value := ""
if !r.chain.failed() {
value = r.resp.Header.Get(header)
}
return &String{r.chain, value}
}
// Cookies returns a new Array object with all cookie names set by this response.
// Returned Array contains a String value for every cookie name.
//
// Note that this returns only cookies set by Set-Cookie headers of this response.
// It doesn't return session cookies from previous responses, which may be stored
// in a cookie jar.
//
// Example:
// resp := NewResponse(t, response)
// resp.Cookies().Contains("session")
func (r *Response) Cookies() *Array {
if r.chain.failed() {
return &Array{r.chain, nil}
}
names := []interface{}{}
for _, c := range r.cookies {
names = append(names, c.Name)
}
return &Array{r.chain, names}
}
// Cookie returns a new Cookie object that may be used to inspect given cookie
// set by this response.
//
// Note that this returns only cookies set by Set-Cookie headers of this response.
// It doesn't return session cookies from previous responses, which may be stored
// in a cookie jar.
//
// Example:
// resp := NewResponse(t, response)
// resp.Cookie("session").Domain().Equal("example.com")
func (r *Response) Cookie(name string) *Cookie {
if r.chain.failed() {
return &Cookie{r.chain, nil}
}
names := []string{}
for _, c := range r.cookies {
if c.Name == name {
return &Cookie{r.chain, c}
}
names = append(names, c.Name)
}
r.chain.fail("\nexpected response with cookie:\n %q\n\nbut got only cookies:\n%s",
name, dumpValue(names))
return &Cookie{r.chain, nil}
}
// Websocket returns Websocket object that can be used to interact with
// WebSocket server.
//
// May be called only if the WithWebsocketUpgrade was called on the request.
// That is responsibility of the caller to explicitly close the websocket after use.
//
// Example:
// req := NewRequest(config, "GET", "/path")
// req.WithWebsocketUpgrade()
// ws := req.Expect().Websocket()
// defer ws.Disconnect()
func (r *Response) Websocket() *Websocket {
if !r.chain.failed() && r.websocket == nil {
r.chain.fail("\nunexpected Websocket call for non-WebSocket response")
}
return makeWebsocket(r.config, r.chain, r.websocket)
}
// Body returns a new String object that may be used to inspect response body.
//
// Example:
// resp := NewResponse(t, response)
// resp.Body().NotEmpty()
// resp.Body().Length().Equal(100)
func (r *Response) Body() *String {
return &String{r.chain, string(r.content)}
}
// NoContent succeeds if response contains empty Content-Type header and
// empty body.
func (r *Response) NoContent() *Response {
if r.chain.failed() {
return r
}
contentType := r.resp.Header.Get("Content-Type")
r.checkEqual("\"Content-Type\" header", "", contentType)
r.checkEqual("body", "", string(r.content))
return r
}
// ContentType succeeds if response contains Content-Type header with given
// media type and charset.
//
// If charset is omitted, and mediaType is non-empty, Content-Type header
// should contain empty or utf-8 charset.
//
// If charset is omitted, and mediaType is also empty, Content-Type header
// should contain no charset.
func (r *Response) ContentType(mediaType string, charset ...string) *Response {
r.checkContentType(mediaType, charset...)
return r
}
// ContentEncoding succeeds if response has exactly given Content-Encoding list.
// Common values are empty, "gzip", "compress", "deflate", "identity" and "br".
func (r *Response) ContentEncoding(encoding ...string) *Response {
if r.chain.failed() {
return r
}
r.checkEqual("\"Content-Encoding\" header", encoding, r.resp.Header["Content-Encoding"])
return r
}
// TransferEncoding succeeds if response contains given Transfer-Encoding list.
// Common values are empty, "chunked" and "identity".
func (r *Response) TransferEncoding(encoding ...string) *Response {
if r.chain.failed() {
return r
}
r.checkEqual("\"Transfer-Encoding\" header", encoding, r.resp.TransferEncoding)
return r
}
// ContentOpts define parameters for matching the response content parameters.
type ContentOpts struct {
// The media type Content-Type part, e.g. "application/json"
MediaType string
// The character set Content-Type part, e.g. "utf-8"
Charset string
}
// Text returns a new String object that may be used to inspect response body.
//
// Text succeeds if response contains "text/plain" Content-Type header
// with empty or "utf-8" charset.
//
// Example:
// resp := NewResponse(t, response)
// resp.Text().Equal("hello, world!")
// resp.Text(ContentOpts{
// MediaType: "text/plain",
// }).Equal("hello, world!")
func (r *Response) Text(opts ...ContentOpts) *String {
var content string
if !r.chain.failed() && r.checkContentOpts(opts, "text/plain") {
content = string(r.content)
}
return &String{r.chain, content}
}
// Form returns a new Object that may be used to inspect form contents
// of response.
//
// Form succeeds if response contains "application/x-www-form-urlencoded"
// Content-Type header and if form may be decoded from response body.
// Decoding is performed using https://github.com/ajg/form.
//
// Example:
// resp := NewResponse(t, response)
// resp.Form().Value("foo").Equal("bar")
// resp.Form(ContentOpts{
// MediaType: "application/x-www-form-urlencoded",
// }).Value("foo").Equal("bar")
func (r *Response) Form(opts ...ContentOpts) *Object {
object := r.getForm(opts...)
return &Object{r.chain, object}
}
func (r *Response) getForm(opts ...ContentOpts) map[string]interface{} {
if r.chain.failed() {
return nil
}
if !r.checkContentOpts(opts, "application/x-www-form-urlencoded", "") {
return nil
}
decoder := form.NewDecoder(bytes.NewReader(r.content))
var object map[string]interface{}
if err := decoder.Decode(&object); err != nil {
r.chain.fail(err.Error())
return nil
}
return object
}
// JSON returns a new Value object that may be used to inspect JSON contents
// of response.
//
// JSON succeeds if response contains "application/json" Content-Type header
// with empty or "utf-8" charset and if JSON may be decoded from response body.
//
// Example:
// resp := NewResponse(t, response)
// resp.JSON().Array().Elements("foo", "bar")
// resp.JSON(ContentOpts{
// MediaType: "application/json",
// }).Array.Elements("foo", "bar")
func (r *Response) JSON(opts ...ContentOpts) *Value {
value := r.getJSON(opts...)
return &Value{r.chain, value}
}
func (r *Response) getJSON(opts ...ContentOpts) interface{} {
if r.chain.failed() {
return nil
}
if !r.checkContentOpts(opts, "application/json") {
return nil
}
var value interface{}
if err := json.Unmarshal(r.content, &value); err != nil {
r.chain.fail(err.Error())
return nil
}
return value
}
// JSONP returns a new Value object that may be used to inspect JSONP contents
// of response.
//
// JSONP succeeds if response contains "application/javascript" Content-Type
// header with empty or "utf-8" charset and response body of the following form:
// callback(<valid json>);
// or:
// callback(<valid json>)
//
// Whitespaces are allowed.
//
// Example:
// resp := NewResponse(t, response)
// resp.JSONP("myCallback").Array().Elements("foo", "bar")
// resp.JSONP("myCallback", ContentOpts{
// MediaType: "application/javascript",
// }).Array.Elements("foo", "bar")
func (r *Response) JSONP(callback string, opts ...ContentOpts) *Value {
value := r.getJSONP(callback, opts...)
return &Value{r.chain, value}
}
var (
jsonp = regexp.MustCompile(`^\s*([^\s(]+)\s*\((.*)\)\s*;*\s*$`)
)
func (r *Response) getJSONP(callback string, opts ...ContentOpts) interface{} {
if r.chain.failed() {
return nil
}
if !r.checkContentOpts(opts, "application/javascript") {
return nil
}
m := jsonp.FindSubmatch(r.content)
if len(m) != 3 || string(m[1]) != callback {
r.chain.fail(
"\nexpected JSONP body in form of:\n \"%s(<valid json>)\"\n\nbut got:\n %q\n",
callback,
string(r.content))
return nil
}
var value interface{}
if err := json.Unmarshal(m[2], &value); err != nil {
r.chain.fail(err.Error())
return nil
}
return value
}
func (r *Response) checkContentOpts(
opts []ContentOpts, expectedType string, expectedCharset ...string,
) bool {
if len(opts) != 0 {
if opts[0].MediaType != "" {
expectedType = opts[0].MediaType
}
if opts[0].Charset != "" {
expectedCharset = []string{opts[0].Charset}
}
}
return r.checkContentType(expectedType, expectedCharset...)
}
func (r *Response) checkContentType(expectedType string, expectedCharset ...string) bool {
if r.chain.failed() {
return false
}
contentType := r.resp.Header.Get("Content-Type")
if expectedType == "" && len(expectedCharset) == 0 {
if contentType == "" {
return true
}
}
mediaType, params, err := mime.ParseMediaType(contentType)
if err != nil {
r.chain.fail("\ngot invalid \"Content-Type\" header %q", contentType)
return false
}
if mediaType != expectedType {
r.chain.fail(
"\nexpected \"Content-Type\" header with %q media type,"+
"\nbut got %q", expectedType, mediaType)
return false
}
charset := params["charset"]
if len(expectedCharset) == 0 {
if charset != "" && !strings.EqualFold(charset, "utf-8") {
r.chain.fail(
"\nexpected \"Content-Type\" header with \"utf-8\" or empty charset,"+
"\nbut got %q", charset)
return false
}
} else {
if !strings.EqualFold(charset, expectedCharset[0]) {
r.chain.fail(
"\nexpected \"Content-Type\" header with %q charset,"+
"\nbut got %q", expectedCharset[0], charset)
return false
}
}
return true
}
func (r *Response) checkEqual(what string, expected, actual interface{}) {
if !reflect.DeepEqual(expected, actual) {
r.chain.fail("\nexpected %s equal to:\n%s\n\nbut got:\n%s", what,
dumpValue(expected), dumpValue(actual))
}
}

320
vendor/gopkg.in/gavv/httpexpect.v2/string.go generated vendored Normal file
View file

@ -0,0 +1,320 @@
package httpexpect
import (
"net/http"
"regexp"
"strings"
"time"
)
// String provides methods to inspect attached string value
// (Go representation of JSON string).
type String struct {
chain chain
value string
}
// NewString returns a new String given a reporter used to report failures
// and value to be inspected.
//
// reporter should not be nil.
//
// Example:
// str := NewString(t, "Hello")
func NewString(reporter Reporter, value string) *String {
return &String{makeChain(reporter), value}
}
// Raw returns underlying value attached to String.
// This is the value originally passed to NewString.
//
// Example:
// str := NewString(t, "Hello")
// assert.Equal(t, "Hello", str.Raw())
func (s *String) Raw() string {
return s.value
}
// Path is similar to Value.Path.
func (s *String) Path(path string) *Value {
return getPath(&s.chain, s.value, path)
}
// Schema is similar to Value.Schema.
func (s *String) Schema(schema interface{}) *String {
checkSchema(&s.chain, s.value, schema)
return s
}
// Length returns a new Number object that may be used to inspect string length.
//
// Example:
// str := NewString(t, "Hello")
// str.Length().Equal(5)
func (s *String) Length() *Number {
return &Number{s.chain, float64(len(s.value))}
}
// DateTime parses date/time from string an returns a new DateTime object.
//
// If layout is given, DateTime() uses time.Parse() with given layout.
// Otherwise, it uses http.ParseTime(). If pasing error occurred,
// DateTime reports failure and returns empty (but non-nil) object.
//
// Example:
// str := NewString(t, "Tue, 15 Nov 1994 08:12:31 GMT")
// str.DateTime().Lt(time.Now())
//
// str := NewString(t, "15 Nov 94 08:12 GMT")
// str.DateTime(time.RFC822).Lt(time.Now())
func (s *String) DateTime(layout ...string) *DateTime {
if s.chain.failed() {
return &DateTime{s.chain, time.Unix(0, 0)}
}
var (
t time.Time
err error
)
if len(layout) != 0 {
t, err = time.Parse(layout[0], s.value)
} else {
t, err = http.ParseTime(s.value)
}
if err != nil {
s.chain.fail(err.Error())
return &DateTime{s.chain, time.Unix(0, 0)}
}
return &DateTime{s.chain, t}
}
// Empty succeeds if string is empty.
//
// Example:
// str := NewString(t, "")
// str.Empty()
func (s *String) Empty() *String {
return s.Equal("")
}
// NotEmpty succeeds if string is non-empty.
//
// Example:
// str := NewString(t, "Hello")
// str.NotEmpty()
func (s *String) NotEmpty() *String {
return s.NotEqual("")
}
// Equal succeeds if string is equal to given Go string.
//
// Example:
// str := NewString(t, "Hello")
// str.Equal("Hello")
func (s *String) Equal(value string) *String {
if !(s.value == value) {
s.chain.fail("\nexpected string equal to:\n %q\n\nbut got:\n %q",
value, s.value)
}
return s
}
// NotEqual succeeds if string is not equal to given Go string.
//
// Example:
// str := NewString(t, "Hello")
// str.NotEqual("Goodbye")
func (s *String) NotEqual(value string) *String {
if !(s.value != value) {
s.chain.fail("\nexpected string not equal to:\n %q", value)
}
return s
}
// EqualFold succeeds if string is equal to given Go string after applying Unicode
// case-folding (so it's a case-insensitive match).
//
// Example:
// str := NewString(t, "Hello")
// str.EqualFold("hELLo")
func (s *String) EqualFold(value string) *String {
if !strings.EqualFold(s.value, value) {
s.chain.fail(
"\nexpected string equal to (case-insensitive):\n %q\n\nbut got:\n %q",
value, s.value)
}
return s
}
// NotEqualFold succeeds if string is not equal to given Go string after applying
// Unicode case-folding (so it's a case-insensitive match).
//
// Example:
// str := NewString(t, "Hello")
// str.NotEqualFold("gOODBYe")
func (s *String) NotEqualFold(value string) *String {
if strings.EqualFold(s.value, value) {
s.chain.fail(
"\nexpected string not equal to (case-insensitive):\n %q\n\nbut got:\n %q",
value, s.value)
}
return s
}
// Contains succeeds if string contains given Go string as a substring.
//
// Example:
// str := NewString(t, "Hello")
// str.Contains("ell")
func (s *String) Contains(value string) *String {
if !strings.Contains(s.value, value) {
s.chain.fail(
"\nexpected string containing substring:\n %q\n\nbut got:\n %q",
value, s.value)
}
return s
}
// NotContains succeeds if string doesn't contain Go string as a substring.
//
// Example:
// str := NewString(t, "Hello")
// str.NotContains("bye")
func (s *String) NotContains(value string) *String {
if strings.Contains(s.value, value) {
s.chain.fail(
"\nexpected string not containing substring:\n %q\n\nbut got:\n %q",
value, s.value)
}
return s
}
// ContainsFold succeeds if string contains given Go string as a substring after
// applying Unicode case-folding (so it's a case-insensitive match).
//
// Example:
// str := NewString(t, "Hello")
// str.ContainsFold("ELL")
func (s *String) ContainsFold(value string) *String {
if !strings.Contains(strings.ToLower(s.value), strings.ToLower(value)) {
s.chain.fail(
"\nexpected string containing substring (case-insensitive):\n %q"+
"\n\nbut got:\n %q", value, s.value)
}
return s
}
// NotContainsFold succeeds if string doesn't contain given Go string as a substring
// after applying Unicode case-folding (so it's a case-insensitive match).
//
// Example:
// str := NewString(t, "Hello")
// str.NotContainsFold("BYE")
func (s *String) NotContainsFold(value string) *String {
if strings.Contains(strings.ToLower(s.value), strings.ToLower(value)) {
s.chain.fail(
"\nexpected string not containing substring (case-insensitive):\n %q"+
"\n\nbut got:\n %q", value, s.value)
}
return s
}
// Match matches the string with given regexp and returns a new Match object
// with found submatches.
//
// If regexp is invalid or string doesn't match regexp, Match fails and returns
// empty (but non-nil) object. regexp.Compile is used to construct regexp, and
// Regexp.FindStringSubmatch is used to construct matches.
//
// Example:
// s := NewString(t, "http://example.com/users/john")
// m := s.Match(`http://(?P<host>.+)/users/(?P<user>.+)`)
//
// m.NotEmpty()
// m.Length().Equal(3)
//
// m.Index(0).Equal("http://example.com/users/john")
// m.Index(1).Equal("example.com")
// m.Index(2).Equal("john")
//
// m.Name("host").Equal("example.com")
// m.Name("user").Equal("john")
func (s *String) Match(re string) *Match {
r, err := regexp.Compile(re)
if err != nil {
s.chain.fail(err.Error())
return makeMatch(s.chain, nil, nil)
}
m := r.FindStringSubmatch(s.value)
if m == nil {
s.chain.fail("\nexpected string matching regexp:\n `%s`\n\nbut got:\n %q",
re, s.value)
return makeMatch(s.chain, nil, nil)
}
return makeMatch(s.chain, m, r.SubexpNames())
}
// MatchAll find all matches in string for given regexp and returns a list
// of found matches.
//
// If regexp is invalid or string doesn't match regexp, MatchAll fails and
// returns empty (but non-nil) slice. regexp.Compile is used to construct
// regexp, and Regexp.FindAllStringSubmatch is used to find matches.
//
// Example:
// s := NewString(t,
// "http://example.com/users/john http://example.com/users/bob")
//
// m := s.MatchAll(`http://(?P<host>\S+)/users/(?P<user>\S+)`)
//
// m[0].Name("user").Equal("john")
// m[1].Name("user").Equal("bob")
func (s *String) MatchAll(re string) []Match {
r, err := regexp.Compile(re)
if err != nil {
s.chain.fail(err.Error())
return []Match{}
}
matches := r.FindAllStringSubmatch(s.value, -1)
if matches == nil {
s.chain.fail("\nexpected string matching regexp:\n `%s`\n\nbut got:\n %q",
re, s.value)
return []Match{}
}
ret := []Match{}
for _, m := range matches {
ret = append(ret, *makeMatch(
s.chain,
m,
r.SubexpNames()))
}
return ret
}
// NotMatch succeeds if the string doesn't match to given regexp.
//
// regexp.Compile is used to construct regexp, and Regexp.MatchString
// is used to perform match.
//
// Example:
// s := NewString(t, "a")
// s.NotMatch(`[^a]`)
func (s *String) NotMatch(re string) *String {
r, err := regexp.Compile(re)
if err != nil {
s.chain.fail(err.Error())
return s
}
if r.MatchString(s.value) {
s.chain.fail("\nexpected string not matching regexp:\n `%s`\n\nbut got:\n %q",
re, s.value)
return s
}
return s
}

286
vendor/gopkg.in/gavv/httpexpect.v2/value.go generated vendored Normal file
View file

@ -0,0 +1,286 @@
package httpexpect
import (
"reflect"
)
// Value provides methods to inspect attached interface{} object
// (Go representation of arbitrary JSON value) and cast it to
// concrete type.
type Value struct {
chain chain
value interface{}
}
// NewValue returns a new Value given a reporter used to report failures
// and value to be inspected.
//
// reporter should not be nil, but value may be nil.
//
// Example:
// value := NewValue(t, map[string]interface{}{"foo": 123})
// value.Object()
//
// value := NewValue(t, []interface{}{"foo", 123})
// value.Array()
//
// value := NewValue(t, "foo")
// value.String()
//
// value := NewValue(t, 123)
// value.Number()
//
// value := NewValue(t, true)
// value.Boolean()
//
// value := NewValue(t, nil)
// value.Null()
func NewValue(reporter Reporter, value interface{}) *Value {
chain := makeChain(reporter)
if value != nil {
value, _ = canonValue(&chain, value)
}
return &Value{chain, value}
}
// Raw returns underlying value attached to Value.
// This is the value originally passed to NewValue, converted to canonical form.
//
// Example:
// value := NewValue(t, "foo")
// assert.Equal(t, "foo", number.Raw().(string))
func (v *Value) Raw() interface{} {
return v.value
}
// Path returns a new Value object for child object(s) matching given
// JSONPath expression.
//
// JSONPath is a simple XPath-like query language.
// See http://goessner.net/articles/JsonPath/.
//
// We currently use https://github.com/yalp/jsonpath, which implements
// only a subset of JSONPath, yet useful for simple queries. It doesn't
// support filters and requires double quotes for strings.
//
// Example 1:
// json := `{"users": [{"name": "john"}, {"name": "bob"}]}`
// value := NewValue(t, json)
//
// value.Path("$.users[0].name").String().Equal("john")
// value.Path("$.users[1].name").String().Equal("bob")
//
// Example 2:
// json := `{"yfGH2a": {"user": "john"}, "f7GsDd": {"user": "john"}}`
// value := NewValue(t, json)
//
// for _, user := range value.Path("$..user").Array().Iter() {
// user.String().Equal("john")
// }
func (v *Value) Path(path string) *Value {
return getPath(&v.chain, v.value, path)
}
// Schema succeeds if value matches given JSON Schema.
//
// JSON Schema specifies a JSON-based format to define the structure of
// JSON data. See http://json-schema.org/.
// We use https://github.com/xeipuuv/gojsonschema implementation.
//
// schema should be one of the following:
// - go value that can be json.Marshal-ed to a valid schema
// - type convertible to string containing valid schema
// - type convertible to string containing valid http:// or file:// URI,
// pointing to reachable and valid schema
//
// Example 1:
// schema := `{
// "type": "object",
// "properties": {
// "foo": {
// "type": "string"
// },
// "bar": {
// "type": "integer"
// }
// },
// "require": ["foo", "bar"]
// }`
//
// value := NewValue(t, map[string]interface{}{
// "foo": "a",
// "bar": 1,
// })
//
// value.Schema(schema)
//
// Example 2:
// value := NewValue(t, data)
// value.Schema("http://example.com/schema.json")
func (v *Value) Schema(schema interface{}) *Value {
checkSchema(&v.chain, v.value, schema)
return v
}
// Object returns a new Object attached to underlying value.
//
// If underlying value is not an object (map[string]interface{}), failure is reported
// and empty (but non-nil) value is returned.
//
// Example:
// value := NewValue(t, map[string]interface{}{"foo": 123})
// value.Object().ContainsKey("foo")
func (v *Value) Object() *Object {
data, ok := v.value.(map[string]interface{})
if !ok {
v.chain.fail("\nexpected object value (map or struct), but got:\n%s",
dumpValue(v.value))
}
return &Object{v.chain, data}
}
// Array returns a new Array attached to underlying value.
//
// If underlying value is not an array ([]interface{}), failure is reported and empty
// (but non-nil) value is returned.
//
// Example:
// value := NewValue(t, []interface{}{"foo", 123})
// value.Array().Elements("foo", 123)
func (v *Value) Array() *Array {
data, ok := v.value.([]interface{})
if !ok {
v.chain.fail("\nexpected array value, but got:\n%s",
dumpValue(v.value))
}
return &Array{v.chain, data}
}
// String returns a new String attached to underlying value.
//
// If underlying value is not a string, failure is reported and empty (but non-nil)
// value is returned.
//
// Example:
// value := NewValue(t, "foo")
// value.String().EqualFold("FOO")
func (v *Value) String() *String {
data, ok := v.value.(string)
if !ok {
v.chain.fail("\nexpected string value, but got:\n%s",
dumpValue(v.value))
}
return &String{v.chain, data}
}
// Number returns a new Number attached to underlying value.
//
// If underlying value is not a number (numeric type convertible to float64), failure
// is reported and empty (but non-nil) value is returned.
//
// Example:
// value := NewValue(t, 123)
// value.Number().InRange(100, 200)
func (v *Value) Number() *Number {
data, ok := v.value.(float64)
if !ok {
v.chain.fail("\nexpected numeric value, but got:\n%s",
dumpValue(v.value))
}
return &Number{v.chain, data}
}
// Boolean returns a new Boolean attached to underlying value.
//
// If underlying value is not a bool, failure is reported and empty (but non-nil)
// value is returned.
//
// Example:
// value := NewValue(t, true)
// value.Boolean().True()
func (v *Value) Boolean() *Boolean {
data, ok := v.value.(bool)
if !ok {
v.chain.fail("\nexpected boolean value, but got:\n%s",
dumpValue(v.value))
}
return &Boolean{v.chain, data}
}
// Null succeeds if value is nil.
//
// Note that non-nil interface{} that points to nil value (e.g. nil slice or map)
// is also treated as null value. Empty (non-nil) slice or map, empty string, and
// zero number are not treated as null value.
//
// Example:
// value := NewValue(t, nil)
// value.Null()
//
// value := NewValue(t, []interface{}(nil))
// value.Null()
func (v *Value) Null() *Value {
if v.value != nil {
v.chain.fail("\nexpected nil value, but got:\n%s",
dumpValue(v.value))
}
return v
}
// NotNull succeeds if value is not nil.
//
// Note that non-nil interface{} that points to nil value (e.g. nil slice or map)
// is also treated as null value. Empty (non-nil) slice or map, empty string, and
// zero number are not treated as null value.
//
// Example:
// value := NewValue(t, "")
// value.NotNull()
//
// value := NewValue(t, make([]interface{}, 0)
// value.Null()
func (v *Value) NotNull() *Value {
if v.value == nil {
v.chain.fail("\nexpected non-nil value, but got:\n%s",
dumpValue(v.value))
}
return v
}
// Equal succeeds if value is equal to given Go value (e.g. map, slice, string, etc).
// Before comparison, both values are converted to canonical form.
//
// Example:
// value := NewValue(t, "foo")
// value.Equal("foo")
func (v *Value) Equal(value interface{}) *Value {
expected, ok := canonValue(&v.chain, value)
if !ok {
return v
}
if !reflect.DeepEqual(expected, v.value) {
v.chain.fail("\nexpected value equal to:\n%s\n\nbut got:\n%s\n\ndiff:\n%s",
dumpValue(expected),
dumpValue(v.value),
diffValues(expected, v.value))
}
return v
}
// NotEqual succeeds if value is not equal to given Go value (e.g. map, slice,
// string, etc). Before comparison, both values are converted to canonical form.
//
// Example:
// value := NewValue(t, "foo")
// value.NorEqual("bar")
func (v *Value) NotEqual(value interface{}) *Value {
expected, ok := canonValue(&v.chain, value)
if !ok {
return v
}
if reflect.DeepEqual(expected, v.value) {
v.chain.fail("\nexpected value not equal to:\n%s",
dumpValue(expected))
}
return v
}

424
vendor/gopkg.in/gavv/httpexpect.v2/websocket.go generated vendored Normal file
View file

@ -0,0 +1,424 @@
package httpexpect
import (
"encoding/json"
"time"
"github.com/gorilla/websocket"
)
const noDuration = time.Duration(0)
var infiniteTime = time.Time{}
// Websocket provides methods to read from, write into and close WebSocket
// connection.
type Websocket struct {
config Config
chain chain
conn *websocket.Conn
readTimeout time.Duration
writeTimeout time.Duration
isClosed bool
}
// NewWebsocket returns a new Websocket given a Config with Reporter and
// Printers, and websocket.Conn to be inspected and handled.
func NewWebsocket(config Config, conn *websocket.Conn) *Websocket {
return makeWebsocket(config, makeChain(config.Reporter), conn)
}
func makeWebsocket(config Config, chain chain, conn *websocket.Conn) *Websocket {
return &Websocket{
config: config,
chain: chain,
conn: conn,
}
}
// Raw returns underlying websocket.Conn object.
// This is the value originally passed to NewConnection.
func (c *Websocket) Raw() *websocket.Conn {
return c.conn
}
// WithReadTimeout sets timeout duration for WebSocket connection reads.
//
// By default no timeout is used.
func (c *Websocket) WithReadTimeout(timeout time.Duration) *Websocket {
c.readTimeout = timeout
return c
}
// WithoutReadTimeout removes timeout for WebSocket connection reads.
func (c *Websocket) WithoutReadTimeout() *Websocket {
c.readTimeout = noDuration
return c
}
// WithWriteTimeout sets timeout duration for WebSocket connection writes.
//
// By default no timeout is used.
func (c *Websocket) WithWriteTimeout(timeout time.Duration) *Websocket {
c.writeTimeout = timeout
return c
}
// WithoutWriteTimeout removes timeout for WebSocket connection writes.
//
// If not used then DefaultWebsocketTimeout will be used.
func (c *Websocket) WithoutWriteTimeout() *Websocket {
c.writeTimeout = noDuration
return c
}
// Subprotocol returns a new String object that may be used to inspect
// negotiated protocol for the connection.
func (c *Websocket) Subprotocol() *String {
s := &String{chain: c.chain}
if c.conn != nil {
s.value = c.conn.Subprotocol()
}
return s
}
// Expect reads next message from WebSocket connection and
// returns a new WebsocketMessage object to inspect received message.
//
// Example:
// msg := conn.Expect()
// msg.JSON().Object().ValueEqual("message", "hi")
func (c *Websocket) Expect() *WebsocketMessage {
switch {
case c.chain.failed():
return makeWebsocketMessage(c.chain)
case c.conn == nil:
c.chain.fail("\nunexpected read from failed WebSocket connection")
return makeWebsocketMessage(c.chain)
case c.isClosed:
c.chain.fail("\nunexpected read from closed WebSocket connection")
return makeWebsocketMessage(c.chain)
case !c.setReadDeadline():
return makeWebsocketMessage(c.chain)
}
var err error
m := makeWebsocketMessage(c.chain)
m.typ, m.content, err = c.conn.ReadMessage()
if err != nil {
if cls, ok := err.(*websocket.CloseError); ok {
m.typ = websocket.CloseMessage
m.closeCode = cls.Code
m.content = []byte(cls.Text)
c.printRead(m.typ, m.content, m.closeCode)
} else {
c.chain.fail(
"\nexpected read WebSocket connection, "+
"but got failure: %s", err.Error())
return makeWebsocketMessage(c.chain)
}
} else {
c.printRead(m.typ, m.content, m.closeCode)
}
return m
}
func (c *Websocket) setReadDeadline() bool {
deadline := infiniteTime
if c.readTimeout != noDuration {
deadline = time.Now().Add(c.readTimeout)
}
if err := c.conn.SetReadDeadline(deadline); err != nil {
c.chain.fail(
"\nunexpected failure when setting "+
"read WebSocket connection deadline: %s", err.Error())
return false
}
return true
}
func (c *Websocket) printRead(typ int, content []byte, closeCode int) {
for _, printer := range c.config.Printers {
if p, ok := printer.(WebsocketPrinter); ok {
p.WebsocketRead(typ, content, closeCode)
}
}
}
// Disconnect closes the underlying WebSocket connection without sending or
// waiting for a close message.
//
// It's okay to call this function multiple times.
//
// It's recommended to always call this function after connection usage is over
// to ensure that no resource leaks will happen.
//
// Example:
// conn := resp.Connection()
// defer conn.Disconnect()
func (c *Websocket) Disconnect() *Websocket {
if c.conn == nil || c.isClosed {
return c
}
c.isClosed = true
if err := c.conn.Close(); err != nil {
c.chain.fail("close error when disconnecting webcoket: " + err.Error())
}
return c
}
// Close cleanly closes the underlying WebSocket connection
// by sending an empty close message and then waiting (with timeout)
// for the server to close the connection.
//
// WebSocket close code may be optionally specified.
// If not, then "1000 - Normal Closure" will be used.
//
// WebSocket close codes are defined in RFC 6455, section 11.7.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// It's okay to call this function multiple times.
//
// Example:
// conn := resp.Connection()
// conn.Close(websocket.CloseUnsupportedData)
func (c *Websocket) Close(code ...int) *Websocket {
switch {
case c.checkUnusable("Close"):
return c
case len(code) > 1:
c.chain.fail("\nunexpected multiple code arguments passed to Close")
return c
}
return c.CloseWithBytes(nil, code...)
}
// CloseWithBytes cleanly closes the underlying WebSocket connection
// by sending given slice of bytes as a close message and then waiting
// (with timeout) for the server to close the connection.
//
// WebSocket close code may be optionally specified.
// If not, then "1000 - Normal Closure" will be used.
//
// WebSocket close codes are defined in RFC 6455, section 11.7.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// It's okay to call this function multiple times.
//
// Example:
// conn := resp.Connection()
// conn.CloseWithBytes([]byte("bye!"), websocket.CloseGoingAway)
func (c *Websocket) CloseWithBytes(b []byte, code ...int) *Websocket {
switch {
case c.checkUnusable("CloseWithBytes"):
return c
case len(code) > 1:
c.chain.fail(
"\nunexpected multiple code arguments passed to CloseWithBytes")
return c
}
c.WriteMessage(websocket.CloseMessage, b, code...)
return c
}
// CloseWithJSON cleanly closes the underlying WebSocket connection
// by sending given object (marshaled using json.Marshal()) as a close message
// and then waiting (with timeout) for the server to close the connection.
//
// WebSocket close code may be optionally specified.
// If not, then "1000 - Normal Closure" will be used.
//
// WebSocket close codes are defined in RFC 6455, section 11.7.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// It's okay to call this function multiple times.
//
// Example:
// type MyJSON struct {
// Foo int `json:"foo"`
// }
//
// conn := resp.Connection()
// conn.CloseWithJSON(MyJSON{Foo: 123}, websocket.CloseUnsupportedData)
func (c *Websocket) CloseWithJSON(
object interface{}, code ...int,
) *Websocket {
switch {
case c.checkUnusable("CloseWithJSON"):
return c
case len(code) > 1:
c.chain.fail(
"\nunexpected multiple code arguments passed to CloseWithJSON")
return c
}
b, err := json.Marshal(object)
if err != nil {
c.chain.fail(err.Error())
return c
}
return c.CloseWithBytes(b, code...)
}
// CloseWithText cleanly closes the underlying WebSocket connection
// by sending given text as a close message and then waiting (with timeout)
// for the server to close the connection.
//
// WebSocket close code may be optionally specified.
// If not, then "1000 - Normal Closure" will be used.
//
// WebSocket close codes are defined in RFC 6455, section 11.7.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// It's okay to call this function multiple times.
//
// Example:
// conn := resp.Connection()
// conn.CloseWithText("bye!")
func (c *Websocket) CloseWithText(s string, code ...int) *Websocket {
switch {
case c.checkUnusable("CloseWithText"):
return c
case len(code) > 1:
c.chain.fail(
"\nunexpected multiple code arguments passed to CloseWithText")
return c
}
return c.CloseWithBytes([]byte(s), code...)
}
// WriteMessage writes to the underlying WebSocket connection a message
// of given type with given content.
// Additionally, WebSocket close code may be specified for close messages.
//
// WebSocket message types are defined in RFC 6455, section 11.8.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// WebSocket close codes are defined in RFC 6455, section 11.7.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// Example:
// conn := resp.Connection()
// conn.WriteMessage(websocket.CloseMessage, []byte("Namárië..."))
func (c *Websocket) WriteMessage(
typ int, content []byte, closeCode ...int,
) *Websocket {
if c.checkUnusable("WriteMessage") {
return c
}
switch typ {
case websocket.TextMessage, websocket.BinaryMessage:
c.printWrite(typ, content, 0)
case websocket.CloseMessage:
if len(closeCode) > 1 {
c.chain.fail("\nunexpected multiple closeCode arguments " +
"passed to WriteMessage")
return c
}
code := websocket.CloseNormalClosure
if len(closeCode) > 0 {
code = closeCode[0]
}
c.printWrite(typ, content, code)
content = websocket.FormatCloseMessage(code, string(content))
default:
c.chain.fail("\nunexpected WebSocket message type '%s' "+
"passed to WriteMessage", wsMessageTypeName(typ))
return c
}
if !c.setWriteDeadline() {
return c
}
if err := c.conn.WriteMessage(typ, content); err != nil {
c.chain.fail(
"\nexpected write into WebSocket connection, "+
"but got failure: %s", err.Error())
}
return c
}
// WriteBytesBinary is a shorthand for c.WriteMessage(websocket.BinaryMessage, b).
func (c *Websocket) WriteBytesBinary(b []byte) *Websocket {
if c.checkUnusable("WriteBytesBinary") {
return c
}
return c.WriteMessage(websocket.BinaryMessage, b)
}
// WriteBytesText is a shorthand for c.WriteMessage(websocket.TextMessage, b).
func (c *Websocket) WriteBytesText(b []byte) *Websocket {
if c.checkUnusable("WriteBytesText") {
return c
}
return c.WriteMessage(websocket.TextMessage, b)
}
// WriteText is a shorthand for
// c.WriteMessage(websocket.TextMessage, []byte(s)).
func (c *Websocket) WriteText(s string) *Websocket {
if c.checkUnusable("WriteText") {
return c
}
return c.WriteMessage(websocket.TextMessage, []byte(s))
}
// WriteJSON writes to the underlying WebSocket connection given object,
// marshaled using json.Marshal().
func (c *Websocket) WriteJSON(object interface{}) *Websocket {
if c.checkUnusable("WriteJSON") {
return c
}
b, err := json.Marshal(object)
if err != nil {
c.chain.fail(err.Error())
return c
}
return c.WriteMessage(websocket.TextMessage, b)
}
func (c *Websocket) checkUnusable(where string) bool {
switch {
case c.chain.failed():
return true
case c.conn == nil:
c.chain.fail("\nunexpected %s call for failed WebSocket connection",
where)
return true
case c.isClosed:
c.chain.fail("\nunexpected %s call for closed WebSocket connection",
where)
return true
}
return false
}
func (c *Websocket) setWriteDeadline() bool {
deadline := infiniteTime
if c.writeTimeout != noDuration {
deadline = time.Now().Add(c.writeTimeout)
}
if err := c.conn.SetWriteDeadline(deadline); err != nil {
c.chain.fail(
"\nunexpected failure when setting "+
"write WebSocket connection deadline: %s", err.Error())
return false
}
return true
}
func (c *Websocket) printWrite(typ int, content []byte, closeCode int) {
for _, printer := range c.config.Printers {
if p, ok := printer.(WebsocketPrinter); ok {
p.WebsocketWrite(typ, content, closeCode)
}
}
}

111
vendor/gopkg.in/gavv/httpexpect.v2/websocket_dialer.go generated vendored Normal file
View file

@ -0,0 +1,111 @@
package httpexpect
import (
"bufio"
"net"
"net/http"
"net/http/httptest"
"sync"
"github.com/gorilla/websocket"
"github.com/valyala/fasthttp"
)
// NewWebsocketDialer produces new websocket.Dialer which dials to bound
// http.Handler without creating a real net.Conn.
func NewWebsocketDialer(handler http.Handler) *websocket.Dialer {
return &websocket.Dialer{
NetDial: func(network, addr string) (net.Conn, error) {
hc := newHandlerConn()
hc.runHandler(handler)
return hc, nil
},
}
}
// NewFastWebsocketDialer produces new websocket.Dialer which dials to bound
// fasthttp.RequestHandler without creating a real net.Conn.
func NewFastWebsocketDialer(handler fasthttp.RequestHandler) *websocket.Dialer {
return &websocket.Dialer{
NetDial: func(network, addr string) (net.Conn, error) {
hc := newHandlerConn()
hc.runFastHandler(handler)
return hc, nil
},
}
}
type handlerConn struct {
net.Conn // returned from dialer
backConn net.Conn // passed to the background goroutine
wg sync.WaitGroup
}
func newHandlerConn() *handlerConn {
dialConn, backConn := net.Pipe()
return &handlerConn{
Conn: dialConn,
backConn: backConn,
}
}
func (hc *handlerConn) Close() error {
err := hc.Conn.Close()
hc.wg.Wait() // wait the background goroutine
return err
}
func (hc *handlerConn) runHandler(handler http.Handler) {
hc.wg.Add(1)
go func() {
defer hc.wg.Done()
recorder := &hijackRecorder{conn: hc.backConn}
for {
req, err := http.ReadRequest(bufio.NewReader(hc.backConn))
if err != nil {
return
}
handler.ServeHTTP(recorder, req)
}
}()
}
func (hc *handlerConn) runFastHandler(handler fasthttp.RequestHandler) {
hc.wg.Add(1)
go func() {
defer hc.wg.Done()
_ = fasthttp.ServeConn(hc.backConn, handler)
}()
}
// hijackRecorder it similar to httptest.ResponseRecorder,
// but with Hijack capabilities.
//
// Original idea is stolen from https://github.com/posener/wstest
type hijackRecorder struct {
httptest.ResponseRecorder
conn net.Conn
}
// Hijack the connection for caller.
//
// Implements http.Hijacker interface.
func (r *hijackRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) {
rw := bufio.NewReadWriter(bufio.NewReader(r.conn), bufio.NewWriter(r.conn))
return r.conn, rw, nil
}
// WriteHeader write HTTP header to the client and closes the connection
//
// Implements http.ResponseWriter interface.
func (r *hijackRecorder) WriteHeader(code int) {
resp := http.Response{StatusCode: code, Header: r.Header()}
_ = resp.Write(r.conn)
}

314
vendor/gopkg.in/gavv/httpexpect.v2/websocket_message.go generated vendored Normal file
View file

@ -0,0 +1,314 @@
package httpexpect
import (
"encoding/json"
"github.com/gorilla/websocket"
)
// WebsocketMessage provides methods to inspect message read from WebSocket connection.
type WebsocketMessage struct {
chain chain
typ int
content []byte
closeCode int
}
// NewWebsocketMessage returns a new WebsocketMessage object given a reporter used to
// report failures and the message parameters to be inspected.
//
// reporter should not be nil.
//
// Example:
// m := NewWebsocketMessage(reporter, websocket.TextMessage, []byte("content"), 0)
// m.TextMessage()
func NewWebsocketMessage(
reporter Reporter, typ int, content []byte, closeCode ...int,
) *WebsocketMessage {
m := &WebsocketMessage{
chain: makeChain(reporter),
typ: typ,
content: content,
}
if len(closeCode) != 0 {
m.closeCode = closeCode[0]
}
return m
}
func makeWebsocketMessage(chain chain) *WebsocketMessage {
return &WebsocketMessage{
chain: chain,
}
}
// Raw returns underlying type, content and close code of WebSocket message.
// Theses values are originally read from WebSocket connection.
func (m *WebsocketMessage) Raw() (typ int, content []byte, closeCode int) {
return m.typ, m.content, m.closeCode
}
// CloseMessage is a shorthand for m.Type(websocket.CloseMessage).
func (m *WebsocketMessage) CloseMessage() *WebsocketMessage {
return m.Type(websocket.CloseMessage)
}
// NotCloseMessage is a shorthand for m.NotType(websocket.CloseMessage).
func (m *WebsocketMessage) NotCloseMessage() *WebsocketMessage {
return m.NotType(websocket.CloseMessage)
}
// BinaryMessage is a shorthand for m.Type(websocket.BinaryMessage).
func (m *WebsocketMessage) BinaryMessage() *WebsocketMessage {
return m.Type(websocket.BinaryMessage)
}
// NotBinaryMessage is a shorthand for m.NotType(websocket.BinaryMessage).
func (m *WebsocketMessage) NotBinaryMessage() *WebsocketMessage {
return m.NotType(websocket.BinaryMessage)
}
// TextMessage is a shorthand for m.Type(websocket.TextMessage).
func (m *WebsocketMessage) TextMessage() *WebsocketMessage {
return m.Type(websocket.TextMessage)
}
// NotTextMessage is a shorthand for m.NotType(websocket.TextMessage).
func (m *WebsocketMessage) NotTextMessage() *WebsocketMessage {
return m.NotType(websocket.TextMessage)
}
// Type succeeds if WebSocket message type is one of the given.
//
// WebSocket message types are defined in RFC 6455, section 11.8.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// Example:
// msg := conn.Expect()
// msg.Type(websocket.TextMessage, websocket.BinaryMessage)
func (m *WebsocketMessage) Type(typ ...int) *WebsocketMessage {
switch {
case m.chain.failed():
return m
case len(typ) == 0:
m.chain.fail("\nunexpected nil argument passed to Type")
return m
}
yes := false
for _, t := range typ {
if t == m.typ {
yes = true
break
}
}
if !yes {
if len(typ) > 1 {
m.chain.fail(
"\nexpected message type equal to one of:\n %v\n\nbut got:\n %d",
typ, m.typ)
} else {
m.chain.fail(
"\nexpected message type:\n %d\n\nbut got:\n %d",
typ[0], m.typ)
}
}
return m
}
// NotType succeeds if WebSocket message type is none of the given.
//
// WebSocket message types are defined in RFC 6455, section 11.8.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// Example:
// msg := conn.Expect()
// msg.NotType(websocket.CloseMessage, websocket.BinaryMessage)
func (m *WebsocketMessage) NotType(typ ...int) *WebsocketMessage {
switch {
case m.chain.failed():
return m
case len(typ) == 0:
m.chain.fail("\nunexpected nil argument passed to NotType")
return m
}
for _, t := range typ {
if t == m.typ {
if len(typ) > 1 {
m.chain.fail(
"\nexpected message type not equal:\n %v\n\nbut got:\n %d",
typ, m.typ)
} else {
m.chain.fail(
"\nexpected message type not equal:\n %d\n\nbut it did",
typ[0], m.typ)
}
return m
}
}
return m
}
// Code succeeds if WebSocket close code is one of the given.
//
// Code fails if WebSocket message type is not "8 - Connection Close Frame".
//
// WebSocket close codes are defined in RFC 6455, section 11.7.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// Example:
// msg := conn.Expect().Closed()
// msg.Code(websocket.CloseNormalClosure, websocket.CloseGoingAway)
func (m *WebsocketMessage) Code(code ...int) *WebsocketMessage {
switch {
case m.chain.failed():
return m
case len(code) == 0:
m.chain.fail("\nunexpected nil argument passed to Code")
return m
case m.checkClosed("Code"):
return m
}
yes := false
for _, c := range code {
if c == m.closeCode {
yes = true
break
}
}
if !yes {
if len(code) > 1 {
m.chain.fail(
"\nexpected close code equal to one of:\n %v\n\nbut got:\n %d",
code, m.closeCode)
} else {
m.chain.fail(
"\nexpected close code:\n %d\n\nbut got:\n %d",
code[0], m.closeCode)
}
}
return m
}
// NotCode succeeds if WebSocket close code is none of the given.
//
// NotCode fails if WebSocket message type is not "8 - Connection Close Frame".
//
// WebSocket close codes are defined in RFC 6455, section 11.7.
// See also https://godoc.org/github.com/gorilla/websocket#pkg-constants
//
// Example:
// msg := conn.Expect().Closed()
// msg.NotCode(websocket.CloseAbnormalClosure, websocket.CloseNoStatusReceived)
func (m *WebsocketMessage) NotCode(code ...int) *WebsocketMessage {
switch {
case m.chain.failed():
return m
case len(code) == 0:
m.chain.fail("\nunexpected nil argument passed to CodeNotEqual")
return m
case m.checkClosed("NotCode"):
return m
}
for _, c := range code {
if c == m.closeCode {
if len(code) > 1 {
m.chain.fail(
"\nexpected close code not equal:\n %v\n\nbut got:\n %d",
code, m.closeCode)
} else {
m.chain.fail(
"\nexpected close code not equal:\n %d\n\nbut it did",
code[0], m.closeCode)
}
return m
}
}
return m
}
func (m *WebsocketMessage) checkClosed(where string) bool {
if m.typ != websocket.CloseMessage {
m.chain.fail(
"\nunexpected %s usage for not '%' WebSocket message type\n\n"+
"got type:\n %s",
where,
wsMessageTypeName(websocket.CloseMessage),
wsMessageTypeName(m.typ))
return true
}
return false
}
// Body returns a new String object that may be used to inspect
// WebSocket message content.
//
// Example:
// msg := conn.Expect()
// msg.Body().NotEmpty()
// msg.Body().Length().Equal(100)
func (m *WebsocketMessage) Body() *String {
return &String{m.chain, string(m.content)}
}
// NoContent succeeds if WebSocket message has no content (is empty).
func (m *WebsocketMessage) NoContent() *WebsocketMessage {
switch {
case m.chain.failed():
return m
case len(m.content) == 0:
return m
}
switch m.typ {
case websocket.BinaryMessage:
m.chain.fail(
"\nexpected message body being empty, but got:\n %d bytes",
len(m.content))
default:
m.chain.fail(
"\nexpected message body being empty, but got:\n %s",
string(m.content))
}
return m
}
// JSON returns a new Value object that may be used to inspect JSON contents
// of WebSocket message.
//
// JSON succeeds if JSON may be decoded from message content.
//
// Example:
// msg := conn.Expect()
// msg.JSON().Array().Elements("foo", "bar")
func (m *WebsocketMessage) JSON() *Value {
return &Value{m.chain, m.getJSON()}
}
func (m *WebsocketMessage) getJSON() interface{} {
if m.chain.failed() {
return nil
}
var value interface{}
if err := json.Unmarshal(m.content, &value); err != nil {
m.chain.fail(err.Error())
return nil
}
return value
}
func wsMessageTypeName(typ int) string {
switch typ {
case websocket.TextMessage:
return "text"
case websocket.BinaryMessage:
return "binary"
case websocket.CloseMessage:
return "close"
case websocket.PingMessage:
return "ping"
case websocket.PongMessage:
return "pong"
}
return "unknown"
}