Skip to content

Commit

Permalink
Add case query matcher
Browse files Browse the repository at this point in the history
  • Loading branch information
prongbang committed Oct 11, 2023
1 parent 9f365d5 commit 535c1fc
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 9 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ project

```shell script
POST http://localhost:8000/api/v1/login
Query
lang: "th"
Header
Api-Key: "ed2b7d14-3999-408e-9bb8-4ea739f2bcb5"
Body
Expand All @@ -99,6 +101,8 @@ routes:
request:
method: "POST"
url: "/api/v1/login"
query:
lang: "th"
header:
Api-Key: "ed2b7d14-3999-408e-9bb8-4ea739f2bcb5"
body:
Expand Down Expand Up @@ -149,6 +153,8 @@ routes:
request:
method: "POST"
url: "/api/v1/user"
query:
lang: "XYZ"
header:
Api-Key: "ABC"
cases:
Expand Down
7 changes: 7 additions & 0 deletions pkg/api/wiremock/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,19 @@ func (h *handler) Handle(w http.ResponseWriter, r *http.Request) {
// Prepared request
body := core.BindBody(h.Routers.Request.Body, r)

// Prepared query
query := core.BindQuery(h.Routers.Request.Query, r)

// Process parameter matching
matching := h.UseCase.ParameterMatching(Parameters{
ReqHeader: ReqHeader{
HttpHeader: httpHeader,
MockHeader: h.Routers.Request.Header,
},
ReqQuery: ReqQuery{
HttpQuery: query,
MockQuery: h.Routers.Request.Query,
},
ReqBody: ReqBody{
HttpBody: body,
MockBody: h.Routers.Request.Body,
Expand Down
7 changes: 7 additions & 0 deletions pkg/api/wiremock/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Request struct {
URL string `yaml:"url"`
Header map[string]interface{} `yaml:"header"`
Body map[string]interface{} `yaml:"body"`
Query map[string]interface{} `yaml:"query"`
Cases map[string]Cases `yaml:"cases"`
}

Expand Down Expand Up @@ -50,9 +51,15 @@ type ReqBody struct {
MockBody map[string]interface{}
}

type ReqQuery struct {
HttpQuery map[string]interface{}
MockQuery map[string]interface{}
}

type Parameters struct {
ReqHeader ReqHeader
ResHeader ResHeader
ReqQuery ReqQuery
ReqBody ReqBody
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/api/wiremock/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"github.com/gorilla/mux"
"github.com/prongbang/wiremock/v2/pkg/config"
"github.com/prongbang/wiremock/v2/pkg/status"
"io/ioutil"
"os"
)

type Router interface {
Expand All @@ -20,7 +20,7 @@ func (r *route) Initial(route *mux.Router) {
pattern := status.Pattern()

// Read dir mock
files, err := ioutil.ReadDir(config.MockPath)
files, err := os.ReadDir(config.MockPath)
if err != nil {
panic(pattern)
}
Expand Down
51 changes: 44 additions & 7 deletions pkg/api/wiremock/usecase.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"github.com/prongbang/wiremock/v2/pkg/core"
"github.com/prongbang/wiremock/v2/pkg/status"
"gopkg.in/yaml.v2"
"io/ioutil"
"net/http"
"os"
)

type UseCase interface {
Expand Down Expand Up @@ -38,6 +38,7 @@ func (u *useCase) GetRoutes(filepath string) Routes {
func (u *useCase) CasesMatching(r *http.Request, path string, cases map[string]Cases, params Parameters) CaseMatching {

// Get request
query := core.Query(r)
body := core.Body(r)

// Process header matching
Expand Down Expand Up @@ -68,16 +69,34 @@ func (u *useCase) CasesMatching(r *http.Request, path string, cases map[string]C
}
matchingHeaderRequest := len(params.ReqHeader.MockHeader) == matchingHeader

// Process body matching
// Process query & body matching
matchingQueryRequest := false
matchingBodyRequest := false
var foundCase Cases

for _, vMock := range cases {
matchingQuery := 0
matchingBody := 0
vMock.Response.FileName = path
if len(body) == 0 {
body = core.BindCaseBody(vMock.Body, r)
}
for qk, qv := range vMock.Query {
vs := fmt.Sprintf("%v", qv)
ks := fmt.Sprintf("%v", query[qk])

// Check require field value is not empty
if vs == "*" {
if query[qk] != nil {
matchingQuery = matchingQuery + 1
}
}

// Value matching
if vs == ks {
matchingQuery = matchingQuery + 1
}
}
for ck, cv := range vMock.Body {
vs := fmt.Sprintf("%v", cv)
ks := fmt.Sprintf("%v", body[ck])
Expand All @@ -97,14 +116,15 @@ func (u *useCase) CasesMatching(r *http.Request, path string, cases map[string]C

// Contains value
matchingBodyRequest = len(vMock.Body) == matchingBody
if matchingBodyRequest {
matchingQueryRequest = len(vMock.Query) == matchingQuery
if matchingBodyRequest && matchingQueryRequest {
foundCase = vMock
break
}
}

return CaseMatching{
IsMatch: matchingBodyRequest && matchingHeaderRequest,
IsMatch: matchingBodyRequest && matchingHeaderRequest && matchingQueryRequest,
Result: result,
Case: foundCase,
}
Expand All @@ -114,7 +134,23 @@ func (u *useCase) ParameterMatching(params Parameters) Matching {
require := map[string]interface{}{}
errors := map[string]interface{}{}
matchingHeader := 0
matchingQuery := 0
matchingBody := 0

for k, v := range params.ReqQuery.MockQuery {
vs := fmt.Sprintf("%v", v)
ks := fmt.Sprintf("%v", params.ReqQuery.HttpQuery[k])
if vs == ks {
matchingQuery = matchingQuery + 1
continue
}
if params.ReqQuery.HttpQuery[k] == nil {
errors[k] = "Require field " + k
} else {
errors[k] = "The " + k + " not match"
}
}

for k, v := range params.ReqBody.MockBody {
vs := fmt.Sprintf("%v", v)
ks := fmt.Sprintf("%v", params.ReqBody.HttpBody[k])
Expand Down Expand Up @@ -155,18 +191,19 @@ func (u *useCase) ParameterMatching(params Parameters) Matching {
}

isMatchHeader := len(params.ReqHeader.MockHeader) == matchingHeader
isMatchQuery := len(params.ReqQuery.MockQuery) == matchingQuery
isMatchBody := len(params.ReqBody.MockBody) == matchingBody

return Matching{
Result: result,
IsMatch: isMatchBody && isMatchHeader,
IsMatch: isMatchBody && isMatchHeader && isMatchQuery,
}
}

func (u *useCase) GetMockResponse(resp Response) []byte {
if resp.BodyFile != "" {
bodyFile := fmt.Sprintf(config.MockResponsePath, resp.FileName, resp.BodyFile)
source, err := ioutil.ReadFile(bodyFile)
source, err := os.ReadFile(bodyFile)
if err != nil {
return []byte("{}")
}
Expand All @@ -178,7 +215,7 @@ func (u *useCase) GetMockResponse(resp Response) []byte {
func (u *useCase) ReadSourceRouteYml(routeName string) []byte {
pattern := status.Pattern()
filename := fmt.Sprintf(config.MockRouteYmlPath, routeName)
source, err := ioutil.ReadFile(filename)
source, err := os.ReadFile(filename)
if err != nil {
panic(pattern)
}
Expand Down
20 changes: 20 additions & 0 deletions pkg/core/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ func Body(r *http.Request) map[string]interface{} {
return data
}

func Query(r *http.Request) map[string]interface{} {
queryParameters := r.URL.Query()
data := map[string]interface{}{}
for k := range queryParameters {
data[k] = queryParameters.Get(k)
}
return data
}

func Header(r *http.Request) map[string]interface{} {
data := map[string]interface{}{}
for k := range r.Header {
Expand All @@ -25,6 +34,17 @@ func Header(r *http.Request) map[string]interface{} {
return data
}

func BindQuery(mockQuery map[string]interface{}, r *http.Request) map[string]interface{} {
queryParameters := r.URL.Query()
data := map[string]interface{}{}
for k := range mockQuery {
if queryParameters.Has(k) {
data[k] = queryParameters.Get(k)
}
}
return data
}

func BindHeader(mockHeader map[string]interface{}, r *http.Request) map[string]interface{} {
data := map[string]interface{}{}
for k := range mockHeader {
Expand Down

0 comments on commit 535c1fc

Please sign in to comment.