This is an automated email from the ASF dual-hosted git repository.

ka94 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new 0e93aa117 test: Support manual e2e testing (#5085)
0e93aa117 is described below

commit 0e93aa1175b236feebd3728edd18012546241746
Author: Keon Amini <[email protected]>
AuthorDate: Mon Jun 12 14:28:28 2023 -0500

    test: Support manual e2e testing (#5085)
---
 backend/Makefile                                   |   2 +-
 backend/test/e2e/manual/.gitignore                 |   1 +
 backend/test/e2e/manual/Readme.md                  |  44 ++++++
 backend/test/e2e/manual/azuredevops/azure_test.go  | 146 ++++++++++++++++++
 backend/test/e2e/manual/azuredevops/models.go      |  67 +++++++++
 backend/test/e2e/manual/gitlab/gitlab_test.go      | 155 +++++++++++++++++++
 backend/test/e2e/manual/gitlab/models.go           |  23 +++
 backend/test/e2e/manual/pagerduty/models.go        |  26 ++++
 .../test/e2e/manual/pagerduty/pagerduty_test.go    | 164 +++++++++++++++++++++
 backend/test/e2e/remote/helper.go                  |   2 +-
 backend/test/helper/api.go                         |   2 +-
 backend/test/helper/client.go                      |  14 +-
 backend/test/helper/models.go                      |  10 ++
 backend/test/helper/utils.go                       |  10 ++
 14 files changed, 656 insertions(+), 10 deletions(-)

diff --git a/backend/Makefile b/backend/Makefile
index 0dec2a7ee..01d1f343d 100644
--- a/backend/Makefile
+++ b/backend/Makefile
@@ -115,7 +115,7 @@ e2e-test:
        set -e;\
        go run ./test/init.go || exit $$?;\
        exit_code=0;\
-       for m in $$(go list ./test/e2e/...); do \
+       for m in $$(go list ./test/e2e/... | grep -v manual/); do \
                echo $$m; go test -p 1 -timeout 300s -v $$m || exit_code=$$?; \
        done; \
        exit $$exit_code
diff --git a/backend/test/e2e/manual/.gitignore 
b/backend/test/e2e/manual/.gitignore
new file mode 100644
index 000000000..606921f2f
--- /dev/null
+++ b/backend/test/e2e/manual/.gitignore
@@ -0,0 +1 @@
+*_local_test.go
\ No newline at end of file
diff --git a/backend/test/e2e/manual/Readme.md 
b/backend/test/e2e/manual/Readme.md
new file mode 100644
index 000000000..715fbc468
--- /dev/null
+++ b/backend/test/e2e/manual/Readme.md
@@ -0,0 +1,44 @@
+Tests in this directory are not meant to be run by CICD automation, but rather 
manually by developers on their machines.
+They serve as workflow tests and mimic the sequence of actions that would be 
performed via the UI. These
+tests will typically connect to real data-sources, so any data-source specific 
data/credential needs to be supplied
+externally. The convention we are using is to wrap all such variables in a 
Config struct, placed in a `models.go` file,
+which is loaded in at runtime. Populating these structs and making them 
available to the tests will be your responsibility.
+See the example below.
+
+You can also add your own manual tests by having the test files follow the 
pattern *_local_test.go to exclude them
+from git's tracking.
+
+Example:
+
+In `models.go` define
+```go
+package azuredevops
+
+    type TestConfig struct {
+        Org     string
+        Project string
+        Token   string
+    }
+```
+
+and load it into your test function (if you write one) via
+```go
+    cfg := helper.GetTestConfig[TestConfig]()
+```
+
+In `azure_local_test.go` (or any git-ignorable file) you write your setup.
+```go
+package azuredevops
+
+import "github.com/apache/incubator-devlake/test/helper"
+
+func init() {
+       helper.SetTestConfig(TestConfig{
+               Org:     "???",
+               Project: "???",
+               Token:   "??????",
+       })
+}
+
+// Your custom test cases (optional)
+```
\ No newline at end of file
diff --git a/backend/test/e2e/manual/azuredevops/azure_test.go 
b/backend/test/e2e/manual/azuredevops/azure_test.go
new file mode 100644
index 000000000..613a97e04
--- /dev/null
+++ b/backend/test/e2e/manual/azuredevops/azure_test.go
@@ -0,0 +1,146 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 azuredevops
+
+import (
+       "fmt"
+       "github.com/apache/incubator-devlake/core/config"
+       "github.com/apache/incubator-devlake/core/models"
+       "github.com/apache/incubator-devlake/core/models/common"
+       "github.com/apache/incubator-devlake/core/plugin"
+       gitextractor 
"github.com/apache/incubator-devlake/plugins/gitextractor/impl"
+       "github.com/apache/incubator-devlake/test/helper"
+       "github.com/stretchr/testify/require"
+       "testing"
+       "time"
+)
+
+const (
+       azurePlugin = "azuredevops"
+)
+
+func TestAzure(t *testing.T) {
+       cfg := helper.GetTestConfig[TestConfig]()
+       client := helper.ConnectLocalServer(t, &helper.LocalClientConfig{
+               ServerPort:   8089,
+               DbURL:        config.GetConfig().GetString("E2E_DB_URL"),
+               CreateServer: true,
+               DropDb:       false,
+               TruncateDb:   true,
+               Plugins: map[string]plugin.PluginMeta{
+                       "gitextractor": gitextractor.GitExtractor{},
+               },
+       })
+       client.SetTimeout(60 * time.Second)
+       // Wait for plugin registration
+       time.Sleep(5 * time.Second)
+       fmt.Println("Create new connection")
+       connection := client.CreateConnection(azurePlugin,
+               AzureConnection{
+                       Name:         "azure_conn",
+                       Token:        cfg.Token,
+                       Organization: cfg.Org,
+               },
+       )
+       client.SetTimeout(0)
+       client.SetPipelineTimeout(0)
+       conns := client.ListConnections(azurePlugin)
+       require.Greater(t, len(conns), 0)
+       t.Run("v200-plugin", func(t *testing.T) {
+               outputProject := client.CreateProject(&helper.ProjectConfig{
+                       ProjectName: "project-1",
+                       EnableDora:  true,
+               })
+               projects := client.ListProjects()
+               require.Equal(t, 1, len(projects.Projects))
+               project := projects.Projects[0]
+               repoConfig := 
helper.Cast[AzureGitRepositoryConfig](client.CreateScopeConfig(azurePlugin, 
connection.ID,
+                       AzureGitRepositoryConfig{
+                               ScopeConfig: common.ScopeConfig{
+                                       Entities: []string{
+                                               plugin.DOMAIN_TYPE_CICD,
+                                               plugin.DOMAIN_TYPE_CODE,
+                                               plugin.DOMAIN_TYPE_CODE_REVIEW,
+                                       },
+                               },
+                               Refdiff: Refdiff{
+                                       TagsPattern: ".*",
+                                       TagsLimit:   1,
+                                       TagsOrder:   "",
+                               },
+                               DeploymentPattern: ".*",
+                               ProductionPattern: ".*",
+                       },
+               ))
+               _ = repoConfig
+               remoteScopes := client.RemoteScopes(helper.RemoteScopesQuery{
+                       PluginName:   azurePlugin,
+                       ConnectionId: connection.ID,
+                       GroupId:      fmt.Sprintf("%s/%s", cfg.Org, 
cfg.Project),
+                       PageToken:    "",
+                       Params:       nil,
+               })
+               scopes := 
helper.Cast[[]AzureGitRepo](client.CreateScopes(azurePlugin, connection.ID, 
remoteScopesToScopes(remoteScopes, cfg.Repos)...))
+               scopesCount := len(scopes)
+               scopesResponse := client.ListScopes(azurePlugin, connection.ID, 
false)
+               require.Equal(t, scopesCount, len(scopesResponse))
+               // associate scopes with the scope config
+               for _, scope := range scopes {
+                       scope.ScopeConfigId = repoConfig.ID
+                       scope = 
helper.Cast[AzureGitRepo](client.UpdateScope(azurePlugin, connection.ID, 
scope.Id, scope))
+                       require.Equal(t, repoConfig.ID, scope.ScopeConfigId)
+               }
+               // create bp_scopes from the scopes
+               var bpScopes []*plugin.BlueprintScopeV200
+               for _, scope := range scopes {
+                       bpScopes = append(bpScopes, &plugin.BlueprintScopeV200{
+                               Id:   scope.Id,
+                               Name: scope.Name,
+                       })
+               }
+               // create the bp
+               bp := client.CreateBasicBlueprintV2(connection.Name, 
&helper.BlueprintV2Config{
+                       Connection: &plugin.BlueprintConnectionV200{
+                               Plugin:       azurePlugin,
+                               ConnectionId: connection.ID,
+                               Scopes:       bpScopes,
+                       },
+                       TimeAfter:   nil,
+                       SkipOnFail:  false,
+                       ProjectName: project.Name,
+               })
+               // get the project ... should have a reference to the blueprint 
now
+               outputProject = client.GetProject(project.Name)
+               require.Equal(t, bp.Name, outputProject.Blueprint.Name)
+               // run the bp
+               pipeline := client.TriggerBlueprint(bp.ID)
+               require.Equal(t, models.TASK_COMPLETED, pipeline.Status)
+       })
+       fmt.Println("========DONE=======")
+}
+
+func remoteScopesToScopes(remoteScopes helper.RemoteScopesOutput, filters 
[]string) []any {
+       var a []any
+       for _, c := range remoteScopes.Children {
+               repo := helper.Cast[AzureGitRepo](c.Data)
+               if len(filters) == 0 || helper.Contains(filters, repo.Name) {
+                       a = append(a, repo)
+               }
+       }
+       return a
+}
diff --git a/backend/test/e2e/manual/azuredevops/models.go 
b/backend/test/e2e/manual/azuredevops/models.go
new file mode 100644
index 000000000..d40172fdd
--- /dev/null
+++ b/backend/test/e2e/manual/azuredevops/models.go
@@ -0,0 +1,67 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 azuredevops
+
+import (
+       "github.com/apache/incubator-devlake/core/models/common"
+)
+
+// These models correspond to Python models
+
+type (
+       Refdiff struct {
+               TagsPattern string
+               TagsLimit   int
+               TagsOrder   string
+       }
+
+       AzureConnection struct {
+               Name         string
+               Token        string
+               Organization string
+       }
+
+       AzureGitRepositoryConfig struct {
+               common.ScopeConfig
+               Refdiff           Refdiff
+               DeploymentPattern string
+               ProductionPattern string
+       }
+
+       AzureGitRepo struct {
+               Id                  string
+               Name                string
+               ConnectionId        uint64
+               Url                 string
+               RemoteUrl           string
+               DefaultBranch       string
+               ProjectId           string
+               OrgId               string
+               ParentRepositoryUrl string
+               Provider            string
+               // special field
+               ScopeConfigId uint64
+       }
+)
+
+type TestConfig struct {
+       Org     string
+       Project string
+       Repos   []string
+       Token   string
+}
diff --git a/backend/test/e2e/manual/gitlab/gitlab_test.go 
b/backend/test/e2e/manual/gitlab/gitlab_test.go
new file mode 100644
index 000000000..c4b0d8ad7
--- /dev/null
+++ b/backend/test/e2e/manual/gitlab/gitlab_test.go
@@ -0,0 +1,155 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 gitlab
+
+import (
+       "fmt"
+       "github.com/apache/incubator-devlake/core/config"
+       "github.com/apache/incubator-devlake/core/models"
+       "github.com/apache/incubator-devlake/core/models/common"
+       "github.com/apache/incubator-devlake/core/plugin"
+       "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       gitextractor 
"github.com/apache/incubator-devlake/plugins/gitextractor/impl"
+       gitlab "github.com/apache/incubator-devlake/plugins/gitlab/impl"
+       pluginmodels "github.com/apache/incubator-devlake/plugins/gitlab/models"
+       "github.com/apache/incubator-devlake/test/helper"
+       "github.com/stretchr/testify/require"
+       "testing"
+)
+
+const pluginName = "gitlab"
+
+func TestGitlabPlugin(t *testing.T) {
+       createConnection := func(cfg TestConfig, client *helper.DevlakeClient) 
*helper.Connection {
+               conn := pluginmodels.GitlabConnection{
+                       BaseConnection: api.BaseConnection{
+                               Name: "gitlab-conn",
+                       },
+                       GitlabConn: pluginmodels.GitlabConn{
+                               RestConnection: api.RestConnection{
+                                       Endpoint:         
"https://gitlab.com/api/v4";,
+                                       Proxy:            "",
+                                       RateLimitPerHour: 0,
+                               },
+                               AccessToken: api.AccessToken{Token: cfg.Token},
+                       },
+               }
+               client.TestConnection(pluginName, conn)
+               return client.CreateConnection(pluginName, conn)
+       }
+       client := helper.ConnectLocalServer(t, &helper.LocalClientConfig{
+               ServerPort:   8089,
+               DbURL:        config.GetConfig().GetString("E2E_DB_URL"),
+               CreateServer: true,
+               DropDb:       false,
+               TruncateDb:   true,
+               Plugins: map[string]plugin.PluginMeta{
+                       "gitlab":       gitlab.Gitlab(""),
+                       "gitextractor": gitextractor.GitExtractor{},
+               },
+       })
+       cfg := helper.GetTestConfig[TestConfig]()
+       connection := createConnection(cfg, client)
+       t.Run("blueprint v200", func(t *testing.T) {
+               rule := 
helper.Cast[pluginmodels.GitlabScopeConfig](client.CreateScopeConfig("gitlab", 
connection.ID,
+                       pluginmodels.GitlabScopeConfig{
+                               ScopeConfig: common.ScopeConfig{
+                                       Entities: []string{
+                                               plugin.DOMAIN_TYPE_CICD,
+                                               plugin.DOMAIN_TYPE_CODE,
+                                               plugin.DOMAIN_TYPE_CODE_REVIEW,
+                                       },
+                               },
+                               Name:                 "rule-1",
+                               PrType:               "",
+                               PrComponent:          "",
+                               PrBodyClosePattern:   "",
+                               IssueSeverity:        "",
+                               IssuePriority:        "",
+                               IssueComponent:       "",
+                               IssueTypeBug:         "",
+                               IssueTypeIncident:    "",
+                               IssueTypeRequirement: "",
+                               DeploymentPattern:    ".*",
+                               ProductionPattern:    ".*",             // this 
triggers dora
+                               Refdiff:              map[string]any{}, // this 
is technically a true/false (nil or not)
+                       }))
+               _ = rule
+               remoteScopes := client.RemoteScopes(helper.RemoteScopesQuery{
+                       PluginName:   pluginName,
+                       ConnectionId: connection.ID,
+                       PageToken:    "",
+                       Params:       nil,
+               })
+               {
+                       // this doesn't have any direct use-case (for testing 
anyway)
+                       searchRemoteScopes := 
client.SearchRemoteScopes(helper.SearchRemoteScopesQuery{
+                               PluginName:   pluginName,
+                               ConnectionId: connection.ID,
+                               Search:       "projects",
+                               Page:         10,
+                               PageSize:     5,
+                               Params:       nil,
+                       })
+                       _ = searchRemoteScopes
+               }
+               var scopeData []any
+               for _, remoteScope := range remoteScopes.Children {
+                       if remoteScope.Type == "scope" {
+                               data := 
helper.Cast[pluginmodels.GitlabProject](remoteScope.Data)
+                               if len(cfg.Projects) == 0 || 
helper.Contains(cfg.Projects, data.Name) {
+                                       data.ScopeConfigId = rule.ID
+                                       scopeData = append(scopeData, data)
+                               }
+                       }
+               }
+               createdScopes := 
helper.Cast[[]*pluginmodels.GitlabProject](client.CreateScopes(pluginName, 
connection.ID, scopeData...))
+               listedScopes := client.ListScopes(pluginName, connection.ID, 
false)
+               require.Equal(t, len(createdScopes), len(listedScopes))
+               outputProject := client.CreateProject(&helper.ProjectConfig{
+                       ProjectName: fmt.Sprintf("project-%s", pluginName),
+                       EnableDora:  true,
+               })
+               projects := client.ListProjects()
+               require.Equal(t, 1, len(projects.Projects))
+               var scopes []*plugin.BlueprintScopeV200
+               for _, scope := range listedScopes {
+                       project := 
helper.Cast[pluginmodels.GitlabProject](scope.Scope)
+                       scopes = append(scopes, &plugin.BlueprintScopeV200{
+                               Id:   fmt.Sprintf("%s", project.ScopeId()),
+                               Name: "blueprint-v200",
+                       })
+               }
+               bp := client.CreateBasicBlueprintV2(connection.Name, 
&helper.BlueprintV2Config{
+                       Connection: &plugin.BlueprintConnectionV200{
+                               Plugin:       pluginName,
+                               ConnectionId: connection.ID,
+                               Scopes:       scopes,
+                       },
+                       SkipOnFail:  true,
+                       ProjectName: outputProject.Name,
+               })
+               // get the project ... should have a reference to the blueprint 
now
+               outputProject = client.GetProject(outputProject.Name)
+               require.Equal(t, bp.Name, outputProject.Blueprint.Name)
+               fmt.Printf("=========================Triggering blueprint for 
project %s =========================\n", outputProject.Name)
+               pipeline := client.TriggerBlueprint(bp.ID)
+               require.Equal(t, models.TASK_COMPLETED, pipeline.Status)
+       })
+       fmt.Println("======DONE======")
+}
diff --git a/backend/test/e2e/manual/gitlab/models.go 
b/backend/test/e2e/manual/gitlab/models.go
new file mode 100644
index 000000000..63f3ffbe1
--- /dev/null
+++ b/backend/test/e2e/manual/gitlab/models.go
@@ -0,0 +1,23 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 gitlab
+
+type TestConfig struct {
+       Token    string
+       Projects []string
+}
diff --git a/backend/test/e2e/manual/pagerduty/models.go 
b/backend/test/e2e/manual/pagerduty/models.go
new file mode 100644
index 000000000..c22634c36
--- /dev/null
+++ b/backend/test/e2e/manual/pagerduty/models.go
@@ -0,0 +1,26 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 pagerduty
+
+import "time"
+
+type TestConfig struct {
+       Token     string
+       TimeSince *time.Time
+       Services  []string
+}
diff --git a/backend/test/e2e/manual/pagerduty/pagerduty_test.go 
b/backend/test/e2e/manual/pagerduty/pagerduty_test.go
new file mode 100644
index 000000000..d8257e2c5
--- /dev/null
+++ b/backend/test/e2e/manual/pagerduty/pagerduty_test.go
@@ -0,0 +1,164 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 pagerduty
+
+import (
+       "fmt"
+       "github.com/apache/incubator-devlake/core/config"
+       "github.com/apache/incubator-devlake/core/models"
+       "github.com/apache/incubator-devlake/core/plugin"
+       "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
+       "github.com/apache/incubator-devlake/plugins/pagerduty/impl"
+       pluginmodels 
"github.com/apache/incubator-devlake/plugins/pagerduty/models"
+       "github.com/apache/incubator-devlake/test/helper"
+       "github.com/stretchr/testify/require"
+       "testing"
+       "time"
+)
+
+const pluginName = "pagerduty"
+
+func TestPagerDutyPlugin(t *testing.T) {
+       cfg := helper.GetTestConfig[TestConfig]()
+       client := helper.ConnectLocalServer(t, &helper.LocalClientConfig{
+               ServerPort:   8089,
+               DbURL:        config.GetConfig().GetString("E2E_DB_URL"),
+               CreateServer: true,
+               DropDb:       false,
+               TruncateDb:   true,
+               Plugins: map[string]plugin.PluginMeta{
+                       pluginName: &impl.PagerDuty{},
+               },
+       })
+       client.SetTimeout(0)
+       client.SetPipelineTimeout(0)
+       connection := createConnection(cfg, client)
+       t.Run("blueprint v200", func(t *testing.T) {
+               serviceScopes := helper.RemoteScopesOutput{}
+               var scopeData []any
+               for {
+                       serviceScopes = 
client.RemoteScopes(helper.RemoteScopesQuery{
+                               PluginName:   pluginName,
+                               ConnectionId: connection.ID,
+                               PageToken:    serviceScopes.NextPageToken,
+                               Params:       nil,
+                       })
+                       for _, remoteScope := range serviceScopes.Children {
+                               if remoteScope.Type == "scope" {
+                                       data := 
helper.Cast[pluginmodels.Service](remoteScope.Data)
+                                       for _, serviceName := range 
cfg.Services {
+                                               if serviceName == data.Name {
+                                                       scopeData = 
append(scopeData, &data)
+                                               }
+                                       }
+                               }
+                       }
+                       if serviceScopes.NextPageToken == "" {
+                               break
+                       }
+               }
+               createdScopes := 
helper.Cast[[]*pluginmodels.Service](client.CreateScopes(pluginName, 
connection.ID, scopeData...))
+               require.True(t, len(createdScopes) > 0)
+               uniqueString := time.Now().Format(time.RFC3339)
+               outputProject := createProject(client, 
fmt.Sprintf("pagerduty-project-%s-%s", pluginName, uniqueString))
+               var bpScopes []*plugin.BlueprintScopeV200
+               for _, scope := range createdScopes {
+                       bpScopes = append(bpScopes, &plugin.BlueprintScopeV200{
+                               Id:   scope.Id,
+                               Name: 
fmt.Sprintf("pagerduty-blueprint-v200-%s", uniqueString),
+                       })
+               }
+               bp := client.CreateBasicBlueprintV2(connection.Name, 
&helper.BlueprintV2Config{
+                       Connection: &plugin.BlueprintConnectionV200{
+                               Plugin:       pluginName,
+                               ConnectionId: connection.ID,
+                               Scopes:       bpScopes,
+                       },
+                       TimeAfter:   cfg.TimeSince,
+                       SkipOnFail:  false,
+                       ProjectName: outputProject.Name,
+               })
+               // get the project ... should have a reference to the blueprint 
now
+               outputProject = client.GetProject(outputProject.Name)
+               require.Equal(t, bp.Name, outputProject.Blueprint.Name)
+               fmt.Printf("=========================Triggering blueprint for 
project %s =========================\n", outputProject.Name)
+               pipeline := client.TriggerBlueprint(bp.ID)
+               require.Equal(t, models.TASK_COMPLETED, pipeline.Status)
+               createdScopesList := client.ListScopes(pluginName, 
connection.ID, true)
+               require.True(t, len(createdScopesList) > 0)
+               for _, scope := range createdScopesList {
+                       scopeCast := 
helper.Cast[pluginmodels.Service](scope.Scope)
+                       fmt.Printf("Deleting scope %s\n", scopeCast.Id)
+                       client.DeleteScope(pluginName, connection.ID, 
scopeCast.Id, false)
+                       fmt.Printf("Deleted scope %s\n", scopeCast.Id)
+               }
+       })
+       fmt.Println("======DONE======")
+}
+
+func createConnection(cfg TestConfig, client *helper.DevlakeClient) 
*helper.Connection {
+       conn := pluginmodels.PagerDutyConn{
+               RestConnection: api.RestConnection{
+                       Endpoint:         "https://api.pagerduty.com";,
+                       Proxy:            "",
+                       RateLimitPerHour: 0,
+               },
+               PagerDutyAccessToken: pluginmodels.PagerDutyAccessToken{
+                       Token: cfg.Token,
+               },
+       }
+       client.TestConnection(pluginName, conn)
+       connections := client.ListConnections(pluginName)
+       for _, connection := range connections {
+               if connection.Name == "pagerduty-conn" {
+                       return connection
+               }
+       }
+       return client.CreateConnection(pluginName, 
pluginmodels.PagerDutyConnection{
+               BaseConnection: api.BaseConnection{
+                       Name: "pagerduty-conn",
+               },
+               PagerDutyConn: conn,
+       })
+}
+
+func createProject(client *helper.DevlakeClient, projectName string) 
models.ApiOutputProject {
+       projects := client.ListProjects()
+       for _, project := range projects.Projects {
+               if project.Name == projectName {
+                       outputProject := client.GetProject(projectName)
+                       return outputProject
+               }
+       }
+       outputProject := client.CreateProject(&helper.ProjectConfig{
+               ProjectName: projectName,
+               EnableDora:  true,
+       })
+       return outputProject
+}
+
+func getTime(timeString string) *time.Time {
+       if timeString == "" {
+               return &time.Time{}
+       }
+       t, err := time.Parse("2006-01-02T15:04:05Z", timeString)
+       if err != nil {
+               panic(err)
+       }
+       return &t
+}
diff --git a/backend/test/e2e/remote/helper.go 
b/backend/test/e2e/remote/helper.go
index 8af1da556..11999e8ad 100644
--- a/backend/test/e2e/remote/helper.go
+++ b/backend/test/e2e/remote/helper.go
@@ -91,7 +91,7 @@ func CreateTestConnection(client *helper.DevlakeClient) 
*helper.Connection {
 }
 
 func CreateTestScope(client *helper.DevlakeClient, config *FakeScopeConfig, 
connectionId uint64) *FakeProject {
-       scopes := helper.Cast[[]FakeProject](client.CreateScope(PLUGIN_NAME,
+       scopes := helper.Cast[[]FakeProject](client.CreateScopes(PLUGIN_NAME,
                connectionId,
                FakeProject{
                        Id:            "p1",
diff --git a/backend/test/helper/api.go b/backend/test/helper/api.go
index 2bca9019d..78d5837d2 100644
--- a/backend/test/helper/api.go
+++ b/backend/test/helper/api.go
@@ -158,7 +158,7 @@ func (d *DevlakeClient) ListProjects() 
apiProject.PaginatedProjects {
        }, http.MethodGet, fmt.Sprintf("%s/projects", d.Endpoint), nil, nil)
 }
 
-func (d *DevlakeClient) CreateScope(pluginName string, connectionId uint64, 
scopes ...any) any {
+func (d *DevlakeClient) CreateScopes(pluginName string, connectionId uint64, 
scopes ...any) any {
        request := map[string]any{
                "data": scopes,
        }
diff --git a/backend/test/helper/client.go b/backend/test/helper/client.go
index 086970e11..7c0f6a5ea 100644
--- a/backend/test/helper/client.go
+++ b/backend/test/helper/client.go
@@ -23,6 +23,11 @@ import (
        "encoding/json"
        goerror "errors"
        "fmt"
+       "github.com/apache/incubator-devlake/core/dal"
+       dora "github.com/apache/incubator-devlake/plugins/dora/impl"
+       org "github.com/apache/incubator-devlake/plugins/org/impl"
+       refdiff "github.com/apache/incubator-devlake/plugins/refdiff/impl"
+       remotePlugin 
"github.com/apache/incubator-devlake/server/services/remote/plugin"
        "io"
        "math"
        "net/http"
@@ -32,11 +37,6 @@ import (
        "testing"
        "time"
 
-       "github.com/apache/incubator-devlake/core/dal"
-       dora "github.com/apache/incubator-devlake/plugins/dora/impl"
-       org "github.com/apache/incubator-devlake/plugins/org/impl"
-       remotePlugin 
"github.com/apache/incubator-devlake/server/services/remote/plugin"
-
        "github.com/apache/incubator-devlake/core/config"
        corectx "github.com/apache/incubator-devlake/core/context"
        "github.com/apache/incubator-devlake/core/errors"
@@ -264,7 +264,7 @@ func (d *DevlakeClient) initPlugins(cfg *LocalClientConfig) 
{
        // default plugins
        cfg.Plugins["org"] = org.Org{}
        cfg.Plugins["dora"] = dora.Dora{}
-
+       cfg.Plugins["refdiff"] = refdiff.RefDiff{}
        // register and init plugins
        for name, p := range cfg.Plugins {
                require.NoError(d.testCtx, plugin.RegisterPlugin(name, p))
@@ -373,7 +373,7 @@ func sendHttpRequest[Res any](t *testing.T, timeout 
time.Duration, debug debugIn
                                return false, errors.Convert(err)
                        }
                        response.Close = true
-                       return false, 
errors.HttpStatus(response.StatusCode).New(fmt.Sprintf("unexpected http status 
code: %d", response.StatusCode))
+                       return false, 
errors.HttpStatus(response.StatusCode).New(fmt.Sprintf("unexpected http status 
code calling [%s] %s: %d", httpMethod, endpoint, response.StatusCode))
                }
                b, _ = io.ReadAll(response.Body)
                if err = json.Unmarshal(b, &result); err != nil {
diff --git a/backend/test/helper/models.go b/backend/test/helper/models.go
index a95bfb263..ad49c50c8 100644
--- a/backend/test/helper/models.go
+++ b/backend/test/helper/models.go
@@ -18,6 +18,7 @@ limitations under the License.
 package helper
 
 import (
+       "github.com/apache/incubator-devlake/core/config"
        "github.com/apache/incubator-devlake/core/models"
        "time"
 
@@ -91,3 +92,12 @@ type SearchRemoteScopesQuery struct {
        PageSize     int
        Params       map[string]string
 }
+
+func SetTestConfig[T any](t T) {
+       config.GetConfig().Set("TEST_CONFIG", t)
+}
+
+func GetTestConfig[T any]() T {
+       raw := config.GetConfig().Get("TEST_CONFIG")
+       return raw.(T)
+}
diff --git a/backend/test/helper/utils.go b/backend/test/helper/utils.go
index 479fcd534..7bf603642 100644
--- a/backend/test/helper/utils.go
+++ b/backend/test/helper/utils.go
@@ -23,6 +23,7 @@ import (
        "fmt"
        "os"
        "path/filepath"
+       "reflect"
        "strings"
 
        "github.com/apache/incubator-devlake/core/plugin"
@@ -76,6 +77,15 @@ func Cast[T any](m any) T {
        return *t
 }
 
+func Contains[T any](list []T, elem any) bool {
+       for _, x := range list {
+               if reflect.DeepEqual(x, elem) {
+                       return true
+               }
+       }
+       return false
+}
+
 func readFile(path string) ([]string, error) {
        file, err := os.Open(path)
        if err != nil {

Reply via email to