-
-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #200 from pact-foundation/feat/graphql-support
feat: GraphQL interface
- Loading branch information
Showing
237 changed files
with
34,318 additions
and
1,736 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
on: [push, pull_request] | ||
name: Test | ||
|
||
env: | ||
REACT_APP_API_BASE_URL: http://localhost:8080 | ||
APP_SHA: ${{ github.sha }} | ||
APP_BRANCH: ${{ github.ref }} | ||
LD_LIBRARY_PATH: /tmp | ||
PACT_GO_LIB_DOWNLOAD_PATH: /tmp | ||
LOG_LEVEL: trace | ||
GIT_COMMIT: ${{ github.sha }} | ||
GIT_REF: ${{ github.ref }} | ||
COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
jobs: | ||
test: | ||
strategy: | ||
matrix: | ||
go-version: [1.17.x, 1.18.x] | ||
# os: [ubuntu-latest, macos-latest, windows-latest] | ||
os: [ubuntu-latest] | ||
runs-on: ${{ matrix.os }} | ||
steps: | ||
- name: Install Go | ||
uses: actions/setup-go@v2 | ||
with: | ||
go-version: ${{ matrix.go-version }} | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
- name: Test | ||
run: GIT_BRANCH=${GIT_REF:11} DOCKER_GATEWAY_HOST=172.17.0.1 DOCKER_HOST_HTTP="http://172.17.0.1" make | ||
- name: Install goveralls | ||
run: go install github.com/mattn/goveralls@latest | ||
- name: Send coverage | ||
run: goveralls -coverprofile=coverage.txt -service=github -parallel | ||
|
||
finish: | ||
needs: test | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Coveralls Finished | ||
uses: coverallsapp/github-action@master | ||
with: | ||
github-token: ${{ secrets.GITHUB_TOKEN }} | ||
parallel-finished: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
package graphql | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
|
||
"github.com/pact-foundation/pact-go/dsl" | ||
) | ||
|
||
// Variables represents values to be substituted into the query | ||
type Variables map[string]interface{} | ||
|
||
// Query is the main implementation of the Pact interface. | ||
type Query struct { | ||
// HTTP Headers | ||
Headers dsl.MapMatcher | ||
|
||
// Path to GraphQL endpoint | ||
Path dsl.Matcher | ||
|
||
// HTTP Query String | ||
QueryString dsl.MapMatcher | ||
|
||
// GraphQL Query | ||
Query string | ||
|
||
// GraphQL Variables | ||
Variables Variables | ||
|
||
// GraphQL Operation | ||
Operation string | ||
|
||
// GraphQL method (usually POST, but can be get with a query string) | ||
// NOTE: for query string users, the standard HTTP interaction should suffice | ||
Method string | ||
|
||
// Supports graphql extensions such as https://www.apollographql.com/docs/apollo-server/performance/apq/ | ||
Extensions Extensions | ||
} | ||
type Extensions map[string]interface{} | ||
|
||
// Specify the operation (if any) | ||
func (r *Query) WithOperation(operation string) *Query { | ||
r.Operation = operation | ||
|
||
return r | ||
} | ||
|
||
// WithContentType overrides the default content-type (application/json) | ||
// for the GraphQL Query | ||
func (r *Query) WithContentType(contentType dsl.Matcher) *Query { | ||
r.setHeader("content-type", contentType) | ||
|
||
return r | ||
} | ||
|
||
// Specify the method (defaults to POST) | ||
func (r *Query) WithMethod(method string) *Query { | ||
r.Method = method | ||
|
||
return r | ||
} | ||
|
||
// Given specifies a provider state. Optional. | ||
func (r *Query) WithQuery(query string) *Query { | ||
r.Query = query | ||
|
||
return r | ||
} | ||
|
||
// Given specifies a provider state. Optional. | ||
func (r *Query) WithVariables(variables Variables) *Query { | ||
r.Variables = variables | ||
|
||
return r | ||
} | ||
|
||
// Set the query extensions | ||
func (r *Query) WithExtensions(extensions Extensions) *Query { | ||
r.Extensions = extensions | ||
|
||
return r | ||
} | ||
|
||
var defaultHeaders = dsl.MapMatcher{"content-type": dsl.String("application/json")} | ||
|
||
func (r *Query) setHeader(headerName string, value dsl.Matcher) *Query { | ||
if r.Headers == nil { | ||
r.Headers = defaultHeaders | ||
} | ||
|
||
r.Headers[headerName] = value | ||
|
||
return r | ||
} | ||
|
||
// Construct a Pact HTTP request for a GraphQL interaction | ||
func Interaction(request Query) *dsl.Request { | ||
if request.Headers == nil { | ||
request.Headers = defaultHeaders | ||
} | ||
|
||
return &dsl.Request{ | ||
Method: request.Method, | ||
Path: request.Path, | ||
Query: request.QueryString, | ||
Body: graphQLQueryBody{ | ||
Operation: request.Operation, | ||
Query: dsl.Regex(request.Query, escapeGraphQlQuery(request.Query)), | ||
Variables: request.Variables, | ||
}, | ||
Headers: request.Headers, | ||
} | ||
|
||
} | ||
|
||
type graphQLQueryBody struct { | ||
Operation string `json:"operationName,omitempty"` | ||
Query dsl.Matcher `json:"query"` | ||
Variables Variables `json:"variables,omitempty"` | ||
} | ||
|
||
func escapeSpace(s string) string { | ||
r := regexp.MustCompile(`\s+`) | ||
return r.ReplaceAllString(s, `\s*`) | ||
} | ||
|
||
func escapeRegexChars(s string) string { | ||
r := regexp.MustCompile(`(?m)[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]`) | ||
|
||
f := func(s string) string { | ||
return fmt.Sprintf(`\%s`, s) | ||
} | ||
return r.ReplaceAllStringFunc(s, f) | ||
} | ||
|
||
func escapeGraphQlQuery(s string) string { | ||
return escapeSpace(escapeRegexChars(s)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package graphql | ||
|
||
// GraphQLRseponse models the GraphQL Response format. | ||
// See also http://spec.graphql.org/October2021/#sec-Response-Format | ||
type Response struct { | ||
Data interface{} `json:"data,omitempty"` | ||
Errors []interface{} `json:"errors,omitempty"` | ||
Extensions map[string]interface{} `json:"extensions,omitempty"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.