diff --git a/console/atest-ui/src/App.vue b/console/atest-ui/src/App.vue index bac998bf..2b0fdead 100644 --- a/console/atest-ui/src/App.vue +++ b/console/atest-ui/src/App.vue @@ -46,7 +46,7 @@ API.GetVersion((d) => { }) const sideWidth = ref("width: 200px; display: flex;flex-direction: column;") -const isCollapse = ref(false) +const isCollapse = ref(true) watch(isCollapse, (e) => { if (e) { sideWidth.value = "width: 80px; display: flex;flex-direction: column;" diff --git a/console/atest-ui/src/views/TestCase.vue b/console/atest-ui/src/views/TestCase.vue index b727b770..cc7ffb96 100644 --- a/console/atest-ui/src/views/TestCase.vue +++ b/console/atest-ui/src/views/TestCase.vue @@ -437,7 +437,7 @@ function formChange() { } } -const bodyType = ref(5) +const bodyType = ref(1) function bodyTypeChange(e: number) { let contentType = "" switch (e) { diff --git a/e2e/compose.yaml b/e2e/compose.yaml index 2d61fc65..4f114ffb 100644 --- a/e2e/compose.yaml +++ b/e2e/compose.yaml @@ -33,7 +33,7 @@ services: # - minio - postgres etcd: - image: "bitnami/etcd:3.5.10" + image: "ghcr.io/linuxsuren/bitnami/etcd:3.5.10" expose: - "2379" environment: @@ -45,7 +45,7 @@ services: retries: 10 start_period: 3s mysql: - image: mysql:8.2.0 + image: ghcr.io/linuxsuren/library/mysql:8.2.0 command: --default-authentication-plugin=mysql_native_password environment: MYSQL_ROOT_PASSWORD: root @@ -57,7 +57,7 @@ services: retries: 10 start_period: 3s mariadb: - image: mariadb:11.0 + image: ghcr.io/linuxsuren/library/mariadb:11.0 environment: MARIADB_ROOT_PASSWORD: root MARIADB_DATABASE: atest @@ -68,14 +68,14 @@ services: retries: 10 start_period: 3s minio: - image: bitnami/minio:2023.11.6 + image: ghcr.io/linuxsuren/bitnami/minio:2023.11.6 environment: MINIO_ROOT_USER: root MINIO_ROOT_PASSWORD: root MINIO_SERVER_HOST: minio MINIO_DEFAULT_BUCKETS: bucket mongo: - image: mongo + image: ghcr.io/linuxsuren/library/mongo:7.0.12 healthcheck: test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/27017"] interval: 3s @@ -86,7 +86,7 @@ services: MONGO_INITDB_ROOT_USERNAME: root MONGO_INITDB_ROOT_PASSWORD: root postgres: - image: postgres:16.0 + image: ghcr.io/linuxsuren/library/postgres:16.0 environment: POSTGRES_USER: root POSTGRES_PASSWORD: root diff --git a/pkg/runner/http.go b/pkg/runner/http.go index 1961b0ff..47a5e042 100644 --- a/pkg/runner/http.go +++ b/pkg/runner/http.go @@ -72,8 +72,9 @@ func (r ReportResultSlice) Swap(i, j int) { type simpleTestCaseRunner struct { UnimplementedRunner - simpleResponse SimpleResponse - cookies []*http.Cookie + simpleResponse SimpleResponse + cookies []*http.Cookie + apiSuggestLimit int } // NewSimpleTestCaseRunner creates the instance of the simple test case runner @@ -82,6 +83,7 @@ func NewSimpleTestCaseRunner() TestCaseRunner { UnimplementedRunner: NewDefaultUnimplementedRunner(), simpleResponse: SimpleResponse{}, cookies: []*http.Cookie{}, + apiSuggestLimit: 10, } return runner } @@ -234,7 +236,6 @@ func (r *simpleTestCaseRunner) GetSuggestedAPIs(suite *testing.TestSuite, api st var swagger *spec.Swagger if swagger, err = apispec.ParseURLToSwagger(suite.Spec.URL); err == nil && swagger != nil { - result = []*testing.TestCase{} swaggerAPI := apispec.NewSwaggerAPI(swagger) for api, methods := range swaggerAPI.ApiMap { for _, method := range methods { @@ -267,6 +268,9 @@ func (r *simpleTestCaseRunner) GetSuggestedAPIs(suite *testing.TestSuite, api st testcase.Name = swagger.Paths.Paths[api].Patch.ID } result = append(result, testcase) + if len(result) >= r.apiSuggestLimit { + return + } } } } @@ -303,8 +307,9 @@ func (r *simpleTestCaseRunner) withResponseRecord(resp *http.Response) (response func (r *simpleTestCaseRunner) GetResponseRecord() SimpleResponse { return r.simpleResponse } -func (s *simpleTestCaseRunner) WithSuite(suite *testing.TestSuite) { - // not need this parameter + +func (r *simpleTestCaseRunner) WithAPISuggestLimit(limit int) { + r.apiSuggestLimit = limit } func expectInt(name string, expect, actual int) (err error) { diff --git a/pkg/runner/http_test.go b/pkg/runner/http_test.go index 816f0e7a..168ceb62 100644 --- a/pkg/runner/http_test.go +++ b/pkg/runner/http_test.go @@ -541,6 +541,7 @@ func TestBodyFiledsVerify(t *testing.T) { func TestGetSuggestedAPIs(t *testing.T) { runner := NewSimpleTestCaseRunner() runner.WithSuite(nil) + runner.WithAPISuggestLimit(6) // not a swagger result, err := runner.GetSuggestedAPIs(&atest.TestSuite{}, "") assert.NoError(t, err, err) diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 8e21f89c..9b1197ca 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -35,6 +35,7 @@ type TestCaseRunner interface { WithTestReporter(TestReporter) WithExecer(fakeruntime.Execer) WithSuite(*testing.TestSuite) + WithAPISuggestLimit(int) } // HTTPResponseRecord represents a http response record @@ -107,3 +108,11 @@ func (r *UnimplementedRunner) GetSuggestedAPIs(suite *testing.TestSuite, api str // empty implement return } + +func (r *UnimplementedRunner) WithAPISuggestLimit(int) { + // empty implement +} + +func (s *UnimplementedRunner) WithSuite(suite *testing.TestSuite) { + // empty implement +} diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index 8a383c2b..4223afbe 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -1,5 +1,5 @@ /* -Copyright 2023 API Testing Authors. +Copyright 2023-2024 API Testing Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,3 +30,20 @@ func TestRunnerFactory(t *testing.T) { runner = GetTestSuiteRunner(&atest.TestSuite{Spec: atest.APISpec{Kind: "grpc", RPC: &atest.RPCDesc{}}}) assert.IsType(t, NewGRPCTestCaseRunner("", atest.RPCDesc{}), runner) } + +func TestUnimplementedRunner(t *testing.T) { + runner := NewDefaultUnimplementedRunner() + output, err := runner.RunTestCase(&atest.TestCase{}, nil, nil) + assert.Nil(t, output) + assert.Error(t, err) + + runner.WithWriteLevel("debug") + runner.WithTestReporter(nil) + + var results []*atest.TestCase + results, err = runner.GetSuggestedAPIs(nil, "") + assert.Nil(t, results) + assert.NoError(t, err) + + runner.WithAPISuggestLimit(0) +} diff --git a/pkg/runner/testdata/swagger.json b/pkg/runner/testdata/swagger.json index 302290ce..29f15020 100644 --- a/pkg/runner/testdata/swagger.json +++ b/pkg/runner/testdata/swagger.json @@ -61,6 +61,12 @@ "summary": "summary", "operationId": "patchUser" } + }, + "/api/v1/groups/{group}": { + "get": { + "summary": "summary", + "operationId": "getGroup" + } } }, "components": { diff --git a/pkg/server/remote_runner.go b/pkg/server/remote_runner.go index bb34bb5e..f5fe5ca3 100644 --- a/pkg/server/remote_runner.go +++ b/pkg/server/remote_runner.go @@ -66,6 +66,8 @@ func (s *remoteRunnerAdapter) WithExecer(fakeruntime.Execer) { func (s *remoteRunnerAdapter) WithSuite(suite *testing.TestSuite) { s.suite = suite } +func (s *remoteRunnerAdapter) WithAPISuggestLimit(limit int) { +} func init() { env := os.Environ() diff --git a/pkg/server/remote_server_test.go b/pkg/server/remote_server_test.go index a0d2fb77..dd4c7d9b 100644 --- a/pkg/server/remote_server_test.go +++ b/pkg/server/remote_server_test.go @@ -919,6 +919,20 @@ func TestFakeSecretServer(t *testing.T) { assert.Error(t, err) } +func TestRemoteRunnerAdapter(t *testing.T) { + runner := &remoteRunnerAdapter{} + runner.GetSuggestedAPIs(nil, "") + runner.WithSecure(nil) + runner.WithOutputWriter(nil) + runner.WithWriteLevel("debug") + runner.WithTestReporter(nil) + runner.WithExecer(nil) + runner.WithSuite(nil) + runner.WithAPISuggestLimit(0) + _, err := runner.RunTestCase(nil, nil, nil) + assert.Error(t, err) +} + func getRemoteServerInTempDir() (server RunnerServer, call func()) { dir, _ := os.MkdirTemp(os.TempDir(), "remote-server-test") call = func() { os.RemoveAll(dir) } diff --git a/pkg/testing/case.go b/pkg/testing/case.go index 63612e8e..aaecc9bb 100644 --- a/pkg/testing/case.go +++ b/pkg/testing/case.go @@ -197,6 +197,8 @@ func (m SortedKeysStringMap) GetValue(key string) string { case map[string]interface{}: verifier := convertToVerifier(o) return verifier.Value + case *Verifier: + return o.Value } return "" diff --git a/pkg/testing/case_test.go b/pkg/testing/case_test.go index d7de5795..d278b37f 100644 --- a/pkg/testing/case_test.go +++ b/pkg/testing/case_test.go @@ -1,5 +1,5 @@ /* -Copyright 2023 API Testing Authors. +Copyright 2023-2024 API Testing Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -54,3 +54,34 @@ body: assert.Nil(t, err) assert.Equal(t, "plain", req.Body.String()) } + +func TestResponse(t *testing.T) { + resp := &atesting.Response{ + Body: "body", + BodyFieldsExpect: map[string]interface{}{ + "name": "rick", + }, + } + assert.Equal(t, "body", resp.GetBody()) + assert.Equal(t, map[string]interface{}{"name": "rick"}, resp.GetBodyFieldsExpect()) +} + +func TestSortedKeysStringMap(t *testing.T) { + obj := atesting.SortedKeysStringMap{ + "c": "d", + "f": map[string]interface{}{ + "value": "f", + }, + "e": &atesting.Verifier{ + Value: "e", + }, + "a": "b", + } + assert.Equal(t, []string{"a", "c", "e", "f"}, obj.Keys()) + assert.Equal(t, "b", obj.GetValue("a")) + assert.Nil(t, obj.GetVerifier("b")) + assert.Equal(t, "e", obj.GetValue("e")) + assert.Equal(t, "f", obj.GetValue("f")) + assert.Equal(t, "f", obj.GetVerifier("f").Value) + assert.Empty(t,obj.GetValue("not-found")) +} diff --git a/pkg/testing/loader_non_test.go b/pkg/testing/loader_non_test.go new file mode 100644 index 00000000..33a6bbf1 --- /dev/null +++ b/pkg/testing/loader_non_test.go @@ -0,0 +1,82 @@ +/* +Copyright 2024 API Testing Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package testing_test + +import ( + "testing" + + atest "github.com/linuxsuren/api-testing/pkg/testing" + "github.com/stretchr/testify/assert" +) + +func TestNonLoader(t *testing.T) { + loader := atest.NewNonWriter() + defer loader.Close() + + assert.False(t, loader.HasMore()) + + data, err := loader.Load() + assert.NoError(t, err) + assert.Nil(t, data) + + assert.NoError(t, loader.Put("")) + assert.Empty(t, loader.GetContext()) + assert.Equal(t, 0, loader.GetCount()) + + loader.Reset() + + var suites []atest.TestSuite + suites, err = loader.ListTestSuite() + assert.NoError(t, err) + assert.Empty(t, suites) + + _, err = loader.GetTestSuite("test", false) + assert.NoError(t, err) + + assert.NoError(t, loader.CreateSuite("", "")) + + var suite *atest.TestSuite + var absPath string + suite, absPath, err = loader.GetSuite("test") + assert.NoError(t, err) + assert.Nil(t, suite) + assert.Empty(t, absPath) + + assert.NoError(t, loader.UpdateSuite(atest.TestSuite{})) + assert.NoError(t, loader.DeleteSuite("")) + + var testCases []atest.TestCase + testCases, err = loader.ListTestCase("") + assert.NoError(t, err) + assert.Empty(t, testCases) + + data, err = loader.GetTestSuiteYaml("") + assert.NoError(t, err) + assert.Nil(t, data) + + _, err = loader.GetTestCase("", "") + assert.NoError(t, err) + assert.NoError(t, loader.CreateTestCase("", atest.TestCase{})) + assert.NoError(t, loader.UpdateTestCase("", atest.TestCase{})) + assert.NoError(t, loader.DeleteTestCase("", "")) + + var readonly bool + readonly, err = loader.Verify() + assert.NoError(t, err) + assert.False(t, readonly) + assert.Empty(t, loader.PProf("")) +} diff --git a/pkg/testing/store.go b/pkg/testing/store.go index 5e2d6703..3faa1727 100644 --- a/pkg/testing/store.go +++ b/pkg/testing/store.go @@ -139,9 +139,6 @@ func (s *storeFactory) GetStores() (stores []Store, err error) { func (s *storeFactory) GetStoresByOwner(owner string) (stores []Store, err error) { var all []Store all, err = s.GetStores() - if owner == "" { - return all, err - } if err == nil { for _, item := range all { if item.Owner != owner { diff --git a/pkg/testing/store_test.go b/pkg/testing/store_test.go index 7b43cb57..7af2f016 100644 --- a/pkg/testing/store_test.go +++ b/pkg/testing/store_test.go @@ -1,25 +1,17 @@ -/** -MIT License - -Copyright (c) 2023 Rick - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +/* +Copyright 2023-2024 API Testing Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ package testing @@ -77,10 +69,21 @@ func TestStoreFactory(t *testing.T) { t.Run("GetAllStores", func(t *testing.T) { stores, err := factory.GetStores() assert.Nil(t, err) - assert.Equal(t, 1, len(stores)) + assert.Equal(t, 2, len(stores)) assert.Equal(t, "db", stores[0].Name) }) + t.Run("Get stores by owner", func(t *testing.T) { + stores, err := factory.GetStoresByOwner("rick") + assert.NoError(t, err) + assert.Len(t, stores, 1) + assert.Equal(t, "git", stores[0].Name) + + stores, err = factory.GetStoresByOwner("fake") + assert.NoError(t, err) + assert.Len(t, stores, 0) + }) + t.Run("DeleteStore", func(t *testing.T) { err := factory.DeleteStore("") assert.NoError(t, err) diff --git a/pkg/testing/testdata/stores.yaml b/pkg/testing/testdata/stores.yaml index 443fdb9e..a21fff25 100644 --- a/pkg/testing/testdata/stores.yaml +++ b/pkg/testing/testdata/stores.yaml @@ -13,6 +13,19 @@ stores: disabled: false properties: database: test + - name: git + owner: rick + kind: + name: "" + url: "" + enabled: false + description: "" + url: "" + username: "" + password: "" + readonly: false + disabled: false + properties: {} plugins: - name: database url: localhost:7071