Repository: gavv/httpexpect
Pull request #397 (2023-04-10 03:55:15)

Convert Object tests to table-driven style
#386 

coveralls: 
[![Coverage Status](https://coveralls.io/builds/58704659/badge)](https://coveralls.io/builds/58704659)

Coverage: 95.633% (-0.04%) from 95.672% when pulling **07ec80b4eb646130c0869398a686d6f95a07f03c on jeremyphua:convert-object-test-to-table-driven** into **77cce299a5f7100194c81de3d94b68ef94d25859 on gavv:master**.

jeremyphua: Hi @gavv , PR is ready. Let me know if there are any changes to be done!

Patch:
diff --git a/Makefile b/Makefile
index a14787e..6f31bfa 100644
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,9 @@
 all: tidy gen build lint test spell
 
 tidy:
-	go mod tidy -v
+	go mod tidy -v 
 	cd _examples && go get -v -u github.com/gavv/httpexpect/v2
-	cd _examples && go mod tidy -v
+	cd _examples && go mod tidy -v -compat=1.17
 
 gen:
 	go generate ./...
diff --git a/_examples/go.mod b/_examples/go.mod
index d47a0ba..b9e3bd3 100644
--- a/_examples/go.mod
+++ b/_examples/go.mod
@@ -9,9 +9,9 @@ require (
 	github.com/gin-gonic/gin v1.8.1
 	github.com/go-oauth2/oauth2/v4 v4.5.1
 	github.com/gorilla/websocket v1.5.0
-	github.com/kataras/iris/v12 v12.1.8
+	github.com/kataras/iris/v12 v12.2.0
 	github.com/labstack/echo/v4 v4.10.0
-	github.com/valyala/fasthttp v1.45.0
+	github.com/valyala/fasthttp v1.46.0
 	golang.org/x/oauth2 v0.4.0
 	google.golang.org/appengine v1.6.7
 )
@@ -19,16 +19,17 @@ require (
 require (
 	github.com/BurntSushi/toml v1.2.1 // indirect
 	github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
-	github.com/CloudyKit/jet/v3 v3.0.1 // indirect
+	github.com/CloudyKit/jet/v6 v6.2.0 // indirect
+	github.com/Joker/jade v1.1.3 // indirect
 	github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
 	github.com/ajg/form v1.5.1 // indirect
 	github.com/andybalholm/brotli v1.0.5 // indirect
 	github.com/aymerick/douceur v0.2.0 // indirect
-	github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect
 	github.com/fatih/color v1.15.0 // indirect
 	github.com/fatih/structs v1.1.0 // indirect
+	github.com/flosch/pongo2/v4 v4.0.2 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
 	github.com/go-playground/locales v0.14.0 // indirect
 	github.com/go-playground/universal-translator v0.18.0 // indirect
@@ -37,38 +38,42 @@ require (
 	github.com/goccy/go-json v0.9.11 // indirect
 	github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
+	github.com/golang/snappy v0.0.4 // indirect
 	github.com/google/go-querystring v1.1.0 // indirect
 	github.com/google/uuid v1.3.0 // indirect
 	github.com/gorilla/css v1.0.0 // indirect
 	github.com/imkira/go-interpol v1.1.0 // indirect
-	github.com/iris-contrib/blackfriday v2.0.0+incompatible // indirect
-	github.com/iris-contrib/go.uuid v2.0.0+incompatible // indirect
-	github.com/iris-contrib/jade v1.1.4 // indirect
-	github.com/iris-contrib/pongo2 v0.0.1 // indirect
 	github.com/iris-contrib/schema v0.0.6 // indirect
+	github.com/josharian/intern v1.0.0 // indirect
 	github.com/json-iterator/go v1.1.12 // indirect
+	github.com/kataras/blocks v0.0.7 // indirect
 	github.com/kataras/golog v0.1.8 // indirect
 	github.com/kataras/pio v0.0.11 // indirect
 	github.com/kataras/sitemap v0.0.6 // indirect
-	github.com/klauspost/compress v1.16.4 // indirect
+	github.com/kataras/tunnel v0.0.4 // indirect
+	github.com/klauspost/compress v1.16.5 // indirect
 	github.com/labstack/gommon v0.4.0 // indirect
 	github.com/leodido/go-urn v1.2.1 // indirect
+	github.com/mailgun/raymond/v2 v2.0.48 // indirect
+	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
 	github.com/mattn/go-isatty v0.0.18 // indirect
-	github.com/microcosm-cc/bluemonday v1.0.21 // indirect
+	github.com/microcosm-cc/bluemonday v1.0.23 // indirect
 	github.com/mitchellh/go-wordwrap v1.0.1 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
-	github.com/ryanuber/columnize v2.1.2+incompatible // indirect
+	github.com/russross/blackfriday/v2 v2.1.0 // indirect
 	github.com/sanity-io/litter v1.5.5 // indirect
 	github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect
 	github.com/schollz/closestmatch v2.1.0+incompatible // indirect
 	github.com/sergi/go-diff v1.3.1 // indirect
-	github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
+	github.com/sirupsen/logrus v1.8.1 // indirect
 	github.com/smartystreets/goconvey v1.7.2 // indirect
 	github.com/stretchr/testify v1.8.2 // indirect
+	github.com/tdewolff/minify/v2 v2.12.4 // indirect
+	github.com/tdewolff/parse/v2 v2.6.4 // indirect
 	github.com/tidwall/btree v0.0.0-20191029221954-400434d76274 // indirect
 	github.com/tidwall/buntdb v1.1.2 // indirect
 	github.com/tidwall/gjson v1.12.1 // indirect
@@ -80,18 +85,21 @@ require (
 	github.com/ugorji/go/codec v1.2.7 // indirect
 	github.com/valyala/bytebufferpool v1.0.0 // indirect
 	github.com/valyala/fasttemplate v1.2.2 // indirect
+	github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
+	github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
 	github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
 	github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
 	github.com/xeipuuv/gojsonschema v1.2.0 // indirect
 	github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect
+	github.com/yosssi/ace v0.0.5 // indirect
 	github.com/yudai/gojsondiff v1.0.0 // indirect
 	github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
 	golang.org/x/crypto v0.7.0 // indirect
 	golang.org/x/net v0.9.0 // indirect
 	golang.org/x/sys v0.7.0 // indirect
 	golang.org/x/text v0.9.0 // indirect
-	golang.org/x/time v0.2.0 // indirect
-	google.golang.org/protobuf v1.28.1 // indirect
+	golang.org/x/time v0.3.0 // indirect
+	google.golang.org/protobuf v1.29.1 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/_examples/go.sum b/_examples/go.sum
index ed79fbc..1d37b9a 100644
--- a/_examples/go.sum
+++ b/_examples/go.sum
@@ -1,59 +1,48 @@
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
-github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
 github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 h1:sR+/8Yb4slttB4vD+b9btVEnWgL3Q00OBTzVT8B9C0c=
 github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
-github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
-github.com/CloudyKit/jet/v3 v3.0.1 h1:LUBMIJtW92Fqi+fOqXbGsT/xKiwNWjYktaNAASPE7E4=
-github.com/CloudyKit/jet/v3 v3.0.1/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
+github.com/CloudyKit/jet/v6 v6.2.0 h1:EpcZ6SR9n28BUGtNJSvlBqf90IpjeFr36Tizxhn/oME=
+github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
 github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc=
 github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
-github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0=
+github.com/Joker/jade v1.1.3 h1:Qbeh12Vq6BxURXT1qZBRHsDxeURB8ztcL6f3EXSGeHk=
+github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
 github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 h1:KkH3I3sJuOLP3TjA/dfr4NAY8bghDwnXiU7cTKxQqo0=
 github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM=
 github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
 github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
-github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
 github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
 github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
-github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
 github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
-github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1:Ppm0npCCsmuR9oQaBtRuZcmILVE74aXE+AmrJj8L2ns=
-github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
-github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
-github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
+github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
+github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 h1:clC1lXBpe2kTj2VHdaIu9ajZQe4kcEY9j0NsnDDBZ3o=
 github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
-github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
 github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
-github.com/fasthttp/websocket v1.4.3-rc.6/go.mod h1:43W9OM2T8FeXpCWMsBd9Cb7nE2CACNqNvCqQCoty/Lc=
 github.com/fasthttp/websocket v1.5.0 h1:B4zbe3xXyvIdnqjOZrafVFklCUq5ZLo/TqCt5JA1wLE=
 github.com/fasthttp/websocket v1.5.0/go.mod h1:n0BlOQvJdPbTuBkZT0O5+jk/sp/1/VCzquR1BehI2F4=
-github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
 github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
 github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
 github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
 github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/flosch/pongo2/v4 v4.0.2 h1:gv+5Pe3vaSVmiJvh/BZa82b7/00YUGm0PIyVVLop0Hw=
+github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
 github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU5kORdjhlA1yX8=
 github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
 github.com/gavv/httpexpect/v2 v2.15.0 h1:CCnFk9of4l4ijUhnMxyoEpJsIIBKcuWIFLMwwGTZxNs=
@@ -62,8 +51,6 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
 github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
 github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
 github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
-github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI=
-github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
 github.com/go-oauth2/oauth2/v4 v4.5.1 h1:3vxp+cjLqDe1TbogbwtMyeHRHr1tD+ksrK7xNppYRDs=
 github.com/go-oauth2/oauth2/v4 v4.5.1/go.mod h1:wk/2uLImWIa9VVQDgxz99H2GDbhmfi/9/Xr+GvkSUSQ=
 github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
@@ -72,16 +59,11 @@ github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb
 github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
 github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
 github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
-github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
 github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
 github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
 github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0=
 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
 github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
-github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
-github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
-github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
-github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
 github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
 github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
@@ -98,74 +80,57 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
+github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
 github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
 github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
 github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
-github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
 github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/imkira/go-interpol v1.1.0 h1:KIiKr0VSG2CUW1hl1jpiyuzuJeKUUpC8iM1AIE7N1Vk=
 github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA=
-github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/iris-contrib/blackfriday v2.0.0+incompatible h1:o5sHQHHm0ToHUlAJSTjW9UWicjJSDDauOOQ2AHuIVp4=
-github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
-github.com/iris-contrib/go.uuid v2.0.0+incompatible h1:XZubAYg61/JwnJNbZilGjf3b3pB80+OQg2qf6c8BfWE=
-github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
-github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk=
-github.com/iris-contrib/jade v1.1.4 h1:WoYdfyJFfZIUgqNAeOyRfTNQZOksSlZ6+FnXR3AEpX0=
-github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE=
-github.com/iris-contrib/pongo2 v0.0.1 h1:zGP7pW51oi5eQZMIlGA3I+FHY9/HOQWDB+572yin0to=
-github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g=
-github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw=
+github.com/iris-contrib/httpexpect/v2 v2.12.1 h1:3cTZSyBBen/kfjCtgNFoUKi1u0FVXNaAjyRJOo6AVS4=
 github.com/iris-contrib/schema v0.0.6 h1:CPSBLyx2e91H2yJzPuhGuifVRnZBBJ3pCOMbOvPZaTw=
 github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA=
-github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
-github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8=
+github.com/kataras/blocks v0.0.7 h1:cF3RDY/vxnSRezc7vLFlQFTYXG/yAr1o7WImJuZbzC4=
+github.com/kataras/blocks v0.0.7/go.mod h1:UJIU97CluDo0f+zEjbnbkeMRlvYORtmc1304EeyXf4I=
 github.com/kataras/golog v0.1.8 h1:isP8th4PJH2SrbkciKnylaND9xoTtfxv++NB+DF0l9g=
 github.com/kataras/golog v0.1.8/go.mod h1:rGPAin4hYROfk1qT9wZP6VY2rsb4zzc37QpdPjdkqVw=
-github.com/kataras/iris/v12 v12.1.8 h1:O3gJasjm7ZxpxwTH8tApZsvf274scSGQAUpNe47c37U=
-github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE=
-github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE=
-github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro=
+github.com/kataras/iris/v12 v12.2.0 h1:WzDY5nGuW/LgVaFS5BtTkW3crdSKJ/FEgWnxPnIVVLI=
+github.com/kataras/iris/v12 v12.2.0/go.mod h1:BLzBpEunc41GbE68OUaQlqX4jzi791mx5HU04uPb90Y=
 github.com/kataras/pio v0.0.11 h1:kqreJ5KOEXGMwHAWHDwIl+mjfNCPhAwZPa8gK7MKlyw=
 github.com/kataras/pio v0.0.11/go.mod h1:38hH6SWH6m4DKSYmRhlrCJ5WItwWgCVrTNU62XZyUvI=
-github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8=
 github.com/kataras/sitemap v0.0.6 h1:w71CRMMKYMJh6LR2wTgnk5hSgjVNB9KL60n5e2KHvLY=
 github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4=
-github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
+github.com/kataras/tunnel v0.0.4 h1:sCAqWuJV7nPzGrlb0os3j49lk2JhILT0rID38NHNLpA=
+github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw=
 github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
-github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
-github.com/klauspost/compress v1.16.4 h1:91KN02FnsOYhuunwU4ssRe8lc2JosWmizWa91B5v1PU=
-github.com/klauspost/compress v1.16.4/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
+github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
@@ -180,71 +145,55 @@ github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8
 github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
 github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
 github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
-github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
+github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
 github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
 github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
 github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
 github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
 github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
-github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
-github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
-github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
-github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
-github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/microcosm-cc/bluemonday v1.0.23 h1:SMZe2IGa0NuHvnVNAZ+6B38gsTbi5e4sViiWJyDDqFY=
+github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4=
 github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
 github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
-github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/moul/http2curl v1.0.0 h1:dRMWoAtb+ePxMlLkrCbAqh4TlPHXvoGUSQ323/9Zahs=
 github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ=
-github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
-github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
-github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
-github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
 github.com/onsi/ginkgo v1.13.0 h1:M76yO2HkZASFjXL0HSoZJ1AYEmQxNJmY41Jx1zNUq1Y=
 github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0=
-github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
 github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
-github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
 github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
 github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
 github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
 github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
-github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
-github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/ryanuber/columnize v2.1.2+incompatible h1:C89EOx/XBWwIXl8wm8OPJBd7kPF25UfsK2X7Ph/zCAk=
-github.com/ryanuber/columnize v2.1.2+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
 github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
-github.com/savsgio/gotils v0.0.0-20210617111740-97865ed5a873/go.mod h1:dmPawKuiAeG/aFYVs2i+Dyosoo7FNcm+Pi8iK6ZUrX8=
 github.com/savsgio/gotils v0.0.0-20211223103454-d0aaa54c5899/go.mod h1:oejLrk1Y/5zOF+c/aHtXqn3TFlzzbAgPWg8zBiAHDas=
 github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo=
 github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
@@ -255,29 +204,22 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
 github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
-github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
+github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
 github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
 github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
-github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
-github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
-github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
-github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.5.0/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@@ -286,6 +228,12 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
 github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
 github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
+github.com/tdewolff/minify/v2 v2.12.4 h1:kejsHQMM17n6/gwdw53qsi6lg0TGddZADVyQOz1KMdE=
+github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZTSF1Ojrr3bk=
+github.com/tdewolff/parse/v2 v2.6.4 h1:KCkDvNUMof10e3QExio9OPZJT8SbdKojLBumw8YZycQ=
+github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs=
+github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM=
+github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
 github.com/tidwall/btree v0.0.0-20191029221954-400434d76274 h1:G6Z6HvJuPjG6XfNGi/feOATzeJrfgTNJY+rGrHbA04E=
 github.com/tidwall/btree v0.0.0-20191029221954-400434d76274/go.mod h1:huei1BkDWJ3/sLXmO+bsCNELL+Bp2Kks9OLyQFkzvA8=
 github.com/tidwall/buntdb v1.1.2 h1:noCrqQXL9EKMtcdwJcmuVKSEjqu1ua99RHHgbLTEHRo=
@@ -305,22 +253,23 @@ github.com/tidwall/rtree v0.0.0-20180113144539-6cd427091e0e h1:+NL1GDIUOKxVfbp2K
 github.com/tidwall/rtree v0.0.0-20180113144539-6cd427091e0e/go.mod h1:/h+UnNGt0IhNNJLkGikcdcJqm66zGD/uJGMRxK/9+Ao=
 github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563 h1:Otn9S136ELckZ3KKDyCkxapfufrqDqwmGjcHfAyXRrE=
 github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563/go.mod h1:mLqSmt7Dv/CNneF2wfcChfN1rvapyQr01LGKnKex0DQ=
-github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
 github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
-github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
 github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
 github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasthttp v1.27.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
 github.com/valyala/fasthttp v1.33.0/go.mod h1:KJRK/MXx0J+yd0c5hlR+s1tIHD72sniU8ZJjl97LIw4=
 github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0=
-github.com/valyala/fasthttp v1.45.0 h1:zPkkzpIn8tdHZUrVa6PzYd0i5verqiPSkgTd3bSUcpA=
-github.com/valyala/fasthttp v1.45.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
+github.com/valyala/fasthttp v1.46.0 h1:6ZRhrFg8zBXTRYY6vdzbFhqsBd7FVv123pV2m9V87U4=
+github.com/valyala/fasthttp v1.46.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
 github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
 github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
 github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
 github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
+github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
+github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
+github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
+github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
 github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
 github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
@@ -328,9 +277,10 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo
 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
 github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
-github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
 github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
+github.com/yosssi/ace v0.0.5 h1:tUkIP/BLdKqrlrPwcmH0shwEEhTRHoGnc1wFIWmaBUA=
+github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
 github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
 github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
 github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M=
@@ -338,52 +288,32 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDf
 github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI=
 github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.2.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
 golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
 golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
-golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
-golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
 golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
 golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -392,17 +322,14 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -411,57 +338,36 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
 golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
-golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
-golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
-golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
-golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
 golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
-golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
+golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -479,29 +385,25 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
-google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.29.1 h1:7QBf+IK2gx70Ap/hDsOmam3GE0v9HicjfEdAxE62UoM=
+google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
-gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/_examples/iris.go b/_examples/iris.go
index e2b2602..c2ba801 100644
--- a/_examples/iris.go
+++ b/_examples/iris.go
@@ -75,15 +75,21 @@ func IrisHandler() http.Handler {
 	})
 
 	app.Get("/stream", func(ctx iris.Context) {
-		ctx.StreamWriter(func(w io.Writer) bool {
-			for i := 0; i < 10; i++ {
-				fmt.Fprintf(w, "%d", i)
+		i := 0
+		ctx.StreamWriter(func(w io.Writer) error {
+			if i == 10 {
+				// causes StreamWriter to stop writing
+				return io.EOF
+			} else if _, err := fmt.Fprintf(w, "%d", i); err != nil {
+				return err
 			}
-			// return true to continue, return false to stop and flush
-			return false
+
+			i++
+			// return nil to continue writing
+			return nil
 		})
 		// if we had to write here then the StreamWriter callback should
-		// return true
+		// return nil instead of EOF
 	})
 
 	app.Post("/stream", func(ctx iris.Context) {
diff --git a/websocket_message.go b/websocket_message.go
index 6ed9970..23b27c3 100644
--- a/websocket_message.go
+++ b/websocket_message.go
@@ -63,9 +63,22 @@ func newWebsocketMessage(
 ) *WebsocketMessage {
 	wm := newEmptyWebsocketMessage(parent)
 
+	opChain := wm.chain.enter("")
+	defer opChain.leave()
+
 	wm.typ = typ
 	wm.content = content
 
+	if len(closeCode) > 1 {
+		opChain.fail(AssertionFailure{
+			Type: AssertUsage,
+			Errors: []error{
+				errors.New("unexpected multiple closeCode arguments"),
+			},
+		})
+		return wm
+	}
+
 	if len(closeCode) != 0 {
 		wm.closeCode = closeCode[0]
 	}


Test patch:
diff --git a/array_test.go b/array_test.go
index b26b771..bde4500 100644
--- a/array_test.go
+++ b/array_test.go
@@ -227,6 +227,61 @@ func TestArray_Alias(t *testing.T) {
 	assert.Equal(t, []string{"foo", "Filter()"}, childValue.chain.context.AliasedPath)
 }
 
+func TestArray_Path(t *testing.T) {
+	cases := []struct {
+		name  string
+		value []interface{}
+	}{
+		{
+			name:  "empty",
+			value: []interface{}{},
+		},
+		{
+			name:  "not empty",
+			value: []interface{}{"foo", 123.0},
+		},
+	}
+
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			reporter := newMockReporter(t)
+
+			value := NewArray(reporter, tc.value)
+
+			assert.Equal(t, tc.value, value.Path("$").Raw())
+			value.chain.assert(t, success)
+		})
+	}
+}
+
+func TestArray_Schema(t *testing.T) {
+	cases := []struct {
+		name  string
+		value []interface{}
+	}{
+		{
+			name:  "empty",
+			value: []interface{}{},
+		},
+		{
+			name:  "not empty",
+			value: []interface{}{"foo", 123.0},
+		},
+	}
+
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			reporter := newMockReporter(t)
+
+			NewArray(reporter, tc.value).Schema(`{"type": "array"}`).
+				chain.assert(t, success)
+
+			NewArray(reporter, tc.value).Schema(`{"type": "object"}`).
+				chain.assert(t, failure)
+		})
+	}
+}
+
 func TestArray_Getters(t *testing.T) {
 	t.Run("empty", func(t *testing.T) {
 		reporter := newMockReporter(t)
@@ -239,18 +294,6 @@ func TestArray_Getters(t *testing.T) {
 		value.chain.assert(t, success)
 		value.chain.clear()
 
-		assert.Equal(t, data, value.Path("$").Raw())
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.Schema(`{"type": "array"}`)
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.Schema(`{"type": "object"}`)
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
 		assert.Equal(t, 0.0, value.Length().Raw())
 		value.chain.assert(t, success)
 		value.chain.clear()
@@ -283,18 +326,6 @@ func TestArray_Getters(t *testing.T) {
 		value.chain.assert(t, success)
 		value.chain.clear()
 
-		assert.Equal(t, data, value.Path("$").Raw())
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.Schema(`{"type": "array"}`)
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.Schema(`{"type": "object"}`)
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
 		assert.Equal(t, 2.0, value.Length().Raw())
 		value.chain.assert(t, success)
 		value.chain.clear()
diff --git a/boolean_test.go b/boolean_test.go
index 5b9ce70..96ee663 100644
--- a/boolean_test.go
+++ b/boolean_test.go
@@ -53,6 +53,19 @@ func TestBoolean_Constructors(t *testing.T) {
 	})
 }
 
+func TestBoolean_Raw(t *testing.T) {
+	for _, data := range []bool{true, false} {
+		t.Run(fmt.Sprintf("%v", data), func(t *testing.T) {
+			reporter := newMockReporter(t)
+
+			value := NewBoolean(reporter, data)
+
+			assert.Equal(t, data, value.Raw())
+			value.chain.assert(t, success)
+		})
+	}
+}
+
 func TestBoolean_Decode(t *testing.T) {
 	t.Run("target is empty interface", func(t *testing.T) {
 		reporter := newMockReporter(t)
@@ -111,64 +124,61 @@ func TestBoolean_Alias(t *testing.T) {
 	assert.Equal(t, []string{"foo"}, value.chain.context.AliasedPath)
 }
 
-func TestBoolean_Getters(t *testing.T) {
+func TestBoolean_Path(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewBoolean(reporter, true)
 
-	assert.Equal(t, true, value.Raw())
-	value.chain.assert(t, success)
-	value.chain.clear()
-
 	assert.Equal(t, true, value.Path("$").Raw())
 	value.chain.assert(t, success)
-	value.chain.clear()
+}
 
-	value.Schema(`{"type": "boolean"}`)
-	value.chain.assert(t, success)
-	value.chain.clear()
+func TestBoolean_Schema(t *testing.T) {
+	reporter := newMockReporter(t)
 
-	value.Schema(`{"type": "object"}`)
-	value.chain.assert(t, failure)
-	value.chain.clear()
+	NewBoolean(reporter, true).Schema(`{"type": "boolean"}`).
+		chain.assert(t, success)
+
+	NewBoolean(reporter, true).Schema(`{"type": "object"}`).
+		chain.assert(t, failure)
 }
 
 func TestBoolean_IsEqual(t *testing.T) {
-	for _, value := range []bool{true, false} {
-		t.Run(fmt.Sprintf("%v", value), func(t *testing.T) {
+	for _, data := range []bool{true, false} {
+		t.Run(fmt.Sprintf("%v", data), func(t *testing.T) {
 			reporter := newMockReporter(t)
 
-			NewBoolean(reporter, value).IsEqual(value).
+			NewBoolean(reporter, data).IsEqual(data).
 				chain.assert(t, success)
 
-			NewBoolean(reporter, value).IsEqual(!value).
+			NewBoolean(reporter, data).IsEqual(!data).
 				chain.assert(t, failure)
 
-			NewBoolean(reporter, value).NotEqual(value).
+			NewBoolean(reporter, data).NotEqual(data).
 				chain.assert(t, failure)
 
-			NewBoolean(reporter, value).NotEqual(!value).
+			NewBoolean(reporter, data).NotEqual(!data).
 				chain.assert(t, success)
 		})
 	}
 }
 
 func TestBoolean_IsValue(t *testing.T) {
-	for _, value := range []bool{true, false} {
-		t.Run(fmt.Sprintf("%v", value), func(t *testing.T) {
+	for _, data := range []bool{true, false} {
+		t.Run(fmt.Sprintf("%v", data), func(t *testing.T) {
 			reporter := newMockReporter(t)
 
-			if value {
-				NewBoolean(reporter, value).IsTrue().
+			if data {
+				NewBoolean(reporter, data).IsTrue().
 					chain.assert(t, success)
 
-				NewBoolean(reporter, value).IsFalse().
+				NewBoolean(reporter, data).IsFalse().
 					chain.assert(t, failure)
 			} else {
-				NewBoolean(reporter, value).IsTrue().
+				NewBoolean(reporter, data).IsTrue().
 					chain.assert(t, failure)
 
-				NewBoolean(reporter, value).IsFalse().
+				NewBoolean(reporter, data).IsFalse().
 					chain.assert(t, success)
 			}
 		})
@@ -177,39 +187,39 @@ func TestBoolean_IsValue(t *testing.T) {
 
 func TestBoolean_InList(t *testing.T) {
 	t.Run("basic", func(t *testing.T) {
-		for _, value := range []bool{true, false} {
-			t.Run(fmt.Sprintf("%v", value), func(t *testing.T) {
+		for _, data := range []bool{true, false} {
+			t.Run(fmt.Sprintf("%v", data), func(t *testing.T) {
 				reporter := newMockReporter(t)
 
-				NewBoolean(reporter, value).InList(value).
+				NewBoolean(reporter, data).InList(data).
 					chain.assert(t, success)
 
-				NewBoolean(reporter, value).InList(!value, value).
+				NewBoolean(reporter, data).InList(!data, data).
 					chain.assert(t, success)
 
-				NewBoolean(reporter, value).InList(!value, !value).
+				NewBoolean(reporter, data).InList(!data, !data).
 					chain.assert(t, failure)
 
-				NewBoolean(reporter, value).NotInList(value).
+				NewBoolean(reporter, data).NotInList(data).
 					chain.assert(t, failure)
 
-				NewBoolean(reporter, value).NotInList(!value, value).
+				NewBoolean(reporter, data).NotInList(!data, data).
 					chain.assert(t, failure)
 
-				NewBoolean(reporter, value).NotInList(!value, !value).
+				NewBoolean(reporter, data).NotInList(!data, !data).
 					chain.assert(t, success)
 			})
 		}
 	})
 
 	t.Run("invalid argument", func(t *testing.T) {
-		for _, value := range []bool{true, false} {
+		for _, data := range []bool{true, false} {
 			reporter := newMockReporter(t)
 
-			NewBoolean(reporter, value).InList().
+			NewBoolean(reporter, data).InList().
 				chain.assert(t, failure)
 
-			NewBoolean(reporter, value).NotInList().
+			NewBoolean(reporter, data).NotInList().
 				chain.assert(t, failure)
 		}
 	})
diff --git a/canon_test.go b/canon_test.go
index 749a082..e0a3484 100644
--- a/canon_test.go
+++ b/canon_test.go
@@ -7,176 +7,242 @@ import (
 )
 
 func TestCanon_Number(t *testing.T) {
-	type (
-		myInt int
-	)
-
-	chain := newMockChain(t).enter("test")
-	defer chain.leave()
-
-	var (
-		val float64
-		ok  bool
-	)
-
-	val, ok = canonNumber(chain, 123)
-	assert.True(t, ok)
-	assert.Equal(t, 123.0, val)
-	chain.assert(t, success)
-	chain.clear()
-
-	val, ok = canonNumber(chain, 123.0)
-	assert.True(t, ok)
-	assert.Equal(t, 123.0, val)
-	chain.assert(t, success)
-	chain.clear()
-
-	val, ok = canonNumber(chain, myInt(123))
-	assert.True(t, ok)
-	assert.Equal(t, 123.0, val)
-	chain.assert(t, success)
-	chain.clear()
-
-	_, ok = canonNumber(chain, "123")
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
-
-	_, ok = canonNumber(chain, nil)
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
+	type myInt int
+
+	cases := []struct {
+		name   string
+		in     interface{}
+		out    interface{}
+		result chainResult
+	}{
+		{
+			name:   "input is int",
+			in:     123,
+			out:    123.0,
+			result: success,
+		},
+		{
+			name:   "input is float",
+			in:     123.0,
+			out:    123.0,
+			result: success,
+		},
+		{
+			name:   "input is myInt",
+			in:     myInt(123),
+			out:    123.0,
+			result: success,
+		},
+		{
+			name:   "input is string",
+			in:     "123",
+			result: failure,
+		},
+		{
+			name:   "input is nil",
+			in:     nil,
+			result: failure,
+		},
+	}
+
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			chain := newMockChain(t).enter("test")
+			defer chain.leave()
+
+			val, ok := canonNumber(chain, tc.in)
+			assert.Equal(t, tc.result, chainResult(ok))
+
+			chain.assert(t, tc.result)
+			if tc.result {
+				assert.Equal(t, tc.out, val)
+			}
+		})
+	}
 }
 
-func TestCanon_Array(t *testing.T) {
+func TestCannon_Array(t *testing.T) {
 	type (
-		myArray []interface{}
 		myInt   int
+		myArray []interface{}
 	)
 
-	chain := newMockChain(t).enter("test")
-	defer chain.leave()
-
-	var (
-		val []interface{}
-		ok  bool
-	)
-
-	val, ok = canonArray(chain, []interface{}{123.0, 456.0})
-	assert.True(t, ok)
-	assert.Equal(t, []interface{}{123.0, 456.0}, val)
-	chain.assert(t, success)
-	chain.clear()
-
-	val, ok = canonArray(chain, myArray{myInt(123), 456.0})
-	assert.True(t, ok)
-	assert.Equal(t, []interface{}{123.0, 456.0}, val)
-	chain.assert(t, success)
-	chain.clear()
-
-	_, ok = canonArray(chain, "123")
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
-
-	_, ok = canonArray(chain, func() {})
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
-
-	_, ok = canonArray(chain, nil)
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
-
-	_, ok = canonArray(chain, []interface{}(nil))
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
+	cases := []struct {
+		name   string
+		in     interface{}
+		out    interface{}
+		result chainResult
+	}{
+		{
+			name:   "input is []interface{}",
+			in:     []interface{}{123.0, 456.0},
+			out:    []interface{}{123.0, 456.0},
+			result: success,
+		},
+		{
+			name:   "input is myArray{}",
+			in:     myArray{myInt(123), 456.0},
+			out:    []interface{}{123.0, 456.0},
+			result: success,
+		},
+		{
+			name:   "input is string",
+			in:     "123",
+			result: failure,
+		},
+		{
+			name:   "input is func() {}",
+			in:     func() {},
+			result: failure,
+		},
+		{
+			name:   "input is nil",
+			in:     nil,
+			result: failure,
+		},
+		{
+			name:   "input is []interface{}(nil)",
+			in:     []interface{}(nil),
+			result: failure,
+		},
+	}
+
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			chain := newMockChain(t).enter("test")
+			defer chain.leave()
+
+			val, ok := canonArray(chain, tc.in)
+			assert.Equal(t, tc.result, chainResult(ok))
+
+			chain.assert(t, tc.result)
+			if tc.result {
+				assert.Equal(t, tc.out, val)
+			}
+		})
+	}
 }
 
 func TestCanon_Map(t *testing.T) {
 	type (
-		myMap map[string]interface{}
 		myInt int
+		myMap map[string]interface{}
 	)
 
-	chain := newMockChain(t).enter("test")
-	defer chain.leave()
-
-	var (
-		val map[string]interface{}
-		ok  bool
-	)
-
-	val, ok = canonMap(chain, map[string]interface{}{"foo": 123.0})
-	assert.True(t, ok)
-	assert.Equal(t, map[string]interface{}{"foo": 123.0}, val)
-	chain.assert(t, success)
-	chain.clear()
-
-	val, ok = canonMap(chain, myMap{"foo": myInt(123)})
-	assert.True(t, ok)
-	assert.Equal(t, map[string]interface{}{"foo": 123.0}, val)
-	chain.assert(t, success)
-	chain.clear()
-
-	_, ok = canonMap(chain, "123")
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
-
-	_, ok = canonMap(chain, func() {})
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
-
-	_, ok = canonMap(chain, nil)
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
-
-	_, ok = canonMap(chain, map[string]interface{}(nil))
-	assert.False(t, ok)
-	chain.assert(t, failure)
-	chain.clear()
+	cases := []struct {
+		name   string
+		in     interface{}
+		out    interface{}
+		result chainResult
+	}{
+		{
+			name:   "input is map[string]interface{}{}",
+			in:     map[string]interface{}{"foo": 123.0},
+			out:    map[string]interface{}{"foo": 123.0},
+			result: success,
+		},
+		{
+			name:   "input is myMap{}",
+			in:     myMap{"foo": myInt(123)},
+			out:    map[string]interface{}{"foo": 123.0},
+			result: success,
+		},
+		{
+			name:   "input is string",
+			in:     "123",
+			result: failure,
+		},
+		{
+			name:   "input is func() {}",
+			in:     func() {},
+			result: failure,
+		},
+		{
+			name:   "input is nil",
+			in:     nil,
+			result: failure,
+		},
+		{
+			name:   "input is map[string]interface{}(nil)",
+			in:     map[string]interface{}(nil),
+			result: failure,
+		},
+	}
+
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			chain := newMockChain(t).enter("test")
+			defer chain.leave()
+
+			val, ok := canonMap(chain, tc.in)
+			assert.Equal(t, tc.result, chainResult(ok))
+
+			chain.assert(t, tc.result)
+			if tc.result {
+				assert.Equal(t, tc.out, val)
+			}
+		})
+	}
 }
 
 func TestCannon_Decode(t *testing.T) {
-	t.Run("target is nil", func(t *testing.T) {
-		chain := newMockChain(t).enter("test")
-		defer chain.leave()
-
-		canonDecode(chain, 123, nil)
-
-		chain.assert(t, failure)
-	})
-
-	t.Run("value is not marshallable", func(t *testing.T) {
-		chain := newMockChain(t).enter("test")
-		defer chain.leave()
-
-		type S struct {
-			MyFunc func() string
-		}
-
-		value := &S{
-			MyFunc: func() string { return "foo" },
-		}
-
-		var target S
-		canonDecode(chain, value, &target)
-
-		chain.assert(t, failure)
-	})
-
-	t.Run("value is not unmarshallable into target", func(t *testing.T) {
-		chain := newMockChain(t).enter("test")
-		defer chain.leave()
-
-		var target int
-		canonDecode(chain, true, target)
-
-		chain.assert(t, failure)
-	})
+	cases := []struct {
+		name   string
+		value  interface{}
+		target interface{}
+		result chainResult
+	}{
+		{
+			name:   "string",
+			value:  "foo",
+			target: new(string),
+			result: success,
+		},
+		{
+			name:   "int",
+			value:  123,
+			target: new(int),
+			result: success,
+		},
+		{
+			name:   "any",
+			value:  123,
+			target: new(interface{}),
+			result: success,
+		},
+		{
+			name:   "target is nil",
+			value:  123,
+			target: nil,
+			result: failure,
+		},
+		{
+			name:   "unmarshallable value",
+			value:  func() {},
+			target: new(interface{}),
+			result: failure,
+		},
+		{
+			name:   "incompatible value",
+			value:  "foo",
+			target: new(int),
+			result: failure,
+		},
+		{
+			name:   "target is not a pointer",
+			value:  123,
+			target: 123,
+			result: failure,
+		},
+	}
+
+	for _, tc := range cases {
+		t.Run(tc.name, func(t *testing.T) {
+			chain := newMockChain(t).enter("test")
+			defer chain.leave()
+
+			canonDecode(chain, tc.value, tc.target)
+			chain.assert(t, tc.result)
+		})
+	}
 }
diff --git a/expect_test.go b/expect_test.go
index 860f74c..b7f2fc9 100644
--- a/expect_test.go
+++ b/expect_test.go
@@ -341,6 +341,130 @@ func TestExpect_Branches(t *testing.T) {
 	e5.chain.assertFlags(t, 0)
 }
 
+func TestExpect_Propagation(t *testing.T) {
+	t.Run("subsequent operations", func(t *testing.T) {
+		ctr := 0
+		reporter := newMockReporter(t)
+		reporter.reportCb = func() {
+			ctr++
+		}
+
+		// Failed operation
+		value := NewArray(reporter, []interface{}{"foo"})
+		value.IsEmpty()
+		value.chain.assertFlags(t, flagFailed)
+		assert.Equal(t, 1, ctr)
+
+		// Subsequent failed operation won't report failures
+		value.IsEmpty()
+		value.chain.assertFlags(t, flagFailed)
+		assert.Equal(t, 1, ctr)
+	})
+
+	t.Run("newly created child", func(t *testing.T) {
+		ctr := 0
+		reporter := newMockReporter(t)
+		reporter.reportCb = func() {
+			ctr++
+		}
+
+		// Parent's failed operation reports failure
+		parent := NewArray(reporter, []interface{}{"foo"})
+		parent.IsEmpty()
+		parent.chain.assertFlags(t, flagFailed)
+		assert.Equal(t, 1, ctr)
+
+		// Child created after parent's failure
+		// Child's failed operation won't report failures
+		child := parent.Value(0)
+		child.IsEqual("bar")
+		parent.chain.assertFlags(t, flagFailed|flagFailedChildren)
+		child.chain.assertFlags(t, flagFailed)
+		assert.Equal(t, 1, ctr)
+	})
+
+	t.Run("previously created child", func(t *testing.T) {
+		ctr := 0
+		reporter := newMockReporter(t)
+		reporter.reportCb = func() {
+			ctr++
+		}
+
+		// Parent and child
+		parent := NewArray(reporter, []interface{}{"foo"})
+		child := parent.Value(0)
+
+		// Parent's failed operation reports failure
+		parent.IsEmpty()
+		parent.chain.assertFlags(t, flagFailed)
+		child.chain.assertFlags(t, 0)
+		assert.Equal(t, 1, ctr)
+
+		// Child was created before parent's failure
+		// Child's failed operation will report failures
+		child.IsEqual("bar")
+		parent.chain.assertFlags(t, flagFailed|flagFailedChildren)
+		child.chain.assertFlags(t, flagFailed)
+		assert.Equal(t, 2, ctr)
+	})
+
+	t.Run("newly created child of parent", func(t *testing.T) {
+		ctr := 0
+		reporter := newMockReporter(t)
+		reporter.reportCb = func() {
+			ctr++
+		}
+
+		// Parent
+		parent := NewArray(reporter, []interface{}{"foo"})
+
+		// Child's failed operation will report failures
+		child := parent.Value(0)
+		child.IsEqual("bar")
+		parent.chain.assertFlags(t, flagFailedChildren)
+		child.chain.assertFlags(t, flagFailed)
+		assert.Equal(t, 1, ctr)
+
+		// New child created after failure in another child
+		// New child's failed operation will report failures
+		newChild := parent.Value(0)
+		newChild.IsEqual("bar")
+		parent.chain.assertFlags(t, flagFailedChildren)
+		child.chain.assertFlags(t, flagFailed)
+		newChild.chain.assertFlags(t, flagFailed)
+		assert.Equal(t, 2, ctr)
+	})
+
+	t.Run("previously created child of parent", func(t *testing.T) {
+		ctr := 0
+		reporter := newMockReporter(t)
+		reporter.reportCb = func() {
+			ctr++
+		}
+
+		// Parent
+		parent := NewArray(reporter, []interface{}{"foo"})
+
+		// Children
+		child1 := parent.Value(0)
+		child2 := parent.Value(0)
+
+		// child1's failed operation will report failures
+		child1.IsEqual("bar")
+		parent.chain.assertFlags(t, flagFailedChildren)
+		child1.chain.assertFlags(t, flagFailed)
+		child2.chain.assertFlags(t, 0)
+		assert.Equal(t, 1, ctr)
+
+		// child2's failed operation will report failures
+		child2.IsEqual("bar")
+		parent.chain.assertFlags(t, flagFailedChildren)
+		child1.chain.assertFlags(t, flagFailed)
+		child2.chain.assertFlags(t, flagFailed)
+		assert.Equal(t, 2, ctr)
+	})
+}
+
 func TestExpect_RequestFactory(t *testing.T) {
 	t.Run("default factory", func(t *testing.T) {
 		e := WithConfig(Config{
diff --git a/number_test.go b/number_test.go
index 475ab9c..8778f14 100644
--- a/number_test.go
+++ b/number_test.go
@@ -65,6 +65,15 @@ func TestNumber_Constructors(t *testing.T) {
 	})
 }
 
+func TestNumber_Raw(t *testing.T) {
+	reporter := newMockReporter(t)
+
+	value := NewNumber(reporter, 123.0)
+
+	assert.Equal(t, 123.0, value.Raw())
+	value.chain.assert(t, success)
+}
+
 func TestNumber_Decode(t *testing.T) {
 	t.Run("target is empty interface", func(t *testing.T) {
 		reporter := newMockReporter(t)
@@ -135,26 +144,23 @@ func TestNumber_Alias(t *testing.T) {
 	assert.Equal(t, []string{"foo"}, value.chain.context.AliasedPath)
 }
 
-func TestNumber_Getters(t *testing.T) {
+func TestNumber_Path(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewNumber(reporter, 123.0)
 
-	assert.Equal(t, 123.0, value.Raw())
-	value.chain.assert(t, success)
-	value.chain.clear()
-
 	assert.Equal(t, 123.0, value.Path("$").Raw())
 	value.chain.assert(t, success)
-	value.chain.clear()
+}
 
-	value.Schema(`{"type": "number"}`)
-	value.chain.assert(t, success)
-	value.chain.clear()
+func TestNumber_Schema(t *testing.T) {
+	reporter := newMockReporter(t)
 
-	value.Schema(`{"type": "object"}`)
-	value.chain.assert(t, failure)
-	value.chain.clear()
+	NewNumber(reporter, 123.0).Schema(`{"type": "number"}`).
+		chain.assert(t, success)
+
+	NewNumber(reporter, 123.0).Schema(`{"type": "object"}`).
+		chain.assert(t, failure)
 }
 
 func TestNumber_IsEqual(t *testing.T) {
diff --git a/object_test.go b/object_test.go
index 4680219..c482665 100644
--- a/object_test.go
+++ b/object_test.go
@@ -260,6 +260,37 @@ func TestObject_Alias(t *testing.T) {
 	assert.Equal(t, []string{"bar", "Values()"}, childValue.chain.context.AliasedPath)
 }
 
+func TestObject_Path(t *testing.T) {
+	reporter := newMockReporter(t)
+
+	m := map[string]interface{}{
+		"foo": 123.0,
+		"bar": []interface{}{"456", 789.0},
+		"baz": map[string]interface{}{
+			"a": "b",
+		},
+	}
+
+	value := NewObject(reporter, m)
+
+	assert.Equal(t, m, value.Path("$").Raw())
+	value.chain.assert(t, success)
+}
+
+func TestObject_Schema(t *testing.T) {
+	reporter := newMockReporter(t)
+
+	data := map[string]interface{}{
+		"foo": "bar",
+	}
+
+	NewObject(reporter, data).Schema(`{"type": "object"}`).
+		chain.assert(t, success)
+
+	NewObject(reporter, data).Schema(`{"type": "array"}`).
+		chain.assert(t, failure)
+}
+
 func TestObject_Getters(t *testing.T) {
 	reporter := newMockReporter(t)
 
@@ -287,18 +318,6 @@ func TestObject_Getters(t *testing.T) {
 	value.chain.assert(t, success)
 	value.chain.clear()
 
-	assert.Equal(t, m, value.Path("$").Raw())
-	value.chain.assert(t, success)
-	value.chain.clear()
-
-	value.Schema(`{"type": "object"}`)
-	value.chain.assert(t, success)
-	value.chain.clear()
-
-	value.Schema(`{"type": "array"}`)
-	value.chain.assert(t, failure)
-	value.chain.clear()
-
 	value.Keys().ContainsOnly(keys...)
 	value.chain.assert(t, success)
 	value.chain.clear()
@@ -337,115 +356,92 @@ func TestObject_IsEmpty(t *testing.T) {
 	t.Run("empty map", func(t *testing.T) {
 		reporter := newMockReporter(t)
 
-		value := NewObject(reporter, map[string]interface{}{})
-
-		value.IsEmpty()
-		value.chain.assert(t, success)
-		value.chain.clear()
+		NewObject(reporter, map[string]interface{}{}).IsEmpty().
+			chain.assert(t, success)
 
-		value.NotEmpty()
-		value.chain.assert(t, failure)
-		value.chain.clear()
+		NewObject(reporter, map[string]interface{}{}).NotEmpty().
+			chain.assert(t, failure)
 	})
 
 	t.Run("one empty element", func(t *testing.T) {
 		reporter := newMockReporter(t)
 
-		value := NewObject(reporter, map[string]interface{}{"": nil})
+		NewObject(reporter, map[string]interface{}{"": nil}).IsEmpty().
+			chain.assert(t, failure)
 
-		value.IsEmpty()
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotEmpty()
-		value.chain.assert(t, success)
-		value.chain.clear()
+		NewObject(reporter, map[string]interface{}{"": nil}).NotEmpty().
+			chain.assert(t, success)
 	})
 }
 
 func TestObject_IsEqual(t *testing.T) {
-	t.Run("empty", func(t *testing.T) {
-		reporter := newMockReporter(t)
-
-		value := NewObject(reporter, map[string]interface{}{})
-
-		assert.Equal(t, map[string]interface{}{}, value.Raw())
-
-		value.IsEqual(map[string]interface{}{})
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.NotEqual(map[string]interface{}{})
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.IsEqual(map[string]interface{}{"": nil})
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotEqual(map[string]interface{}{"": nil})
-		value.chain.assert(t, success)
-		value.chain.clear()
-	})
-
-	t.Run("not empty", func(t *testing.T) {
-		reporter := newMockReporter(t)
-
-		value := NewObject(reporter, map[string]interface{}{"foo": 123.0})
-
-		assert.Equal(t, map[string]interface{}{"foo": 123.0}, value.Raw())
-
-		value.IsEqual(map[string]interface{}{})
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotEqual(map[string]interface{}{})
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.IsEqual(map[string]interface{}{"FOO": 123.0})
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotEqual(map[string]interface{}{"FOO": 123.0})
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.IsEqual(map[string]interface{}{"foo": 456.0})
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotEqual(map[string]interface{}{"foo": 456.0})
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.IsEqual(map[string]interface{}{"foo": 123.0})
-		value.chain.assert(t, success)
-		value.chain.clear()
+	t.Run("basic", func(t *testing.T) {
+		cases := []struct {
+			name      string
+			value     map[string]interface{}
+			testValue map[string]interface{}
+			wantEqual chainResult
+		}{
+			{
+				name:      "empty vs one empty",
+				value:     map[string]interface{}{},
+				testValue: map[string]interface{}{},
+				wantEqual: success,
+			},
+			{
+				name:      "empty vs one empty element",
+				value:     map[string]interface{}{},
+				testValue: map[string]interface{}{"": nil},
+				wantEqual: failure,
+			},
+			{
+				name:      "one empty element vs empty",
+				value:     map[string]interface{}{"": nil},
+				testValue: map[string]interface{}{},
+				wantEqual: failure,
+			},
+			{
+				name:      "non-empty vs empty",
+				value:     map[string]interface{}{"foo": 123.0},
+				testValue: map[string]interface{}{},
+				wantEqual: failure,
+			},
+			{
+				name:      "different key",
+				value:     map[string]interface{}{"foo": 123.0},
+				testValue: map[string]interface{}{"FOO": 123.0},
+				wantEqual: failure,
+			},
+			{
+				name:      "different value",
+				value:     map[string]interface{}{"foo": 123.0},
+				testValue: map[string]interface{}{"foo": 456.0},
+				wantEqual: failure,
+			},
+			{
+				name:      "equal",
+				value:     map[string]interface{}{"foo": 123.0},
+				testValue: map[string]interface{}{"foo": 123.0},
+				wantEqual: success,
+			},
+		}
 
-		value.NotEqual(map[string]interface{}{"foo": 123.0})
-		value.chain.assert(t, failure)
-		value.chain.clear()
+		for _, tc := range cases {
+			t.Run(tc.name, func(t *testing.T) {
+				reporter := newMockReporter(t)
 
-		value.IsEqual(nil)
-		value.chain.assert(t, failure)
-		value.chain.clear()
+				NewObject(reporter, tc.value).IsEqual(tc.testValue).
+					chain.assert(t, tc.wantEqual)
 
-		value.NotEqual(nil)
-		value.chain.assert(t, failure)
-		value.chain.clear()
+				NewObject(reporter, tc.value).NotEqual(tc.testValue).
+					chain.assert(t, !tc.wantEqual)
+			})
+		}
 	})
 
 	t.Run("struct", func(t *testing.T) {
 		reporter := newMockReporter(t)
 
-		value := NewObject(reporter, map[string]interface{}{
-			"foo": 123,
-			"bar": map[string]interface{}{
-				"baz": []interface{}{true, false},
-			},
-		})
-
 		type (
 			Bar struct {
 				Baz []bool `json:"baz"`
@@ -457,6 +453,13 @@ func TestObject_IsEqual(t *testing.T) {
 			}
 		)
 
+		value := map[string]interface{}{
+			"foo": 123,
+			"bar": map[string]interface{}{
+				"baz": []interface{}{true, false},
+			},
+		}
+
 		s := S{
 			Foo: 123,
 			Bar: Bar{
@@ -464,176 +467,105 @@ func TestObject_IsEqual(t *testing.T) {
 			},
 		}
 
-		value.IsEqual(s)
-		value.chain.assert(t, success)
-		value.chain.clear()
+		NewObject(reporter, value).IsEqual(s).
+			chain.assert(t, success)
 
-		value.NotEqual(s)
-		value.chain.assert(t, failure)
-		value.chain.clear()
+		NewObject(reporter, value).NotEqual(s).
+			chain.assert(t, failure)
 
-		value.IsEqual(S{})
-		value.chain.assert(t, failure)
-		value.chain.clear()
+		NewObject(reporter, value).IsEqual(S{}).
+			chain.assert(t, failure)
 
-		value.NotEqual(S{})
-		value.chain.assert(t, success)
-		value.chain.clear()
+		NewObject(reporter, value).NotEqual(S{}).
+			chain.assert(t, success)
 	})
 
 	t.Run("canonization", func(t *testing.T) {
+		reporter := newMockReporter(t)
+
 		type (
 			myMap map[string]interface{}
 			myInt int
 		)
 
-		reporter := newMockReporter(t)
-
-		value := NewObject(reporter, map[string]interface{}{"foo": 123})
-
-		value.IsEqual(map[string]interface{}{"foo": 123.0})
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.NotEqual(map[string]interface{}{"foo": 123.0})
-		value.chain.assert(t, failure)
-		value.chain.clear()
+		data := map[string]interface{}{"foo": 123}
 
-		value.IsEqual(myMap{"foo": myInt(123)})
-		value.chain.assert(t, success)
-		value.chain.clear()
+		NewObject(reporter, data).IsEqual(myMap{"foo": myInt(123)}).
+			chain.assert(t, success)
 
-		value.NotEqual(myMap{"foo": myInt(123)})
-		value.chain.assert(t, failure)
-		value.chain.clear()
+		NewObject(reporter, data).NotEqual(myMap{"foo": myInt(123)}).
+			chain.assert(t, failure)
 	})
 }
 
 func TestObject_InList(t *testing.T) {
 	t.Run("basic", func(t *testing.T) {
-		reporter := newMockReporter(t)
-
-		value := NewObject(reporter, map[string]interface{}{"foo": 123.0})
-
-		value.InList(
-			map[string]interface{}{"FOO": 123.0},
-			map[string]interface{}{"BAR": 456.0},
-		)
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotInList(
-			map[string]interface{}{"FOO": 123.0},
-			map[string]interface{}{"BAR": 456.0},
-		)
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.InList(
-			map[string]interface{}{"foo": 456.0},
-			map[string]interface{}{"bar": 123.0},
-		)
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotInList(
-			map[string]interface{}{"foo": 456.0},
-			map[string]interface{}{"bar": 123.0},
-		)
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.InList(
-			map[string]interface{}{"foo": 123.0},
-			map[string]interface{}{"bar": 456.0},
-		)
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.NotInList(
-			map[string]interface{}{"foo": 123.0},
-			map[string]interface{}{"bar": 456.0},
-		)
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.InList(struct {
-			Foo float64 `json:"foo"`
-		}{Foo: 123.00})
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.NotInList(struct {
-			Foo float64 `json:"foo"`
-		}{Foo: 123.00})
-		value.chain.assert(t, failure)
-		value.chain.clear()
-	})
-
-	t.Run("empty", func(t *testing.T) {
-		reporter := newMockReporter(t)
-
-		value := NewObject(reporter, map[string]interface{}{})
-
-		value.InList(map[string]interface{}{})
-		value.chain.assert(t, success)
-		value.chain.clear()
-
-		value.NotInList(map[string]interface{}{})
-		value.chain.assert(t, failure)
-		value.chain.clear()
-	})
-
-	t.Run("not object", func(t *testing.T) {
-		reporter := newMockReporter(t)
-
-		value := NewObject(reporter, map[string]interface{}{"foo": 123.0})
-
-		value.InList(map[string]interface{}{"bar": 123.0}, "NOT OBJECT")
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotInList(map[string]interface{}{"bar": 123.0}, "NOT OBJECT")
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.InList(map[string]interface{}{"foo": 123.0}, "NOT OBJECT")
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotInList(map[string]interface{}{"foo": 123.0}, "NOT OBJECT")
-		value.chain.assert(t, failure)
-		value.chain.clear()
-	})
-
-	t.Run("invalid argument", func(t *testing.T) {
-		reporter := newMockReporter(t)
-
-		value := NewObject(reporter, map[string]interface{}{})
-
-		value.InList()
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.NotInList()
-		value.chain.assert(t, failure)
-		value.chain.clear()
-
-		value.InList(nil)
-		value.chain.assert(t, failure)
-		value.chain.clear()
+		cases := []struct {
+			name      string
+			value     map[string]interface{}
+			testList  []interface{}
+			wantEqual chainResult
+		}{
+			{
+				name:  "empty vs empty",
+				value: map[string]interface{}{},
+				testList: []interface{}{
+					map[string]interface{}{},
+				},
+				wantEqual: success,
+			},
+			{
+				name:  "different key",
+				value: map[string]interface{}{"foo": 123.0},
+				testList: []interface{}{
+					map[string]interface{}{"FOO": 123.0},
+					map[string]interface{}{"BAR": 456.0},
+				},
+				wantEqual: failure,
+			},
+			{
+				name:  "different key or value",
+				value: map[string]interface{}{"foo": 123.0},
+				testList: []interface{}{
+					map[string]interface{}{"foo": 456.0},
+					map[string]interface{}{"bar": 123.0},
+				},
+				wantEqual: failure,
+			},
+			{
+				name:  "success",
+				value: map[string]interface{}{"foo": 123.0},
+				testList: []interface{}{
+					map[string]interface{}{"foo": 123.0},
+					map[string]interface{}{"bar": 456.0},
+				},
+				wantEqual: success,
+			},
+			{
+				name:  "struct",
+				value: map[string]interface{}{"foo": 123.0},
+				testList: []interface{}{
+					struct {
+						Foo float64 `json:"foo"`
+					}{
+						Foo: 123.00,
+					},
+				},
+				wantEqual: success,
+			},
+		}
 
-		value.NotInList(nil)
-		value.chain.assert(t, failure)
-		value.chain.clear()
+		for _, tc := range cases {
+			t.Run(tc.name, func(t *testing.T) {
+				reporter := newMockReporter(t)
 
-		value.InList(func() {})
-		value.chain.assert(t, failure)
-		value.chain.clear()
+				NewObject(reporter, tc.value).InList(tc.testList...).
+					chain.assert(t, tc.wantEqual)
 
-		value.NotInList(func() {})
-		value.chain.assert(t, failure)
-		value.chain.clear()
+				NewObject(reporter, tc.value).NotInList(tc.testList...).
+					chain.assert(t, !tc.wantEqual)
+			})
+		}
 	})
 
 	t.Run("canonization", func(t *testing.T) {
@@ -641,26 +573,67 @@ func TestObject_InList(t *testing.T) {
 			myMap map[string]interface{}
 			myInt int
 		)
-
 		reporter := newMockReporter(t)
 
-		value := NewObject(reporter, map[string]interface{}{"foo": 123, "bar": 456})
+		data := map[string]interface{}{"foo": 123, "bar": 456}
 
-		value.InList(myMap{"foo": 123.0, "bar": 456.0})
-		value.chain.assert(t, success)
-		value.chain.clear()
+		NewObject(reporter, data).InList(myMap{"foo": 123.0, "bar": 456.0}).
+			chain.assert(t, success)
 
-		value.NotInList(myMap{"foo": 123.0, "bar": 456.0})
-		value.chain.assert(t, failure)
-		value.chain.clear()
+		NewObject(reporter, data).NotInList(myMap{"foo": 123.0, "bar": 456.0}).
+			chain.assert(t, failure)
+	})
 
-		value.InList(myMap{"foo": "123", "bar": myInt(456.0)})
-		value.chain.assert(t, failure)
-		value.chain.clear()
+	t.Run("invalid argument", func(t *testing.T) {
+		cases := []struct {
+			name     string
+			value    map[string]interface{}
+			testList []interface{}
+		}{
+			{
+				name:     "empty list",
+				value:    map[string]interface{}{},
+				testList: []interface{}{},
+			},
+			{
+				name:     "nil list",
+				value:    map[string]interface{}{},
+				testList: nil,
+			},
+			{
+				name:     "invalid type",
+				value:    map[string]interface{}{},
+				testList: []interface{}{func() {}},
+			},
+			{
+				name:  "one inequal object, another not object",
+				value: map[string]interface{}{"foo": 123.0},
+				testList: []interface{}{
+					map[string]interface{}{"bar": 123.0},
+					"NOT OBJECT",
+				},
+			},
+			{
+				name:  "one equal object, another not object",
+				value: map[string]interface{}{"foo": 123.0},
+				testList: []interface{}{
+					map[string]interface{}{"foo": 123.0},
+					"NOT OBJECT",
+				},
+			},
+		}
 
-		value.NotInList(myMap{"foo": "123", "bar": myInt(456.0)})
-		value.chain.assert(t, success)
-		value.chain.clear()
+		for _, tc := range cases {
+			t.Run(tc.name, func(t *testing.T) {
+				reporter := newMockReporter(t)
+
+				NewObject(reporter, tc.value).InList(tc.testList...).
+					chain.assert(t, failure)
+
+				NewObject(reporter, tc.value).NotInList(tc.testList...).
+					chain.assert(t, failure)
+			})
+		}
 	})
 }
 
@@ -1567,9 +1540,8 @@ func TestObject_Transform(t *testing.T) {
 		newObject := object.Transform(func(_ string, val interface{}) interface{} {
 			if v, err := strconv.ParseFloat(val.(string), 64); err == nil {
 				return myInt(v)
-			} else {
-				return val
 			}
+			return val
 		})
 
 		assert.Equal(t,
diff --git a/string_test.go b/string_test.go
index 344d572..a184cdd 100644
--- a/string_test.go
+++ b/string_test.go
@@ -145,25 +145,32 @@ func TestString_Alias(t *testing.T) {
 	assert.Equal(t, []string{"foo", "AsNumber()"}, childValue.chain.context.AliasedPath)
 }
 
-func TestString_Getters(t *testing.T) {
+func TestString_Path(t *testing.T) {
 	reporter := newMockReporter(t)
 
 	value := NewString(reporter, "foo")
 
-	assert.Equal(t, "foo", value.Raw())
-	value.chain.assert(t, success)
-	value.chain.clear()
-
 	assert.Equal(t, "foo", value.Path("$").Raw())
 	value.chain.assert(t, success)
-	value.chain.clear()
+}
 
-	value.Schema(`{"type": "string"}`)
-	value.chain.assert(t, success)
-	value.chain.clear()
+func TestString_Schema(t *testing.T) {
+	reporter := newMockReporter(t)
 
-	value.Schema(`{"type": "object"}`)
-	value.chain.assert(t, failure)
+	NewString(reporter, "foo").Schema(`{"type": "string"}`).
+		chain.assert(t, success)
+
+	NewString(reporter, "foo").Schema(`{"type": "object"}`).
+		chain.assert(t, failure)
+}
+
+func TestString_Getters(t *testing.T) {
+	reporter := newMockReporter(t)
+
+	value := NewString(reporter, "foo")
+
+	assert.Equal(t, "foo", value.Raw())
+	value.chain.assert(t, success)
 	value.chain.clear()
 
 	num := value.Length()
diff --git a/value_test.go b/value_test.go
index 78c3d1d..d30c1a4 100644
--- a/value_test.go
+++ b/value_test.go
@@ -1130,8 +1130,6 @@ func TestValue_PathExpressions(t *testing.T) {
 }
 
 func TestValue_Schema(t *testing.T) {
-	reporter := newMockReporter(t)
-
 	schema := `{
 		"type": "object",
 		"properties": {
@@ -1145,43 +1143,130 @@ func TestValue_Schema(t *testing.T) {
 		"require": ["foo", "bar"]
 	}`
 
-	data1 := map[string]interface{}{
-		"foo": "a",
-		"bar": 1,
-	}
+	t.Run("schema with valid data", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": 1,
+		}
+		NewValue(reporter, data).Schema(schema).
+			chain.assert(t, success)
+	})
 
-	data2 := map[string]interface{}{
-		"foo": "a",
-		"bar": "b",
-	}
+	t.Run("byte slice schema with valid data", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": 1,
+		}
+		NewValue(reporter, data).Schema([]byte(schema)).
+			chain.assert(t, success)
+	})
 
-	NewValue(reporter, data1).Schema(schema).chain.assert(t, success)
-	NewValue(reporter, data2).Schema(schema).chain.assert(t, failure)
+	t.Run("schema with invalid data", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": "b",
+		}
+		NewValue(reporter, data).Schema(schema).
+			chain.assert(t, failure)
+	})
 
-	NewValue(reporter, data1).Schema([]byte(schema)).chain.assert(t, success)
-	NewValue(reporter, data2).Schema([]byte(schema)).chain.assert(t, failure)
+	t.Run("byte slice schema with invalid data", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": "b",
+		}
+		NewValue(reporter, data).Schema([]byte(schema)).
+			chain.assert(t, failure)
+	})
 
-	var b interface{}
-	err := json.Unmarshal([]byte(schema), &b)
-	require.Nil(t, err)
+	t.Run("schema from unmarshalled JSON with valid data", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": 1,
+		}
+		var b interface{}
+		err := json.Unmarshal([]byte(schema), &b)
+		require.Nil(t, err)
+		NewValue(reporter, data).Schema(b).
+			chain.assert(t, success)
+	})
 
-	NewValue(reporter, data1).Schema(b).chain.assert(t, success)
-	NewValue(reporter, data2).Schema(b).chain.assert(t, failure)
+	t.Run("schema from unmarshalled JSON with invalid data", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": "b",
+		}
+		var b interface{}
+		err := json.Unmarshal([]byte(schema), &b)
+		require.Nil(t, err)
+		NewValue(reporter, data).Schema(b).
+			chain.assert(t, failure)
+	})
+
+	t.Run("schema with valid file url with valid data", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": 1,
+		}
+		tmp, _ := ioutil.TempFile("", "httpexpect")
+		defer os.Remove(tmp.Name())
+
+		_, err := tmp.Write([]byte(schema))
+		require.Nil(t, err)
+
+		err = tmp.Close()
+		require.Nil(t, err)
+
+		url := "file://" + tmp.Name()
+		NewValue(reporter, data).Schema(url).
+			chain.assert(t, success)
+	})
+
+	t.Run("schema with valid file url with invalid data", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": "b",
+		}
 
-	tmp, _ := ioutil.TempFile("", "httpexpect")
-	defer os.Remove(tmp.Name())
+		tmp, _ := ioutil.TempFile("", "httpexpect")
+		defer os.Remove(tmp.Name())
 
-	_, err = tmp.Write([]byte(schema))
-	require.Nil(t, err)
+		_, err := tmp.Write([]byte(schema))
+		require.Nil(t, err)
 
-	err = tmp.Close()
-	require.Nil(t, err)
+		err = tmp.Close()
+		require.Nil(t, err)
 
-	url := "file://" + tmp.Name()
+		url := "file://" + tmp.Name()
+		NewValue(reporter, data).Schema(url).
+			chain.assert(t, failure)
+	})
 
-	NewValue(reporter, data1).Schema(url).chain.assert(t, success)
-	NewValue(reporter, data2).Schema(url).chain.assert(t, failure)
+	t.Run("invalid schema file url", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": 1,
+		}
+		NewValue(reporter, data).Schema("file:///bad/path").
+			chain.assert(t, failure)
+	})
 
-	NewValue(reporter, data1).Schema("file:///bad/path").chain.assert(t, failure)
-	NewValue(reporter, data1).Schema("{ bad json").chain.assert(t, failure)
+	t.Run("invalid schema json", func(t *testing.T) {
+		reporter := newMockReporter(t)
+		data := map[string]interface{}{
+			"foo": "a",
+			"bar": 1,
+		}
+		NewValue(reporter, data).Schema("{ bad json").
+			chain.assert(t, failure)
+	})
 }
diff --git a/websocket_message_test.go b/websocket_message_test.go
index c4e78ff..6fc9129 100644
--- a/websocket_message_test.go
+++ b/websocket_message_test.go
@@ -73,6 +73,33 @@ func TestWebsocketMessage_Alias(t *testing.T) {
 	assert.Equal(t, []string{"foo", "Body()"}, childValue.chain.context.AliasedPath)
 }
 
+func TestWebsocketMessage_CloseCode(t *testing.T) {
+	t.Run("close code is not passed", func(t *testing.T) {
+		reporter := newMockReporter(t)
+
+		NewWebsocketMessage(reporter, websocket.CloseMessage, nil).Code(0).
+			chain.assert(t, success)
+		NewWebsocketMessage(reporter, websocket.CloseMessage, nil).NotCode(0).
+			chain.assert(t, failure)
+	})
+
+	t.Run("single close code is passed", func(t *testing.T) {
+		reporter := newMockReporter(t)
+
+		NewWebsocketMessage(reporter, websocket.CloseMessage, nil, 10).Code(10).
+			chain.assert(t, success)
+		NewWebsocketMessage(reporter, websocket.CloseMessage, nil, 10).NotCode(10).
+			chain.assert(t, failure)
+	})
+
+	t.Run("multiple close code is passed", func(t *testing.T) {
+		reporter := newMockReporter(t)
+
+		NewWebsocketMessage(reporter, websocket.CloseMessage, nil, 10, 20).
+			chain.assert(t, failure)
+	})
+}
+
 func TestWebsocketMessage_CloseMessage(t *testing.T) {
 	t.Run("CloseMessage type with functions", func(t *testing.T) {
 		cases := []struct {