feat: add ui for the api-testing (#102)
* feat: add ui project for the atest * add grpc gateway support * complete the very basic ui of atest * add local storage flag into the server sub-command * add unit tests for the remote server * put the console into the docker image * remove unused files from console * add more unit tests * support to execute test case on ui * fix the code smells located by sonarqube --------- Co-authored-by: rick <linuxsuren@users.noreply.github.com>
This commit is contained in:
parent
7ff05a862e
commit
02d7e23cb3
|
@ -6,3 +6,4 @@ dist/
|
|||
.vscode/launch.json
|
||||
sample.yaml
|
||||
.DS_Store
|
||||
console/atest-ui/node_modules
|
||||
|
|
14
Dockerfile
14
Dockerfile
|
@ -4,6 +4,7 @@ WORKDIR /workspace
|
|||
COPY cmd/ cmd/
|
||||
COPY pkg/ pkg/
|
||||
COPY extensions/ extensions/
|
||||
COPY console/atest-ui atest-ui/
|
||||
COPY sample/ sample/
|
||||
COPY go.mod go.mod
|
||||
COPY go.sum go.sum
|
||||
|
@ -17,6 +18,13 @@ RUN go mod download
|
|||
RUN CGO_ENABLE=0 go build -ldflags "-w -s" -o atest .
|
||||
RUN CGO_ENABLE=0 go build -ldflags "-w -s" -o atest-collector extensions/collector/main.go
|
||||
|
||||
FROM node:20-alpine3.17 AS ui
|
||||
|
||||
WORKDIR /workspace
|
||||
COPY --from=builder /workspace/atest-ui .
|
||||
RUN npm install --ignore-scripts
|
||||
RUN npm run build-only
|
||||
|
||||
FROM ubuntu:23.04
|
||||
|
||||
LABEL "com.github.actions.name"="API testing"
|
||||
|
@ -35,4 +43,8 @@ COPY --from=builder /workspace/atest-collector /usr/local/bin/atest-collector
|
|||
COPY --from=builder /workspace/LICENSE /LICENSE
|
||||
COPY --from=builder /workspace/README.md /README.md
|
||||
|
||||
CMD ["atest", "server"]
|
||||
RUN mkdir -p /var/www
|
||||
COPY --from=builder /workspace/sample /var/www/sample
|
||||
COPY --from=ui /workspace/dist /var/www/html
|
||||
|
||||
CMD ["atest", "server", "--console-path=/var/www/html", "--local-storage=/var/www/sample/testsuite-*.yaml"]
|
||||
|
|
14
Makefile
14
Makefile
|
@ -7,7 +7,7 @@ goreleaser:
|
|||
build-image:
|
||||
docker build -t ghcr.io/linuxsuren/api-testing:dev .
|
||||
run-image:
|
||||
docker run ghcr.io/linuxsuren/api-testing:dev
|
||||
docker run -p 7070:7070 -p 8080:8080 ghcr.io/linuxsuren/api-testing:dev
|
||||
copy: build
|
||||
sudo cp bin/atest /usr/local/bin/
|
||||
copy-restart: build
|
||||
|
@ -24,13 +24,25 @@ grpc:
|
|||
protoc --go_out=. --go_opt=paths=source_relative \
|
||||
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
|
||||
pkg/server/server.proto
|
||||
grpc-gw:
|
||||
protoc -I . --grpc-gateway_out . \
|
||||
--grpc-gateway_opt logtostderr=true \
|
||||
--grpc-gateway_opt paths=source_relative \
|
||||
--grpc-gateway_opt generate_unbound_methods=true \
|
||||
pkg/server/server.proto
|
||||
grpc-js:
|
||||
protoc -I=pkg/server server.proto \
|
||||
--js_out=import_style=commonjs:bin \
|
||||
--grpc-web_out=import_style=commonjs,mode=grpcwebtext:bin
|
||||
# https://github.com/grpc/grpc-web
|
||||
grpc-ts:
|
||||
protoc -I=pkg/server server.proto \
|
||||
--js_out=import_style=commonjs,binary:console/atest-ui/src \
|
||||
--grpc-web_out=import_style=typescript,mode=grpcwebtext:console/atest-ui/src
|
||||
grpc-java:
|
||||
protoc --plugin=protoc-gen-grpc-java=/usr/local/bin/protoc-gen-grpc-java \
|
||||
--grpc-java_out=bin --proto_path=pkg/server server.proto
|
||||
install-tool:
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.1
|
||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2
|
||||
hd i protoc-gen-grpc-web
|
||||
|
|
|
@ -15,7 +15,7 @@ This is a API testing tool.
|
|||
* Validate the response body with [JSON schema](https://json-schema.org/)
|
||||
* Pre and post handle with the API request
|
||||
* Output reference between TestCase
|
||||
* Run in server mode, and provide the [gRPC endpoint](pkg/server/server.proto)
|
||||
* Run in server mode, and provide the [gRPC](pkg/server/server.proto) and HTTP endpoint
|
||||
* [VS Code extension](https://github.com/LinuxSuRen/vscode-api-testing) support
|
||||
* [HTTP API record](extensions/collector)
|
||||
|
||||
|
@ -66,9 +66,9 @@ consume: 1m2.153686448s
|
|||
|
||||
## Use in Docker
|
||||
|
||||
Use `atest` as server mode in Docker:
|
||||
Use `atest` as server mode in Docker, then you could visit the UI from `8080` and the gRPC endpoint from `7070`:
|
||||
```
|
||||
docker run -p 7070:7070 ghcr.io/linuxsuren/api-testing
|
||||
docker run -p 7070:7070 -p 8080:8080 ghcr.io/linuxsuren/api-testing
|
||||
```
|
||||
|
||||
Use `atest-collector` in Docker:
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/linuxsuren/api-testing/cmd"
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -35,7 +36,8 @@ func TestCreateFunctionCommand(t *testing.T) {
|
|||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := cmd.NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, cmd.NewFakeGRPCServer())
|
||||
c := cmd.NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"},
|
||||
cmd.NewFakeGRPCServer(), server.NewFakeHTTPServer())
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
c.SetOut(buf)
|
||||
|
|
|
@ -6,12 +6,14 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/linuxsuren/api-testing/cmd"
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestJSONSchemaCmd(t *testing.T) {
|
||||
c := cmd.NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, cmd.NewFakeGRPCServer())
|
||||
c := cmd.NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"},
|
||||
cmd.NewFakeGRPCServer(), server.NewFakeHTTPServer())
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
c.SetOut(buf)
|
||||
|
|
|
@ -3,13 +3,15 @@ package cmd
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
"github.com/linuxsuren/api-testing/pkg/version"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// NewRootCmd creates the root command
|
||||
func NewRootCmd(execer fakeruntime.Execer, gRPCServer gRPCServer) (c *cobra.Command) {
|
||||
func NewRootCmd(execer fakeruntime.Execer, gRPCServer gRPCServer,
|
||||
httpServer server.HTTPServer) (c *cobra.Command) {
|
||||
c = &cobra.Command{
|
||||
Use: "atest",
|
||||
Short: "API testing tool",
|
||||
|
@ -18,7 +20,7 @@ func NewRootCmd(execer fakeruntime.Execer, gRPCServer gRPCServer) (c *cobra.Comm
|
|||
c.Version = version.GetVersion()
|
||||
c.AddCommand(createInitCommand(execer),
|
||||
createRunCommand(), createSampleCmd(),
|
||||
createServerCmd(gRPCServer), createJSONSchemaCmd(),
|
||||
createServerCmd(gRPCServer, httpServer), createJSONSchemaCmd(),
|
||||
createServiceCommand(execer), createFunctionCmd())
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
)
|
||||
|
||||
|
@ -15,18 +16,18 @@ func TestCreateRunCommand(t *testing.T) {
|
|||
init := createInitCommand(fakeruntime.FakeExecer{})
|
||||
assert.Equal(t, "init", init.Use)
|
||||
|
||||
server := createServerCmd(&fakeGRPCServer{})
|
||||
assert.NotNil(t, server)
|
||||
assert.Equal(t, "server", server.Use)
|
||||
s := createServerCmd(&fakeGRPCServer{}, server.NewFakeHTTPServer())
|
||||
assert.NotNil(t, s)
|
||||
assert.Equal(t, "server", s.Use)
|
||||
|
||||
root := NewRootCmd(fakeruntime.FakeExecer{}, NewFakeGRPCServer())
|
||||
root := NewRootCmd(fakeruntime.FakeExecer{}, NewFakeGRPCServer(), server.NewFakeHTTPServer())
|
||||
root.SetArgs([]string{"init", "-k=demo.yaml", "--wait-namespace", "demo", "--wait-resource", "demo"})
|
||||
err := root.Execute()
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestRootCmd(t *testing.T) {
|
||||
c := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, NewFakeGRPCServer())
|
||||
c := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, NewFakeGRPCServer(), server.NewFakeHTTPServer())
|
||||
assert.NotNil(t, c)
|
||||
assert.Equal(t, "atest", c.Use)
|
||||
}
|
||||
|
|
|
@ -5,13 +5,15 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/linuxsuren/api-testing/cmd"
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
"github.com/linuxsuren/api-testing/sample"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestSampleCmd(t *testing.T) {
|
||||
c := cmd.NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, cmd.NewFakeGRPCServer())
|
||||
c := cmd.NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"},
|
||||
cmd.NewFakeGRPCServer(), server.NewFakeHTTPServer())
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
c.SetOut(buf)
|
||||
|
|
|
@ -5,14 +5,21 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
"github.com/linuxsuren/api-testing/pkg/testing"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func createServerCmd(gRPCServer gRPCServer) (c *cobra.Command) {
|
||||
opt := &serverOption{gRPCServer: gRPCServer}
|
||||
func createServerCmd(gRPCServer gRPCServer, httpServer server.HTTPServer) (c *cobra.Command) {
|
||||
opt := &serverOption{
|
||||
gRPCServer: gRPCServer,
|
||||
httpServer: httpServer,
|
||||
}
|
||||
c = &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Run as a server mode",
|
||||
|
@ -20,14 +27,22 @@ func createServerCmd(gRPCServer gRPCServer) (c *cobra.Command) {
|
|||
}
|
||||
flags := c.Flags()
|
||||
flags.IntVarP(&opt.port, "port", "p", 7070, "The RPC server port")
|
||||
flags.IntVarP(&opt.httpPort, "http-port", "", 8080, "The HTTP server port")
|
||||
flags.BoolVarP(&opt.printProto, "print-proto", "", false, "Print the proto content and exit")
|
||||
flags.StringVarP(&opt.localStorage, "local-storage", "", "", "The local storage path")
|
||||
flags.StringVarP(&opt.consolePath, "console-path", "", "", "The path of the console")
|
||||
return
|
||||
}
|
||||
|
||||
type serverOption struct {
|
||||
gRPCServer gRPCServer
|
||||
httpServer server.HTTPServer
|
||||
|
||||
port int
|
||||
httpPort int
|
||||
printProto bool
|
||||
localStorage string
|
||||
consolePath string
|
||||
}
|
||||
|
||||
func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
|
||||
|
@ -38,17 +53,54 @@ func (o *serverOption) runE(cmd *cobra.Command, args []string) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
var lis net.Listener
|
||||
var (
|
||||
lis net.Listener
|
||||
httplis net.Listener
|
||||
)
|
||||
lis, err = net.Listen("tcp", fmt.Sprintf(":%d", o.port))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
s := o.gRPCServer
|
||||
server.RegisterRunnerServer(s, server.NewRemoteServer())
|
||||
log.Printf("server listening at %v", lis.Addr())
|
||||
s.Serve(lis)
|
||||
httplis, err = net.Listen("tcp", fmt.Sprintf(":%d", o.httpPort))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
loader := testing.NewFileLoader()
|
||||
if o.localStorage != "" {
|
||||
if err = loader.Put(o.localStorage); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
removeServer := server.NewRemoteServer(loader)
|
||||
s := o.gRPCServer
|
||||
go func() {
|
||||
server.RegisterRunnerServer(s, removeServer)
|
||||
log.Printf("gRPC server listening at %v", lis.Addr())
|
||||
s.Serve(lis)
|
||||
}()
|
||||
|
||||
mux := runtime.NewServeMux()
|
||||
err = server.RegisterRunnerHandlerServer(cmd.Context(), mux, removeServer)
|
||||
if err == nil {
|
||||
mux.HandlePath("GET", "/", frontEndHandlerWithLocation(o.consolePath))
|
||||
mux.HandlePath("GET", "/assets/{asset}", frontEndHandlerWithLocation(o.consolePath))
|
||||
o.httpServer.WithHandler(mux)
|
||||
err = o.httpServer.Serve(httplis)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func frontEndHandlerWithLocation(consolePath string) func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
|
||||
return func(w http.ResponseWriter, r *http.Request, pathParams map[string]string) {
|
||||
target := r.URL.Path
|
||||
if target == "/" {
|
||||
target = "/index.html"
|
||||
}
|
||||
|
||||
http.ServeFile(w, r, path.Join(consolePath, target))
|
||||
}
|
||||
}
|
||||
|
||||
type gRPCServer interface {
|
||||
|
|
|
@ -2,9 +2,11 @@ package cmd
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -29,7 +31,7 @@ func TestPrintProto(t *testing.T) {
|
|||
},
|
||||
}, {
|
||||
name: "random port",
|
||||
args: []string{"server", "-p=0"},
|
||||
args: []string{"server", "-p=0", "--http-port=0", "--local-storage=./*"},
|
||||
verify: func(t *testing.T, buf *bytes.Buffer, err error) {
|
||||
assert.Nil(t, err)
|
||||
},
|
||||
|
@ -37,7 +39,8 @@ func TestPrintProto(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
root := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, &fakeGRPCServer{})
|
||||
root := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"},
|
||||
&fakeGRPCServer{}, server.NewFakeHTTPServer())
|
||||
root.SetOut(buf)
|
||||
root.SetArgs(tt.args)
|
||||
err := root.Execute()
|
||||
|
@ -45,3 +48,27 @@ func TestPrintProto(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFrontEndHandlerWithLocation(t *testing.T) {
|
||||
handler := frontEndHandlerWithLocation("testdata")
|
||||
req, err := http.NewRequest("GET", "/", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
handler(&fakeResponseWriter{buf: buf}, req, map[string]string{})
|
||||
assert.Equal(t, "404 page not found\n", buf.String())
|
||||
}
|
||||
|
||||
type fakeResponseWriter struct {
|
||||
buf *bytes.Buffer
|
||||
}
|
||||
|
||||
func (w *fakeResponseWriter) Header() http.Header {
|
||||
return make(http.Header)
|
||||
}
|
||||
func (w *fakeResponseWriter) Write(data []byte) (int, error) {
|
||||
return w.buf.Write(data)
|
||||
}
|
||||
func (w *fakeResponseWriter) WriteHeader(int) {
|
||||
// do nothing due to this is a fake response writer
|
||||
}
|
||||
|
|
|
@ -5,18 +5,19 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
fakeruntime "github.com/linuxsuren/go-fake-runtime"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestService(t *testing.T) {
|
||||
root := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, NewFakeGRPCServer())
|
||||
root := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "linux"}, NewFakeGRPCServer(), server.NewFakeHTTPServer())
|
||||
root.SetArgs([]string{"service", "fake"})
|
||||
root.SetOut(new(bytes.Buffer))
|
||||
err := root.Execute()
|
||||
assert.NotNil(t, err)
|
||||
|
||||
notLinux := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "fake"}, NewFakeGRPCServer())
|
||||
notLinux := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: "fake"}, NewFakeGRPCServer(), server.NewFakeHTTPServer())
|
||||
notLinux.SetArgs([]string{"service", paramAction, "install"})
|
||||
notLinux.SetOut(new(bytes.Buffer))
|
||||
err = notLinux.Execute()
|
||||
|
@ -87,7 +88,8 @@ func TestService(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
normalRoot := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: tt.targetOS, ExpectOutput: tt.expectOutput}, NewFakeGRPCServer())
|
||||
normalRoot := NewRootCmd(fakeruntime.FakeExecer{ExpectOS: tt.targetOS, ExpectOutput: tt.expectOutput},
|
||||
NewFakeGRPCServer(), server.NewFakeHTTPServer())
|
||||
normalRoot.SetOut(buf)
|
||||
normalRoot.SetArgs([]string{"service", "--action", tt.action, "--script-path", tmpFile.Name()})
|
||||
err = normalRoot.Execute()
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/* eslint-env node */
|
||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
'extends': [
|
||||
'plugin:vue/vue3-essential',
|
||||
'eslint:recommended',
|
||||
'@vue/eslint-config-typescript',
|
||||
'@vue/eslint-config-prettier/skip-formatting'
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
files: [
|
||||
'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}'
|
||||
],
|
||||
'extends': [
|
||||
'plugin:cypress/recommended'
|
||||
]
|
||||
}
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest'
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
coverage
|
||||
*.local
|
||||
|
||||
/cypress/videos/
|
||||
/cypress/screenshots/
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"trailingComma": "none"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
# atest-ui
|
||||
|
||||
This template should help get you started developing with Vue 3 in Vite.
|
||||
|
||||
## Recommended IDE Setup
|
||||
|
||||
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||
|
||||
## Type Support for `.vue` Imports in TS
|
||||
|
||||
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
|
||||
|
||||
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
||||
|
||||
1. Disable the built-in TypeScript Extension
|
||||
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
||||
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
||||
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
||||
|
||||
## Customize configuration
|
||||
|
||||
See [Vite Configuration Reference](https://vitejs.dev/config/).
|
||||
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compile and Hot-Reload for Development
|
||||
|
||||
```sh
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Type-Check, Compile and Minify for Production
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Run Unit Tests with [Vitest](https://vitest.dev/)
|
||||
|
||||
```sh
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
### Run End-to-End Tests with [Cypress](https://www.cypress.io/)
|
||||
|
||||
```sh
|
||||
npm run test:e2e:dev
|
||||
```
|
||||
|
||||
This runs the end-to-end tests against the Vite development server.
|
||||
It is much faster than the production build.
|
||||
|
||||
But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments):
|
||||
|
||||
```sh
|
||||
npm run build
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
### Lint with [ESLint](https://eslint.org/)
|
||||
|
||||
```sh
|
||||
npm run lint
|
||||
```
|
||||
|
||||
```sh
|
||||
npm install -g cnpm --registry=https://registry.npmmirror.com
|
||||
```
|
|
@ -0,0 +1,8 @@
|
|||
import { defineConfig } from 'cypress'
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}',
|
||||
baseUrl: 'http://localhost:4173'
|
||||
}
|
||||
})
|
|
@ -0,0 +1,8 @@
|
|||
// https://on.cypress.io/api
|
||||
|
||||
describe('My First Test', () => {
|
||||
it('visits the app root url', () => {
|
||||
cy.visit('/')
|
||||
cy.contains('h1', 'You did it!')
|
||||
})
|
||||
})
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"include": ["./**/*", "../support/**/*"],
|
||||
"compilerOptions": {
|
||||
"isolatedModules": false,
|
||||
"target": "es5",
|
||||
"lib": ["es5", "dom"],
|
||||
"types": ["cypress"]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/// <reference types="cypress" />
|
||||
// ***********************************************
|
||||
// This example commands.ts shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
//
|
||||
// declare global {
|
||||
// namespace Cypress {
|
||||
// interface Chainable {
|
||||
// login(email: string, password: string): Chainable<void>
|
||||
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
|
||||
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
export {}
|
|
@ -0,0 +1,20 @@
|
|||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
|
@ -0,0 +1 @@
|
|||
/// <reference types="vite/client" />
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
./node_modules/.bin/grpc_tools_node_protoc --plugin=protoc-gen-ts=. --ts_out=../../pkg/server -I ../../pkg/server ../../pkg/server/server.proto
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" href="/favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>API Testing</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"name": "-atest-ui",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "run-p type-check build-only",
|
||||
"preview": "vite preview",
|
||||
"test:unit": "vitest",
|
||||
"test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'",
|
||||
"test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'",
|
||||
"build-only": "vite build",
|
||||
"type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
|
||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"element-plus": "^2.3.7",
|
||||
"vue": "^3.3.4",
|
||||
"vue-router": "^4.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.2.0",
|
||||
"@tsconfig/node18": "^2.0.1",
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/google-protobuf": "^3.15.6",
|
||||
"@types/jsdom": "^21.1.1",
|
||||
"@types/node": "^18.16.18",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@vitejs/plugin-vue-jsx": "^3.0.1",
|
||||
"@vue/eslint-config-prettier": "^7.1.0",
|
||||
"@vue/eslint-config-typescript": "^11.0.3",
|
||||
"@vue/test-utils": "^2.3.2",
|
||||
"@vue/tsconfig": "^0.4.0",
|
||||
"cypress": "^12.14.0",
|
||||
"eslint": "^8.39.0",
|
||||
"eslint-plugin-cypress": "^2.13.3",
|
||||
"eslint-plugin-vue": "^9.11.0",
|
||||
"grpc_tools_node_protoc_ts": "^5.3.3",
|
||||
"grpc-tools": "^1.12.4",
|
||||
"jsdom": "^22.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^2.8.8",
|
||||
"start-server-and-test": "^2.0.0",
|
||||
"typescript": "~5.0.4",
|
||||
"vite": "^4.3.9",
|
||||
"vitest": "^0.32.0",
|
||||
"vue-tsc": "^1.6.5"
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
|
@ -0,0 +1,139 @@
|
|||
<script setup lang="ts">
|
||||
import TestCase from './views/TestCase.vue'
|
||||
import { ref } from 'vue'
|
||||
import { ElTree } from "element-plus"
|
||||
|
||||
interface Tree {
|
||||
id: string
|
||||
label: string
|
||||
parent: string
|
||||
children?: Tree[]
|
||||
}
|
||||
|
||||
const testCaseName = ref('')
|
||||
const testSuite = ref('')
|
||||
const handleNodeClick = (data: Tree) => {
|
||||
testCaseName.value = data.label
|
||||
testSuite.value = data.parent
|
||||
}
|
||||
|
||||
const data = ref([])
|
||||
const treeRef = ref<InstanceType<typeof ElTree>>()
|
||||
|
||||
const requestOptions = {
|
||||
method: 'POST'
|
||||
};
|
||||
fetch('/server.Runner/GetSuites', requestOptions)
|
||||
.then(response => response.json())
|
||||
.then(d => {
|
||||
data.value = []
|
||||
Object.keys(d.data).map(k => {
|
||||
console.log(d.data[k])
|
||||
let suite = {
|
||||
id: k,
|
||||
label: k,
|
||||
children: [],
|
||||
}
|
||||
|
||||
d.data[k].data.forEach((item: any) => {
|
||||
suite.children?.push({
|
||||
id: item,
|
||||
label: item,
|
||||
parent: k,
|
||||
})
|
||||
})
|
||||
data.value.push(suite)
|
||||
})
|
||||
|
||||
// treeRef.value.updateKeyChildren('1', data[0].children)
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="common-layout">
|
||||
<el-container>
|
||||
<el-aside width="200px">
|
||||
<el-tree :data="data" :props="defaultProps"
|
||||
default-expand-all
|
||||
ref="treeRef"
|
||||
node-key="id"
|
||||
@node-click="handleNodeClick" />
|
||||
</el-aside>
|
||||
|
||||
<el-main>
|
||||
<TestCase :suite="testSuite" :name="testCaseName"/>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
header {
|
||||
line-height: 1.5;
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: block;
|
||||
margin: 0 auto 2rem;
|
||||
}
|
||||
|
||||
nav {
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
nav a.router-link-exact-active {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
nav a.router-link-exact-active:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
nav a {
|
||||
display: inline-block;
|
||||
padding: 0 1rem;
|
||||
border-left: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
nav a:first-of-type {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
header {
|
||||
display: flex;
|
||||
place-items: center;
|
||||
padding-right: calc(var(--section-gap) / 2);
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin: 0 2rem 0 0;
|
||||
}
|
||||
|
||||
header .wrapper {
|
||||
display: flex;
|
||||
place-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
nav {
|
||||
text-align: left;
|
||||
margin-left: -1rem;
|
||||
font-size: 1rem;
|
||||
|
||||
padding: 1rem 0;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
.demo-tabs > .el-tabs__content {
|
||||
padding: 32px;
|
||||
color: #6b778c;
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,73 @@
|
|||
/* color palette from <https://github.com/vuejs/theme> */
|
||||
:root {
|
||||
--vt-c-white: #fff;
|
||||
--vt-c-white-soft: #f8f8f8;
|
||||
--vt-c-white-mute: #f2f2f2;
|
||||
|
||||
--vt-c-black: #181818;
|
||||
--vt-c-black-soft: #222;
|
||||
--vt-c-black-mute: #282828;
|
||||
|
||||
--vt-c-indigo: #2c3e50;
|
||||
|
||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
||||
|
||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
||||
--vt-c-text-dark-1: var(--vt-c-white);
|
||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
||||
}
|
||||
|
||||
/* semantic color variables for this project */
|
||||
:root {
|
||||
--color-background: var(--vt-c-white);
|
||||
--color-background-soft: var(--vt-c-white-soft);
|
||||
--color-background-mute: var(--vt-c-white-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-light-2);
|
||||
--color-border-hover: var(--vt-c-divider-light-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-light-1);
|
||||
--color-text: var(--vt-c-text-light-1);
|
||||
|
||||
--section-gap: 160px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--color-background: var(--vt-c-black);
|
||||
--color-background-soft: var(--vt-c-black-soft);
|
||||
--color-background-mute: var(--vt-c-black-mute);
|
||||
|
||||
--color-border: var(--vt-c-divider-dark-2);
|
||||
--color-border-hover: var(--vt-c-divider-dark-1);
|
||||
|
||||
--color-heading: var(--vt-c-text-dark-1);
|
||||
--color-text: var(--vt-c-text-dark-2);
|
||||
}
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
color: var(--color-text);
|
||||
background: var(--color-background);
|
||||
transition: color 0.5s, background-color 0.5s;
|
||||
line-height: 1.6;
|
||||
font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu,
|
||||
Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
font-size: 15px;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 261.76 226.69"><path d="M161.096.001l-30.225 52.351L100.647.001H-.005l130.877 226.688L261.749.001z" fill="#41b883"/><path d="M161.096.001l-30.225 52.351L100.647.001H52.346l78.526 136.01L209.398.001z" fill="#34495e"/></svg>
|
After Width: | Height: | Size: 276 B |
|
@ -0,0 +1,22 @@
|
|||
@import './base.css';
|
||||
|
||||
#app {
|
||||
/* max-width: 1280px; */
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a,
|
||||
.green {
|
||||
text-decoration: none;
|
||||
color: hsla(160, 100%, 37%, 1);
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
a:hover {
|
||||
background-color: hsla(160, 100%, 37%, 0.2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import './assets/main.css'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
// import router from './router'
|
||||
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
app.use(ElementPlus, {
|
||||
locale: zhCn,
|
||||
})
|
||||
// app.use(router)
|
||||
|
||||
app.mount('#app')
|
|
@ -0,0 +1,202 @@
|
|||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import type { TabsPaneContext } from 'element-plus'
|
||||
|
||||
const props = defineProps({
|
||||
name: String,
|
||||
suite: String,
|
||||
})
|
||||
|
||||
const testResult = ref('')
|
||||
function sendRequest() {
|
||||
const name = props.name
|
||||
const suite = props.suite
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
suite: suite,
|
||||
testcase: name,
|
||||
})
|
||||
};
|
||||
fetch('/server.Runner/RunTestCase', requestOptions)
|
||||
.then(response => response.json())
|
||||
.then(e => {
|
||||
testResult.value = e.body
|
||||
});
|
||||
}
|
||||
|
||||
interface Pair{
|
||||
key: string,
|
||||
value: string
|
||||
}
|
||||
|
||||
const emptyPair: Pair[] = []
|
||||
|
||||
const verifyList = ref('')
|
||||
const requestBody = ref('')
|
||||
const bodyFieldsExpect = ref('')
|
||||
const headersData = ref(emptyPair)
|
||||
|
||||
watch(props, (p) => {
|
||||
const name = p.name
|
||||
const suite = p.suite
|
||||
const requestOptions = {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
suite: suite,
|
||||
testcase: name,
|
||||
})
|
||||
};
|
||||
fetch('/server.Runner/GetTestCase', requestOptions)
|
||||
.then(response => response.json())
|
||||
.then(e => {
|
||||
if (e.request.method === "") {
|
||||
e.request.method = "GET"
|
||||
}
|
||||
value.value = e.request.method
|
||||
input.value = e.request.api
|
||||
requestBody.value = e.request.body
|
||||
verifyList.value = e.response.verify
|
||||
|
||||
headersData.value = []
|
||||
e.request.header.forEach(h => {
|
||||
headersData.value.push({
|
||||
key: h.key,
|
||||
value: h.value
|
||||
})
|
||||
})
|
||||
|
||||
let items: Pair[] = []
|
||||
e.response.bodyFieldsExpect.forEach(b => {
|
||||
items.push({
|
||||
key: b.key,
|
||||
value: b.value
|
||||
})
|
||||
})
|
||||
bodyFieldsExpect.value = items
|
||||
});
|
||||
})
|
||||
|
||||
const value = ref('')
|
||||
|
||||
const options = [
|
||||
{
|
||||
value: 'GET',
|
||||
label: 'GET',
|
||||
},
|
||||
{
|
||||
value: 'POST',
|
||||
label: 'POST',
|
||||
},
|
||||
{
|
||||
value: 'DELETE',
|
||||
label: 'DELETE',
|
||||
},
|
||||
{
|
||||
value: 'PUT',
|
||||
label: 'PUT',
|
||||
},
|
||||
]
|
||||
|
||||
const activeName = ref('second')
|
||||
|
||||
const handleClick = (tab: TabsPaneContext, event: Event) => {
|
||||
console.log(tab, event)
|
||||
}
|
||||
|
||||
const input = ref('')
|
||||
|
||||
function change() {
|
||||
let lastItem = headersData.value[headersData.value.length - 1]
|
||||
if (lastItem.key !== '') {
|
||||
headersData.value.push({
|
||||
key: '',
|
||||
value: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const radio1 = ref('1')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="common-layout">
|
||||
<el-container>
|
||||
<el-header style="padding-left: 5px;">
|
||||
<el-select v-model="value" class="m-2" placeholder="Method" size="large">
|
||||
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
<el-input v-model="input" placeholder="API Address" style="width: 70%; margin-left: 5px; margin-right: 5px;"/>
|
||||
<el-button type="primary" @click="sendRequest">Send</el-button>
|
||||
</el-header>
|
||||
|
||||
<el-main>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
|
||||
|
||||
<el-tab-pane label="Headers" name="second">
|
||||
<el-table :data="headersData" style="width: 100%">
|
||||
<el-table-column label="Key" width="180">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.key" placeholder="Key" @change="change" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Value">
|
||||
<template #default="scope">
|
||||
<div style="display: flex; align-items: center">
|
||||
<el-input v-model="scope.row.value" placeholder="Value" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="Body" name="third">
|
||||
<el-radio-group v-model="radio1">
|
||||
<el-radio :label="1">none</el-radio>
|
||||
<el-radio :label="2">form-data</el-radio>
|
||||
<el-radio :label="3">raw</el-radio>
|
||||
<el-radio :label="4">x-www-form-urlencoded</el-radio>
|
||||
</el-radio-group>
|
||||
|
||||
<el-input v-model="requestBody" :autosize="{ minRows: 4, maxRows: 8 }" type="textarea"
|
||||
placeholder="Please input" />
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="BodyFiledExpect" name="fourth">
|
||||
<el-table :data="bodyFieldsExpect" style="width: 100%">
|
||||
<el-table-column label="Key" width="180">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.key" placeholder="Key" @change="change" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Value">
|
||||
<template #default="scope">
|
||||
<div style="display: flex; align-items: center">
|
||||
<el-input v-model="scope.row.value" placeholder="Value" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="Verify" name="fifth">
|
||||
<div v-for="verify in verifyList" :key="verify">
|
||||
<el-input :value="verify" placeholder="API Address" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-main>
|
||||
|
||||
<el-footer>
|
||||
<div>Test Result:</div>
|
||||
<el-input
|
||||
v-model="testResult"
|
||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
||||
readonly="true"
|
||||
type="textarea"
|
||||
placeholder="Please input"
|
||||
/>
|
||||
</el-footer>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue", "vue.config.ts"],
|
||||
"exclude": ["src/**/__tests__/*"],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"files": [],
|
||||
"compilerOptions":{
|
||||
"module":"commonjs",
|
||||
"allowJs": true,
|
||||
"target": "es6",
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.vitest.json"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"extends": "@tsconfig/node18/tsconfig.json",
|
||||
"include": [
|
||||
"vite.config.*",
|
||||
"vitest.config.*",
|
||||
"cypress.config.*",
|
||||
"nightwatch.conf.*",
|
||||
"playwright.config.*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"module": "ESNext",
|
||||
"types": ["node"]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "./tsconfig.app.json",
|
||||
"exclude": [],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"lib": [],
|
||||
"types": ["node", "jsdom"]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
}
|
||||
},
|
||||
server: {
|
||||
proxy: {
|
||||
'/server.Runner': {
|
||||
target: 'http://127.0.0.1:8080',
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
|
@ -0,0 +1,18 @@
|
|||
import { fileURLToPath } from 'node:url'
|
||||
import { mergeConfig } from 'vite'
|
||||
import { configDefaults, defineConfig } from 'vitest/config'
|
||||
import viteConfig from './vite.config'
|
||||
|
||||
export default mergeConfig(
|
||||
viteConfig,
|
||||
defineConfig({
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
exclude: [...configDefaults.exclude, 'e2e/*'],
|
||||
root: fileURLToPath(new URL('./', import.meta.url)),
|
||||
transformMode: {
|
||||
web: [/\.[jt]sx$/]
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
18
go.mod
18
go.mod
|
@ -7,6 +7,7 @@ require (
|
|||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
|
||||
github.com/antonmedv/expr v1.12.1
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0
|
||||
github.com/h2non/gock v1.2.0
|
||||
github.com/invopop/jsonschema v0.7.0
|
||||
github.com/linuxsuren/go-fake-runtime v0.0.0-20230426144714-1a7a0d160d3f
|
||||
|
@ -15,24 +16,26 @@ require (
|
|||
github.com/stretchr/testify v1.8.2
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
golang.org/x/sync v0.1.0
|
||||
google.golang.org/grpc v1.54.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
google.golang.org/grpc v1.55.0
|
||||
google.golang.org/protobuf v1.30.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
||||
github.com/huandu/xstrings v1.3.3 // indirect
|
||||
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
|
||||
github.com/imdario/mergo v0.3.11 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/shopspring/decimal v1.2.0 // indirect
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
|
@ -40,10 +43,11 @@ require (
|
|||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
golang.org/x/crypto v0.3.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
44
go.sum
44
go.sum
|
@ -9,19 +9,23 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
|
|||
github.com/antonmedv/expr v1.12.1 h1:GTGrGN1kxxb+le0uQKaFRK8By4cvq1sleUCGE/U6hHg=
|
||||
github.com/antonmedv/expr v1.12.1/go.mod h1:FPC8iWArxls7axbVLsW+kpg1mz29A1b2M6jt+hZfDkU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
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/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE=
|
||||
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/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/uuid v1.1.1/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/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
|
||||
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
||||
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||
|
@ -36,11 +40,12 @@ github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7P
|
|||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy770So=
|
||||
github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/linuxsuren/go-fake-runtime v0.0.0-20230426144714-1a7a0d160d3f h1:TfAzkLxq/agwMBbccTx/f/dlmFWIBLWRGCWjI4IOlK8=
|
||||
github.com/linuxsuren/go-fake-runtime v0.0.0-20230426144714-1a7a0d160d3f/go.mod h1:zmh6J78hSnWZo68faMA2eKOdaEp8eFbERHi3ZB9xHCQ=
|
||||
github.com/linuxsuren/unstructured v0.0.1 h1:ilUA8MUYbR6l9ebo/YPV2bKqlf62bzQursDSE+j00iU=
|
||||
|
@ -53,6 +58,8 @@ github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy
|
|||
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
|
||||
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.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
|
@ -92,8 +99,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
|
@ -104,8 +111,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
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.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.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=
|
||||
|
@ -113,24 +120,27 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|||
golang.org/x/text v0.3.3/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.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
|
||||
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
|
||||
google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
|
||||
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
|
||||
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||
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.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/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-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
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=
|
||||
|
|
|
@ -1 +1,9 @@
|
|||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
|
4
main.go
4
main.go
|
@ -4,13 +4,15 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/linuxsuren/api-testing/cmd"
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
exec "github.com/linuxsuren/go-fake-runtime"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gRPCServer := grpc.NewServer()
|
||||
c := cmd.NewRootCmd(exec.DefaultExecer{}, gRPCServer)
|
||||
c := cmd.NewRootCmd(exec.DefaultExecer{}, gRPCServer,
|
||||
server.NewDefaultHTTPServer())
|
||||
if err := c.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// HTTPServer is an interface for serving HTTP requests
|
||||
type HTTPServer interface {
|
||||
Serve(lis net.Listener) error
|
||||
WithHandler(handler http.Handler)
|
||||
}
|
||||
|
||||
type defaultHTTPServer struct {
|
||||
handler http.Handler
|
||||
}
|
||||
|
||||
// NewDefaultHTTPServer creates a default HTTP server
|
||||
func NewDefaultHTTPServer() HTTPServer {
|
||||
return &defaultHTTPServer{}
|
||||
}
|
||||
|
||||
func (s *defaultHTTPServer) Serve(lis net.Listener) (err error) {
|
||||
server := &http.Server{Handler: s.handler}
|
||||
err = server.Serve(lis)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *defaultHTTPServer) WithHandler(h http.Handler) {
|
||||
s.handler = h
|
||||
}
|
||||
|
||||
type fakeHandler struct{}
|
||||
|
||||
// NewFakeHTTPServer creates a fake HTTP server
|
||||
func NewFakeHTTPServer() HTTPServer {
|
||||
return &fakeHandler{}
|
||||
}
|
||||
|
||||
func (s *fakeHandler) Serve(lis net.Listener) (err error) {
|
||||
// do nothing due to this is a fake method
|
||||
return
|
||||
}
|
||||
|
||||
func (s *fakeHandler) WithHandler(h http.Handler) {
|
||||
// do nothing due to this is a fake method
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package server_test
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/linuxsuren/api-testing/pkg/server"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestHTTPServer(t *testing.T) {
|
||||
lis, err := net.Listen("tcp", ":0")
|
||||
assert.Nil(t, err)
|
||||
|
||||
fake := server.NewFakeHTTPServer()
|
||||
fake.WithHandler(nil)
|
||||
fake.Serve(lis)
|
||||
|
||||
defaultHTTPServer := server.NewDefaultHTTPServer()
|
||||
defaultHTTPServer.WithHandler(nil)
|
||||
}
|
|
@ -14,15 +14,17 @@ import (
|
|||
"github.com/linuxsuren/api-testing/pkg/testing"
|
||||
"github.com/linuxsuren/api-testing/pkg/version"
|
||||
"github.com/linuxsuren/api-testing/sample"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type server struct {
|
||||
UnimplementedRunnerServer
|
||||
loader testing.Loader
|
||||
}
|
||||
|
||||
// NewRemoteServer creates a remote server instance
|
||||
func NewRemoteServer() RunnerServer {
|
||||
return &server{}
|
||||
func NewRemoteServer(loader testing.Loader) RunnerServer {
|
||||
return &server{loader: loader}
|
||||
}
|
||||
|
||||
func withDefaultValue(old, defVal any) any {
|
||||
|
@ -141,6 +143,154 @@ func (s *server) GetVersion(ctx context.Context, in *Empty) (reply *HelloReply,
|
|||
return
|
||||
}
|
||||
|
||||
func (s *server) GetSuites(ctx context.Context, in *Empty) (reply *Suites, err error) {
|
||||
defer func() {
|
||||
s.loader.Reset()
|
||||
}()
|
||||
|
||||
reply = &Suites{
|
||||
Data: make(map[string]*Items),
|
||||
}
|
||||
for s.loader.HasMore() {
|
||||
var data []byte
|
||||
if data, err = s.loader.Load(); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var testSuite *testing.TestSuite
|
||||
if testSuite, err = testing.Parse(data); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
items := &Items{}
|
||||
for _, item := range testSuite.Items {
|
||||
items.Data = append(items.Data, item.Name)
|
||||
}
|
||||
reply.Data[testSuite.Name] = items
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *server) GetTestCase(ctx context.Context, in *TestCaseIdentity) (reply *TestCase, err error) {
|
||||
defer func() {
|
||||
s.loader.Reset()
|
||||
}()
|
||||
|
||||
for s.loader.HasMore() {
|
||||
var data []byte
|
||||
if data, err = s.loader.Load(); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var testSuite *testing.TestSuite
|
||||
if testSuite, err = testing.Parse(data); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if testSuite.Name != in.Suite {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, testCase := range testSuite.Items {
|
||||
if testCase.Name != in.Testcase {
|
||||
continue
|
||||
}
|
||||
|
||||
req := &Request{
|
||||
Api: testCase.Request.API,
|
||||
Method: testCase.Request.Method,
|
||||
Header: mapToPair(testCase.Request.Header),
|
||||
Query: mapToPair(testCase.Request.Query),
|
||||
Form: mapToPair(testCase.Request.Form),
|
||||
Body: testCase.Request.Body,
|
||||
}
|
||||
|
||||
resp := &Response{
|
||||
StatusCode: int32(testCase.Expect.StatusCode),
|
||||
Body: testCase.Expect.Body,
|
||||
Header: mapToPair(testCase.Expect.Header),
|
||||
BodyFieldsExpect: mapInterToPair(testCase.Expect.BodyFieldsExpect),
|
||||
Verify: testCase.Expect.Verify,
|
||||
Schema: testCase.Expect.Schema,
|
||||
}
|
||||
|
||||
reply = &TestCase{
|
||||
Name: testCase.Name,
|
||||
Request: req,
|
||||
Response: resp,
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *server) RunTestCase(ctx context.Context, in *TestCaseIdentity) (result *TestCaseResult, err error) {
|
||||
defer func() {
|
||||
s.loader.Reset()
|
||||
}()
|
||||
|
||||
var targetTestSuite *testing.TestSuite
|
||||
for s.loader.HasMore() {
|
||||
var data []byte
|
||||
if data, err = s.loader.Load(); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var testSuite *testing.TestSuite
|
||||
if testSuite, err = testing.Parse(data); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if testSuite.Name == in.Suite {
|
||||
targetTestSuite = testSuite
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if targetTestSuite != nil {
|
||||
var data []byte
|
||||
if data, err = yaml.Marshal(targetTestSuite); err == nil {
|
||||
task := &TestTask{
|
||||
Kind: "testcaseInSuite",
|
||||
Data: string(data),
|
||||
CaseName: in.Testcase,
|
||||
Level: "debug",
|
||||
}
|
||||
|
||||
var reply *HelloReply
|
||||
if reply, err = s.Run(ctx, task); err == nil {
|
||||
result = &TestCaseResult{
|
||||
Body: reply.Message,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mapInterToPair(data map[string]interface{}) (pairs []*Pair) {
|
||||
pairs = make([]*Pair, 0)
|
||||
for k, v := range data {
|
||||
pairs = append(pairs, &Pair{
|
||||
Key: k,
|
||||
Value: fmt.Sprintf("%v", v),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func mapToPair(data map[string]string) (pairs []*Pair) {
|
||||
pairs = make([]*Pair, 0)
|
||||
for k, v := range data {
|
||||
pairs = append(pairs, &Pair{
|
||||
Key: k,
|
||||
Value: v,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Sample returns a sample of the test task
|
||||
func (s *server) Sample(ctx context.Context, in *Empty) (reply *HelloReply, err error) {
|
||||
reply = &HelloReply{Message: sample.TestSuiteGitLab}
|
||||
|
|
|
@ -18,7 +18,9 @@ const (
|
|||
)
|
||||
|
||||
func TestRemoteServer(t *testing.T) {
|
||||
server := NewRemoteServer()
|
||||
loader := atesting.NewFileLoader()
|
||||
loader.Put("testdata/simple.yaml")
|
||||
server := NewRemoteServer(loader)
|
||||
_, err := server.Run(context.TODO(), &TestTask{
|
||||
Kind: "fake",
|
||||
})
|
||||
|
@ -66,6 +68,42 @@ func TestRemoteServer(t *testing.T) {
|
|||
ver, err = server.Sample(context.TODO(), &Empty{})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, sample.TestSuiteGitLab, ver.Message)
|
||||
|
||||
var suites *Suites
|
||||
suites, err = server.GetSuites(context.TODO(), &Empty{})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, suites, &Suites{Data: map[string]*Items{
|
||||
"simple": {
|
||||
Data: []string{"get", "query"},
|
||||
},
|
||||
}})
|
||||
|
||||
var testCase *TestCase
|
||||
testCase, err = server.GetTestCase(context.TODO(), &TestCaseIdentity{
|
||||
Suite: "simple",
|
||||
Testcase: "get",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "get", testCase.Name)
|
||||
assert.Equal(t, "http://foo", testCase.Request.Api)
|
||||
}
|
||||
|
||||
func TestRunTestCase(t *testing.T) {
|
||||
loader := atesting.NewFileLoader()
|
||||
loader.Put("testdata/simple.yaml")
|
||||
server := NewRemoteServer(loader)
|
||||
|
||||
defer gock.Clean()
|
||||
gock.New(urlFoo).Get("/").MatchHeader("key", "value").
|
||||
Reply(http.StatusOK).
|
||||
BodyString(`{"message": "hello"}`)
|
||||
|
||||
result, err := server.RunTestCase(context.TODO(), &TestCaseIdentity{
|
||||
Suite: "simple",
|
||||
Testcase: "get",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, result.Body, "start to run: 'get'\nstart to send request to http://foo\nresponse body:")
|
||||
}
|
||||
|
||||
func TestFindParentTestCases(t *testing.T) {
|
||||
|
@ -195,6 +233,11 @@ func TestWithDefaultValue(t *testing.T) {
|
|||
assert.Equal(t, withDefaultValue(map[string]string{"key": "val"}, map[string]string{"key": "value"}), map[string]string{"key": "val"})
|
||||
}
|
||||
|
||||
func TestMapInterToPair(t *testing.T) {
|
||||
assert.Equal(t, []*Pair{{Key: "key", Value: "val"}},
|
||||
mapInterToPair(map[string]interface{}{"key": "val"}))
|
||||
}
|
||||
|
||||
//go:embed testdata/simple.yaml
|
||||
var simpleSuite string
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,596 @@
|
|||
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
|
||||
// source: pkg/server/server.proto
|
||||
|
||||
/*
|
||||
Package server is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// Suppress "imported and not used" errors
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ status.Status
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
var _ = metadata.Join
|
||||
|
||||
func request_Runner_Run_0(ctx context.Context, marshaler runtime.Marshaler, client RunnerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq TestTask
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.Run(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Runner_Run_0(ctx context.Context, marshaler runtime.Marshaler, server RunnerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq TestTask
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.Run(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Runner_Sample_0(ctx context.Context, marshaler runtime.Marshaler, client RunnerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.Sample(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Runner_Sample_0(ctx context.Context, marshaler runtime.Marshaler, server RunnerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.Sample(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Runner_GetVersion_0(ctx context.Context, marshaler runtime.Marshaler, client RunnerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GetVersion(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Runner_GetVersion_0(ctx context.Context, marshaler runtime.Marshaler, server RunnerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GetVersion(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Runner_GetSuites_0(ctx context.Context, marshaler runtime.Marshaler, client RunnerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GetSuites(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Runner_GetSuites_0(ctx context.Context, marshaler runtime.Marshaler, server RunnerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq Empty
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GetSuites(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Runner_RunTestCase_0(ctx context.Context, marshaler runtime.Marshaler, client RunnerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq TestCaseIdentity
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.RunTestCase(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Runner_RunTestCase_0(ctx context.Context, marshaler runtime.Marshaler, server RunnerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq TestCaseIdentity
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.RunTestCase(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Runner_GetTestCase_0(ctx context.Context, marshaler runtime.Marshaler, client RunnerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq TestCaseIdentity
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := client.GetTestCase(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Runner_GetTestCase_0(ctx context.Context, marshaler runtime.Marshaler, server RunnerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq TestCaseIdentity
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
msg, err := server.GetTestCase(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterRunnerHandlerServer registers the http handlers for service Runner to "mux".
|
||||
// UnaryRPC :call RunnerServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterRunnerHandlerFromEndpoint instead.
|
||||
func RegisterRunnerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server RunnerServer) error {
|
||||
|
||||
mux.Handle("POST", pattern_Runner_Run_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/server.Runner/Run", runtime.WithHTTPPathPattern("/server.Runner/Run"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Runner_Run_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_Run_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_Sample_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/server.Runner/Sample", runtime.WithHTTPPathPattern("/server.Runner/Sample"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Runner_Sample_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_Sample_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_GetVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/server.Runner/GetVersion", runtime.WithHTTPPathPattern("/server.Runner/GetVersion"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Runner_GetVersion_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_GetVersion_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_GetSuites_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/server.Runner/GetSuites", runtime.WithHTTPPathPattern("/server.Runner/GetSuites"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Runner_GetSuites_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_GetSuites_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_RunTestCase_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/server.Runner/RunTestCase", runtime.WithHTTPPathPattern("/server.Runner/RunTestCase"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Runner_RunTestCase_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_RunTestCase_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_GetTestCase_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/server.Runner/GetTestCase", runtime.WithHTTPPathPattern("/server.Runner/GetTestCase"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Runner_GetTestCase_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_GetTestCase_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterRunnerHandlerFromEndpoint is same as RegisterRunnerHandler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func RegisterRunnerHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.DialContext(ctx, endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return RegisterRunnerHandler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// RegisterRunnerHandler registers the http handlers for service Runner to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func RegisterRunnerHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
return RegisterRunnerHandlerClient(ctx, mux, NewRunnerClient(conn))
|
||||
}
|
||||
|
||||
// RegisterRunnerHandlerClient registers the http handlers for service Runner
|
||||
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "RunnerClient".
|
||||
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "RunnerClient"
|
||||
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
|
||||
// "RunnerClient" to call the correct interceptors.
|
||||
func RegisterRunnerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client RunnerClient) error {
|
||||
|
||||
mux.Handle("POST", pattern_Runner_Run_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/server.Runner/Run", runtime.WithHTTPPathPattern("/server.Runner/Run"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Runner_Run_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_Run_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_Sample_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/server.Runner/Sample", runtime.WithHTTPPathPattern("/server.Runner/Sample"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Runner_Sample_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_Sample_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_GetVersion_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/server.Runner/GetVersion", runtime.WithHTTPPathPattern("/server.Runner/GetVersion"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Runner_GetVersion_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_GetVersion_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_GetSuites_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/server.Runner/GetSuites", runtime.WithHTTPPathPattern("/server.Runner/GetSuites"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Runner_GetSuites_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_GetSuites_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_RunTestCase_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/server.Runner/RunTestCase", runtime.WithHTTPPathPattern("/server.Runner/RunTestCase"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Runner_RunTestCase_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_RunTestCase_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_Runner_GetTestCase_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
var err error
|
||||
var annotatedContext context.Context
|
||||
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/server.Runner/GetTestCase", runtime.WithHTTPPathPattern("/server.Runner/GetTestCase"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Runner_GetTestCase_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Runner_GetTestCase_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_Runner_Run_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "Run"}, ""))
|
||||
|
||||
pattern_Runner_Sample_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "Sample"}, ""))
|
||||
|
||||
pattern_Runner_GetVersion_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "GetVersion"}, ""))
|
||||
|
||||
pattern_Runner_GetSuites_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "GetSuites"}, ""))
|
||||
|
||||
pattern_Runner_RunTestCase_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "RunTestCase"}, ""))
|
||||
|
||||
pattern_Runner_GetTestCase_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"server.Runner", "GetTestCase"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_Runner_Run_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Runner_Sample_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Runner_GetVersion_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Runner_GetSuites_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Runner_RunTestCase_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Runner_GetTestCase_0 = runtime.ForwardResponseMessage
|
||||
)
|
|
@ -8,6 +8,22 @@ service Runner {
|
|||
rpc Run (TestTask) returns (HelloReply) {}
|
||||
rpc Sample(Empty) returns (HelloReply) {}
|
||||
rpc GetVersion(Empty) returns (HelloReply) {}
|
||||
rpc GetSuites(Empty) returns (Suites) {}
|
||||
rpc RunTestCase(TestCaseIdentity) returns (TestCaseResult) {}
|
||||
rpc GetTestCase(TestCaseIdentity) returns (TestCase) {}
|
||||
}
|
||||
|
||||
message Suites {
|
||||
map<string, Items> data = 1;
|
||||
}
|
||||
|
||||
message Items {
|
||||
repeated string data = 1;
|
||||
}
|
||||
|
||||
message TestCaseIdentity {
|
||||
string suite = 1;
|
||||
string testcase = 2;
|
||||
}
|
||||
|
||||
message TestTask {
|
||||
|
@ -23,5 +39,46 @@ message HelloReply {
|
|||
string error = 2;
|
||||
}
|
||||
|
||||
message Suite {
|
||||
string name = 1;
|
||||
string api = 2;
|
||||
repeated TestCase items = 3;
|
||||
}
|
||||
|
||||
message TestCase {
|
||||
string name = 1;
|
||||
Request request = 2;
|
||||
Response response = 3;
|
||||
}
|
||||
|
||||
message Request {
|
||||
string api = 1;
|
||||
string method = 2;
|
||||
repeated Pair header = 3;
|
||||
repeated Pair query = 4;
|
||||
repeated Pair form = 5;
|
||||
string body = 6;
|
||||
}
|
||||
|
||||
message TestCaseResult {
|
||||
int32 statusCode = 1;
|
||||
string body = 2;
|
||||
repeated Pair header = 3;
|
||||
}
|
||||
|
||||
message Response {
|
||||
int32 statusCode = 1;
|
||||
string body = 2;
|
||||
repeated Pair header = 3;
|
||||
repeated Pair bodyFieldsExpect = 4;
|
||||
repeated string verify = 5;
|
||||
string schema = 6;
|
||||
}
|
||||
|
||||
message Pair {
|
||||
string key = 1;
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
message Empty {
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.12.4
|
||||
// - protoc v4.22.2
|
||||
// source: pkg/server/server.proto
|
||||
|
||||
package server
|
||||
|
@ -25,6 +25,9 @@ type RunnerClient interface {
|
|||
Run(ctx context.Context, in *TestTask, opts ...grpc.CallOption) (*HelloReply, error)
|
||||
Sample(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error)
|
||||
GetVersion(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*HelloReply, error)
|
||||
GetSuites(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Suites, error)
|
||||
RunTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCaseResult, error)
|
||||
GetTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCase, error)
|
||||
}
|
||||
|
||||
type runnerClient struct {
|
||||
|
@ -62,6 +65,33 @@ func (c *runnerClient) GetVersion(ctx context.Context, in *Empty, opts ...grpc.C
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *runnerClient) GetSuites(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Suites, error) {
|
||||
out := new(Suites)
|
||||
err := c.cc.Invoke(ctx, "/server.Runner/GetSuites", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *runnerClient) RunTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCaseResult, error) {
|
||||
out := new(TestCaseResult)
|
||||
err := c.cc.Invoke(ctx, "/server.Runner/RunTestCase", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *runnerClient) GetTestCase(ctx context.Context, in *TestCaseIdentity, opts ...grpc.CallOption) (*TestCase, error) {
|
||||
out := new(TestCase)
|
||||
err := c.cc.Invoke(ctx, "/server.Runner/GetTestCase", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// RunnerServer is the server API for Runner service.
|
||||
// All implementations must embed UnimplementedRunnerServer
|
||||
// for forward compatibility
|
||||
|
@ -69,6 +99,9 @@ type RunnerServer interface {
|
|||
Run(context.Context, *TestTask) (*HelloReply, error)
|
||||
Sample(context.Context, *Empty) (*HelloReply, error)
|
||||
GetVersion(context.Context, *Empty) (*HelloReply, error)
|
||||
GetSuites(context.Context, *Empty) (*Suites, error)
|
||||
RunTestCase(context.Context, *TestCaseIdentity) (*TestCaseResult, error)
|
||||
GetTestCase(context.Context, *TestCaseIdentity) (*TestCase, error)
|
||||
mustEmbedUnimplementedRunnerServer()
|
||||
}
|
||||
|
||||
|
@ -85,6 +118,15 @@ func (UnimplementedRunnerServer) Sample(context.Context, *Empty) (*HelloReply, e
|
|||
func (UnimplementedRunnerServer) GetVersion(context.Context, *Empty) (*HelloReply, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented")
|
||||
}
|
||||
func (UnimplementedRunnerServer) GetSuites(context.Context, *Empty) (*Suites, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetSuites not implemented")
|
||||
}
|
||||
func (UnimplementedRunnerServer) RunTestCase(context.Context, *TestCaseIdentity) (*TestCaseResult, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RunTestCase not implemented")
|
||||
}
|
||||
func (UnimplementedRunnerServer) GetTestCase(context.Context, *TestCaseIdentity) (*TestCase, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetTestCase not implemented")
|
||||
}
|
||||
func (UnimplementedRunnerServer) mustEmbedUnimplementedRunnerServer() {}
|
||||
|
||||
// UnsafeRunnerServer may be embedded to opt out of forward compatibility for this service.
|
||||
|
@ -152,6 +194,60 @@ func _Runner_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(i
|
|||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Runner_GetSuites_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RunnerServer).GetSuites(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/server.Runner/GetSuites",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RunnerServer).GetSuites(ctx, req.(*Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Runner_RunTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TestCaseIdentity)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RunnerServer).RunTestCase(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/server.Runner/RunTestCase",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RunnerServer).RunTestCase(ctx, req.(*TestCaseIdentity))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Runner_GetTestCase_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TestCaseIdentity)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RunnerServer).GetTestCase(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/server.Runner/GetTestCase",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RunnerServer).GetTestCase(ctx, req.(*TestCaseIdentity))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// Runner_ServiceDesc is the grpc.ServiceDesc for Runner service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
|
@ -171,6 +267,18 @@ var Runner_ServiceDesc = grpc.ServiceDesc{
|
|||
MethodName: "GetVersion",
|
||||
Handler: _Runner_GetVersion_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetSuites",
|
||||
Handler: _Runner_GetSuites_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "RunTestCase",
|
||||
Handler: _Runner_RunTestCase_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetTestCase",
|
||||
Handler: _Runner_GetTestCase_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "pkg/server/server.proto",
|
||||
|
|
|
@ -4,6 +4,8 @@ items:
|
|||
- name: get
|
||||
request:
|
||||
api: http://foo
|
||||
header:
|
||||
key: value
|
||||
- name: query
|
||||
request:
|
||||
api: /
|
|
@ -7,4 +7,5 @@ type Loader interface {
|
|||
Put(string) (err error)
|
||||
GetContext() string
|
||||
GetCount() int
|
||||
Reset()
|
||||
}
|
||||
|
|
|
@ -50,3 +50,8 @@ func (l *fileLoader) GetContext() string {
|
|||
func (l *fileLoader) GetCount() int {
|
||||
return len(l.paths)
|
||||
}
|
||||
|
||||
// Reset resets the index
|
||||
func (l *fileLoader) Reset() {
|
||||
l.index = -1
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ func TestFileLoader(t *testing.T) {
|
|||
items: []string{},
|
||||
verify: func(t *testing.T, loader atest.Loader) {
|
||||
assert.False(t, loader.HasMore())
|
||||
assert.Empty(t, loader.GetCount())
|
||||
assert.Equal(t, 0, loader.GetCount())
|
||||
},
|
||||
}, {
|
||||
name: "brace expansion path",
|
||||
|
@ -53,4 +53,6 @@ func defaultVerify(t *testing.T, loader atest.Loader) {
|
|||
assert.Equal(t, "testdata", loader.GetContext())
|
||||
|
||||
assert.False(t, loader.HasMore())
|
||||
loader.Reset()
|
||||
assert.True(t, loader.HasMore())
|
||||
}
|
||||
|
|
|
@ -62,6 +62,13 @@ func TestDuplicatedNames(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestRequestRender(t *testing.T) {
|
||||
validMap := map[string]string{
|
||||
"key": "{{.Name}}",
|
||||
}
|
||||
invalidMap := map[string]string{
|
||||
"key": "{{.name}}",
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
request *atest.Request
|
||||
|
@ -136,12 +143,26 @@ func TestRequestRender(t *testing.T) {
|
|||
},
|
||||
ctx: atest.TestCase{},
|
||||
hasErr: true,
|
||||
}, {
|
||||
name: "failed with header render",
|
||||
request: &atest.Request{
|
||||
Header: map[string]string{
|
||||
"key": "{{.name}}",
|
||||
},
|
||||
},
|
||||
ctx: atest.TestCase{},
|
||||
hasErr: true,
|
||||
}, {
|
||||
name: "failed with form render",
|
||||
request: &atest.Request{
|
||||
Form: invalidMap,
|
||||
},
|
||||
ctx: atest.TestCase{},
|
||||
hasErr: true,
|
||||
}, {
|
||||
name: "form render",
|
||||
request: &atest.Request{
|
||||
Form: map[string]string{
|
||||
"key": "{{.Name}}",
|
||||
},
|
||||
Form: validMap,
|
||||
},
|
||||
ctx: atest.TestCase{Name: "linuxsuren"},
|
||||
verify: func(t *testing.T, req *atest.Request) {
|
||||
|
@ -151,9 +172,7 @@ func TestRequestRender(t *testing.T) {
|
|||
}, {
|
||||
name: "header render",
|
||||
request: &atest.Request{
|
||||
Header: map[string]string{
|
||||
"key": "{{.Name}}",
|
||||
},
|
||||
Header: validMap,
|
||||
},
|
||||
ctx: atest.TestCase{Name: "linuxsuren"},
|
||||
verify: func(t *testing.T, req *atest.Request) {
|
||||
|
|
Loading…
Reference in New Issue