diff --git a/go.mod b/go.mod index 3364128c3..0599590e3 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,6 @@ require ( github.com/docker/go-units v0.5.0 github.com/drone/envsubst v1.0.3 github.com/expr-lang/expr v1.16.9 - github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf github.com/fsnotify/fsnotify v1.8.0 github.com/gdgvda/cron v0.3.0 github.com/getkin/kin-openapi v0.128.1-0.20241224102021-cea0a13b906a diff --git a/go.sum b/go.sum index 15ff0fbd0..630894792 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,6 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf h1:NrF81UtW8gG2LBGkXFQFqlfNnvMt9WdB46sfdJY4oqc= -github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= diff --git a/pipeline/backend/kubernetes/kubernetes_test.go b/pipeline/backend/kubernetes/kubernetes_test.go index 5a0c3b75f..bd3e3bee3 100644 --- a/pipeline/backend/kubernetes/kubernetes_test.go +++ b/pipeline/backend/kubernetes/kubernetes_test.go @@ -45,9 +45,9 @@ func TestGettingConfig(t *testing.T) { assert.Equal(t, "default", engine.config.Namespace) assert.Equal(t, "hdd", engine.config.StorageClass) assert.Equal(t, "1G", engine.config.VolumeSize) - assert.Equal(t, false, engine.config.StorageRwx) - assert.Equal(t, 1, len(engine.config.PodLabels)) - assert.Equal(t, 1, len(engine.config.PodAnnotations)) - assert.Equal(t, 1, len(engine.config.ImagePullSecretNames)) - assert.Equal(t, false, engine.config.SecurityContext.RunAsNonRoot) + assert.False(t, engine.config.StorageRwx) + assert.Len(t, engine.config.PodLabels, 1) + assert.Len(t, engine.config.PodAnnotations, 1) + assert.Len(t, engine.config.ImagePullSecretNames, 1) + assert.False(t, engine.config.SecurityContext.RunAsNonRoot) } diff --git a/pipeline/backend/kubernetes/secrets_test.go b/pipeline/backend/kubernetes/secrets_test.go index 6c2385f1e..c918fc741 100644 --- a/pipeline/backend/kubernetes/secrets_test.go +++ b/pipeline/backend/kubernetes/secrets_test.go @@ -29,7 +29,7 @@ func TestNativeSecretsEnabled(t *testing.T) { nsp := newNativeSecretsProcessor(&config{ NativeSecretsAllowFromStep: true, }, nil) - assert.Equal(t, true, nsp.isEnabled()) + assert.True(t, nsp.isEnabled()) } func TestNativeSecretsDisabled(t *testing.T) { @@ -54,7 +54,7 @@ func TestNativeSecretsDisabled(t *testing.T) { }, }, }) - assert.Equal(t, false, nsp.isEnabled()) + assert.False(t, nsp.isEnabled()) err := nsp.process() assert.NoError(t, err) diff --git a/pipeline/frontend/yaml/matrix/matrix_test.go b/pipeline/frontend/yaml/matrix/matrix_test.go index 9bf0b1417..bda186722 100644 --- a/pipeline/frontend/yaml/matrix/matrix_test.go +++ b/pipeline/frontend/yaml/matrix/matrix_test.go @@ -17,42 +17,34 @@ package matrix import ( "testing" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" ) func TestMatrix(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("Calculate matrix", func() { - axis, _ := ParseString(fakeMatrix) + axis, _ := ParseString(fakeMatrix) + assert.Len(t, axis, 24) - g.It("Should calculate permutations", func() { - g.Assert(len(axis)).Equal(24) - }) + set := map[string]bool{} + for _, perm := range axis { + set[perm.String()] = true + } + assert.Len(t, set, 24) +} - g.It("Should not duplicate permutations", func() { - set := map[string]bool{} - for _, perm := range axis { - set[perm.String()] = true - } - g.Assert(len(set)).Equal(24) - }) +func TestMatrixEmpty(t *testing.T) { + axis, err := ParseString("") + assert.NoError(t, err) + assert.Empty(t, axis) +} - g.It("Should return empty array if no matrix", func() { - axis, err := ParseString("") - g.Assert(err).IsNil() - g.Assert(len(axis) == 0).IsTrue() - }) - - g.It("Should return included axis", func() { - axis, err := ParseString(fakeMatrixInclude) - g.Assert(err).IsNil() - g.Assert(len(axis)).Equal(2) - g.Assert(axis[0]["go_version"]).Equal("1.5") - g.Assert(axis[1]["go_version"]).Equal("1.6") - g.Assert(axis[0]["python_version"]).Equal("3.4") - g.Assert(axis[1]["python_version"]).Equal("3.4") - }) - }) +func TestMatrixIncluded(t *testing.T) { + axis, err := ParseString(fakeMatrixInclude) + assert.NoError(t, err) + assert.Len(t, axis, 2) + assert.Equal(t, "1.5", axis[0]["go_version"]) + assert.Equal(t, "1.6", axis[1]["go_version"]) + assert.Equal(t, "3.4", axis[0]["python_version"]) + assert.Equal(t, "3.4", axis[1]["python_version"]) } var fakeMatrix = ` diff --git a/pipeline/frontend/yaml/parse_test.go b/pipeline/frontend/yaml/parse_test.go index 5e0b5520e..63f240040 100644 --- a/pipeline/frontend/yaml/parse_test.go +++ b/pipeline/frontend/yaml/parse_test.go @@ -15,10 +15,8 @@ package yaml import ( - "slices" "testing" - "github.com/franela/goblin" "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/pipeline/frontend/metadata" @@ -26,116 +24,103 @@ import ( ) func TestParse(t *testing.T) { - g := goblin.Goblin(t) + t.Run("Should unmarshal a string", func(t *testing.T) { + out, err := ParseString(sampleYaml) + assert.NoError(t, err) - g.Describe("Parser", func() { - g.Describe("Given a yaml file", func() { - g.It("Should unmarshal a string", func() { - out, err := ParseString(sampleYaml) - if err != nil { - g.Fail(err) - } + assert.Contains(t, out.When.Constraints[0].Event, "tester") - g.Assert(slices.Contains(out.When.Constraints[0].Event, "tester")).Equal(true) + assert.Equal(t, "/go", out.Workspace.Base) + assert.Equal(t, "src/github.com/octocat/hello-world", out.Workspace.Path) + assert.Equal(t, "custom", out.Volumes.WorkflowVolumes[0].Name) + assert.Equal(t, "blockbridge", out.Volumes.WorkflowVolumes[0].Driver) + assert.Equal(t, "custom", out.Networks.WorkflowNetworks[0].Name) + assert.Equal(t, "overlay", out.Networks.WorkflowNetworks[0].Driver) + assert.Equal(t, "database", out.Services.ContainerList[0].Name) + assert.Equal(t, "mysql", out.Services.ContainerList[0].Image) + assert.Equal(t, "test", out.Steps.ContainerList[0].Name) + assert.Equal(t, "golang", out.Steps.ContainerList[0].Image) + assert.Equal(t, yaml_base_types.StringOrSlice{"go install", "go test"}, out.Steps.ContainerList[0].Commands) + assert.Equal(t, "build", out.Steps.ContainerList[1].Name) + assert.Equal(t, "golang", out.Steps.ContainerList[1].Image) + assert.Equal(t, yaml_base_types.StringOrSlice{"go build"}, out.Steps.ContainerList[1].Commands) + assert.Equal(t, "notify", out.Steps.ContainerList[2].Name) + assert.Equal(t, "slack", out.Steps.ContainerList[2].Image) + assert.Equal(t, "frontend", out.Labels["com.example.team"]) + assert.Equal(t, "build", out.Labels["com.example.type"]) + assert.Equal(t, "lint", out.DependsOn[0]) + assert.Equal(t, "test", out.DependsOn[1]) + assert.Equal(t, ("success"), out.RunsOn[0]) + assert.Equal(t, ("failure"), out.RunsOn[1]) + assert.False(t, out.SkipClone) + }) - g.Assert(out.Workspace.Base).Equal("/go") - g.Assert(out.Workspace.Path).Equal("src/github.com/octocat/hello-world") - g.Assert(out.Volumes.WorkflowVolumes[0].Name).Equal("custom") - g.Assert(out.Volumes.WorkflowVolumes[0].Driver).Equal("blockbridge") - g.Assert(out.Networks.WorkflowNetworks[0].Name).Equal("custom") - g.Assert(out.Networks.WorkflowNetworks[0].Driver).Equal("overlay") - g.Assert(out.Services.ContainerList[0].Name).Equal("database") - g.Assert(out.Services.ContainerList[0].Image).Equal("mysql") - g.Assert(out.Steps.ContainerList[0].Name).Equal("test") - g.Assert(out.Steps.ContainerList[0].Image).Equal("golang") - g.Assert(out.Steps.ContainerList[0].Commands).Equal(yaml_base_types.StringOrSlice{"go install", "go test"}) - g.Assert(out.Steps.ContainerList[1].Name).Equal("build") - g.Assert(out.Steps.ContainerList[1].Image).Equal("golang") - g.Assert(out.Steps.ContainerList[1].Commands).Equal(yaml_base_types.StringOrSlice{"go build"}) - g.Assert(out.Steps.ContainerList[2].Name).Equal("notify") - g.Assert(out.Steps.ContainerList[2].Image).Equal("slack") - // g.Assert(out.Steps.ContainerList[2].NetworkMode).Equal("container:name") - g.Assert(out.Labels["com.example.team"]).Equal("frontend") - g.Assert(out.Labels["com.example.type"]).Equal("build") - g.Assert(out.DependsOn[0]).Equal("lint") - g.Assert(out.DependsOn[1]).Equal("test") - g.Assert(out.RunsOn[0]).Equal("success") - g.Assert(out.RunsOn[1]).Equal("failure") - g.Assert(out.SkipClone).Equal(false) - }) + t.Run("Should handle simple yaml anchors", func(t *testing.T) { + out, err := ParseString(simpleYamlAnchors) + assert.NoError(t, err) + assert.Equal(t, "notify_success", out.Steps.ContainerList[0].Name) + assert.Equal(t, "plugins/slack", out.Steps.ContainerList[0].Image) + }) - g.It("Should handle simple yaml anchors", func() { - out, err := ParseString(simpleYamlAnchors) - if err != nil { - g.Fail(err) - } - g.Assert(out.Steps.ContainerList[0].Name).Equal("notify_success") - g.Assert(out.Steps.ContainerList[0].Image).Equal("plugins/slack") - }) + t.Run("Should unmarshal variables", func(t *testing.T) { + out, err := ParseString(sampleVarYaml) + assert.NoError(t, err) + assert.Equal(t, "notify_fail", out.Steps.ContainerList[0].Name) + assert.Equal(t, "plugins/slack", out.Steps.ContainerList[0].Image) + assert.Equal(t, "notify_success", out.Steps.ContainerList[1].Name) + assert.Equal(t, "plugins/slack", out.Steps.ContainerList[1].Image) - g.It("Should unmarshal variables", func() { - out, err := ParseString(sampleVarYaml) - if err != nil { - g.Fail(err) - } - g.Assert(out.Steps.ContainerList[0].Name).Equal("notify_fail") - g.Assert(out.Steps.ContainerList[0].Image).Equal("plugins/slack") - g.Assert(out.Steps.ContainerList[1].Name).Equal("notify_success") - g.Assert(out.Steps.ContainerList[1].Image).Equal("plugins/slack") + assert.Empty(t, out.Steps.ContainerList[0].When.Constraints) + assert.Equal(t, "notify_success", out.Steps.ContainerList[1].Name) + assert.Equal(t, "plugins/slack", out.Steps.ContainerList[1].Image) + assert.Equal(t, yaml_base_types.StringOrSlice{"success"}, out.Steps.ContainerList[1].When.Constraints[0].Event) + }) +} - g.Assert(len(out.Steps.ContainerList[0].When.Constraints)).Equal(0) - g.Assert(out.Steps.ContainerList[1].Name).Equal("notify_success") - g.Assert(out.Steps.ContainerList[1].Image).Equal("plugins/slack") - g.Assert(out.Steps.ContainerList[1].When.Constraints[0].Event).Equal(yaml_base_types.StringOrSlice{"success"}) - }) +func TestMatch(t *testing.T) { + matchConfig, err := ParseString(sampleYaml) + assert.NoError(t, err) - matchConfig, err := ParseString(sampleYaml) - if err != nil { - g.Fail(err) - } + t.Run("Should match event tester", func(t *testing.T) { + match, err := matchConfig.When.Match(metadata.Metadata{ + Curr: metadata.Pipeline{ + Event: "tester", + }, + }, false, nil) + assert.True(t, match) + assert.NoError(t, err) + }) - g.It("Should match event tester", func() { - match, err := matchConfig.When.Match(metadata.Metadata{ - Curr: metadata.Pipeline{ - Event: "tester", - }, - }, false, nil) - g.Assert(match).Equal(true) - g.Assert(err).IsNil() - }) + t.Run("Should match event tester2", func(t *testing.T) { + match, err := matchConfig.When.Match(metadata.Metadata{ + Curr: metadata.Pipeline{ + Event: "tester2", + }, + }, false, nil) + assert.True(t, match) + assert.NoError(t, err) + }) - g.It("Should match event tester2", func() { - match, err := matchConfig.When.Match(metadata.Metadata{ - Curr: metadata.Pipeline{ - Event: "tester2", - }, - }, false, nil) - g.Assert(match).Equal(true) - g.Assert(err).IsNil() - }) + t.Run("Should match branch tester", func(t *testing.T) { + match, err := matchConfig.When.Match(metadata.Metadata{ + Curr: metadata.Pipeline{ + Commit: metadata.Commit{ + Branch: "tester", + }, + }, + }, true, nil) + assert.True(t, match) + assert.NoError(t, err) + }) - g.It("Should match branch tester", func() { - match, err := matchConfig.When.Match(metadata.Metadata{ - Curr: metadata.Pipeline{ - Commit: metadata.Commit{ - Branch: "tester", - }, - }, - }, true, nil) - g.Assert(match).Equal(true) - g.Assert(err).IsNil() - }) - - g.It("Should not match event push", func() { - match, err := matchConfig.When.Match(metadata.Metadata{ - Curr: metadata.Pipeline{ - Event: "push", - }, - }, false, nil) - g.Assert(match).Equal(false) - g.Assert(err).IsNil() - }) - }) + t.Run("Should not match event push", func(t *testing.T) { + match, err := matchConfig.When.Match(metadata.Metadata{ + Curr: metadata.Pipeline{ + Event: "push", + }, + }, false, nil) + assert.False(t, match) + assert.NoError(t, err) }) } @@ -262,27 +247,19 @@ steps: ` func TestSlice(t *testing.T) { - g := goblin.Goblin(t) + t.Run("should marshal a not set slice to nil", func(t *testing.T) { + out, err := ParseString(sampleSliceYaml) + assert.NoError(t, err) - g.Describe("Parser", func() { - g.It("should marshal a not set slice to nil", func() { - out, err := ParseString(sampleSliceYaml) - if err != nil { - g.Fail(err) - } + assert.Nil(t, out.Steps.ContainerList[0].DependsOn) + assert.Empty(t, out.Steps.ContainerList[0].DependsOn) + }) - g.Assert(out.Steps.ContainerList[0].DependsOn).IsNil() - g.Assert(len(out.Steps.ContainerList[0].DependsOn)).Equal(0) - }) + t.Run("should marshal an empty slice", func(t *testing.T) { + out, err := ParseString(sampleSliceYaml) + assert.NoError(t, err) - g.It("should marshal an empty slice", func() { - out, err := ParseString(sampleSliceYaml) - if err != nil { - g.Fail(err) - } - - g.Assert(out.Steps.ContainerList[1].DependsOn).IsNotNil() - g.Assert(len(out.Steps.ContainerList[1].DependsOn)).Equal(0) - }) + assert.NotNil(t, out.Steps.ContainerList[1].DependsOn) + assert.Empty(t, (out.Steps.ContainerList[1].DependsOn)) }) } diff --git a/pipeline/frontend/yaml/types/base/bool_test.go b/pipeline/frontend/yaml/types/base/bool_test.go index 9c574d1cb..8264f59f6 100644 --- a/pipeline/frontend/yaml/types/base/bool_test.go +++ b/pipeline/frontend/yaml/types/base/bool_test.go @@ -17,51 +17,39 @@ package base import ( "testing" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" "gopkg.in/yaml.v3" ) func TestBoolTrue(t *testing.T) { - g := goblin.Goblin(t) + t.Run("unmarshal true", func(t *testing.T) { + in := []byte("true") + out := BoolTrue{} + err := yaml.Unmarshal(in, &out) + assert.NoError(t, err) + assert.True(t, out.Bool()) + }) - g.Describe("Yaml bool type", func() { - g.Describe("given a yaml file", func() { - g.It("should unmarshal true", func() { - in := []byte("true") - out := BoolTrue{} - err := yaml.Unmarshal(in, &out) - if err != nil { - g.Fail(err) - } - g.Assert(out.Bool()).Equal(true) - }) + t.Run("unmarshal false", func(t *testing.T) { + in := []byte("false") + out := BoolTrue{} + err := yaml.Unmarshal(in, &out) + assert.NoError(t, err) + assert.False(t, out.Bool()) + }) - g.It("should unmarshal false", func() { - in := []byte("false") - out := BoolTrue{} - err := yaml.Unmarshal(in, &out) - if err != nil { - g.Fail(err) - } - g.Assert(out.Bool()).Equal(false) - }) + t.Run("unmarshal true when empty", func(t *testing.T) { + in := []byte("") + out := BoolTrue{} + err := yaml.Unmarshal(in, &out) + assert.NoError(t, err) + assert.True(t, out.Bool()) + }) - g.It("should unmarshal true when empty", func() { - in := []byte("") - out := BoolTrue{} - err := yaml.Unmarshal(in, &out) - if err != nil { - g.Fail(err) - } - g.Assert(out.Bool()).Equal(true) - }) - - g.It("should throw error when invalid", func() { - in := []byte("abc") // string value should fail parse - out := BoolTrue{} - err := yaml.Unmarshal(in, &out) - g.Assert(err).IsNotNil("expects error") - }) - }) + t.Run("throw error when invalid", func(t *testing.T) { + in := []byte("abc") // string value should fail parse + out := BoolTrue{} + err := yaml.Unmarshal(in, &out) + assert.Error(t, err) }) } diff --git a/server/api/hook_test.go b/server/api/hook_test.go index b107d7c6b..6620440f3 100644 --- a/server/api/hook_test.go +++ b/server/api/hook_test.go @@ -7,7 +7,6 @@ import ( "net/url" "testing" - "github.com/franela/goblin" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -28,77 +27,70 @@ import ( func TestHook(t *testing.T) { gin.SetMode(gin.TestMode) - g := goblin.Goblin(t) - g.Describe("Hook", func() { - g.It("should handle a correct webhook payload", func() { - _manager := mocks_services.NewManager(t) - _forge := mocks_forge.NewForge(t) - _store := mocks_store.NewStore(t) - _configService := mocks_config_service.NewService(t) - _secretService := mocks_secret_service.NewService(t) - _registryService := mocks_registry_service.NewService(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = true - server.Config.Permissions.Orgs = permissions.NewOrgs(nil) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) - user := &model.User{ - ID: 123, - } - repo := &model.Repo{ - ID: 123, - ForgeRemoteID: "123", - Owner: "owner", - Name: "name", - IsActive: true, - UserID: user.ID, - Hash: "secret-123-this-is-a-secret", - } - pipeline := &model.Pipeline{ - ID: 123, - RepoID: repo.ID, - Event: model.EventPush, - } + _manager := mocks_services.NewManager(t) + _forge := mocks_forge.NewForge(t) + _store := mocks_store.NewStore(t) + _configService := mocks_config_service.NewService(t) + _secretService := mocks_secret_service.NewService(t) + _registryService := mocks_registry_service.NewService(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = true + server.Config.Permissions.Orgs = permissions.NewOrgs(nil) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) + user := &model.User{ + ID: 123, + } + repo := &model.Repo{ + ID: 123, + ForgeRemoteID: "123", + Owner: "owner", + Name: "name", + IsActive: true, + UserID: user.ID, + Hash: "secret-123-this-is-a-secret", + } + pipeline := &model.Pipeline{ + ID: 123, + RepoID: repo.ID, + Event: model.EventPush, + } - repoToken := token.New(token.HookToken) - repoToken.Set("repo-id", fmt.Sprintf("%d", repo.ID)) - signedToken, err := repoToken.Sign("secret-123-this-is-a-secret") - if err != nil { - g.Fail(err) - } + repoToken := token.New(token.HookToken) + repoToken.Set("repo-id", fmt.Sprintf("%d", repo.ID)) + signedToken, err := repoToken.Sign("secret-123-this-is-a-secret") + assert.NoError(t, err) - header := http.Header{} - header.Set("Authorization", fmt.Sprintf("Bearer %s", signedToken)) - c.Request = &http.Request{ - Header: header, - URL: &url.URL{ - Scheme: "https", - }, - } + header := http.Header{} + header.Set("Authorization", fmt.Sprintf("Bearer %s", signedToken)) + c.Request = &http.Request{ + Header: header, + URL: &url.URL{ + Scheme: "https", + }, + } - _manager.On("ForgeFromRepo", repo).Return(_forge, nil) - _forge.On("Hook", mock.Anything, mock.Anything).Return(repo, pipeline, nil) - _store.On("GetRepo", repo.ID).Return(repo, nil) - _store.On("GetUser", user.ID).Return(user, nil) - _store.On("UpdateRepo", repo).Return(nil) - _store.On("CreatePipeline", mock.Anything).Return(nil) - _manager.On("ConfigServiceFromRepo", repo).Return(_configService) - _configService.On("Fetch", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) - _forge.On("Netrc", mock.Anything, mock.Anything).Return(&model.Netrc{}, nil) - _store.On("GetPipelineLastBefore", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) - _manager.On("SecretServiceFromRepo", repo).Return(_secretService) - _secretService.On("SecretListPipeline", repo, mock.Anything, mock.Anything).Return(nil, nil) - _manager.On("RegistryServiceFromRepo", repo).Return(_registryService) - _registryService.On("RegistryListPipeline", repo, mock.Anything).Return(nil, nil) - _manager.On("EnvironmentService").Return(nil) - _store.On("DeletePipeline", mock.Anything).Return(nil) + _manager.On("ForgeFromRepo", repo).Return(_forge, nil) + _forge.On("Hook", mock.Anything, mock.Anything).Return(repo, pipeline, nil) + _store.On("GetRepo", repo.ID).Return(repo, nil) + _store.On("GetUser", user.ID).Return(user, nil) + _store.On("UpdateRepo", repo).Return(nil) + _store.On("CreatePipeline", mock.Anything).Return(nil) + _manager.On("ConfigServiceFromRepo", repo).Return(_configService) + _configService.On("Fetch", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) + _forge.On("Netrc", mock.Anything, mock.Anything).Return(&model.Netrc{}, nil) + _store.On("GetPipelineLastBefore", mock.Anything, mock.Anything, mock.Anything).Return(nil, nil) + _manager.On("SecretServiceFromRepo", repo).Return(_secretService) + _secretService.On("SecretListPipeline", repo, mock.Anything, mock.Anything).Return(nil, nil) + _manager.On("RegistryServiceFromRepo", repo).Return(_registryService) + _registryService.On("RegistryListPipeline", repo, mock.Anything).Return(nil, nil) + _manager.On("EnvironmentService").Return(nil) + _store.On("DeletePipeline", mock.Anything).Return(nil) - api.PostHook(c) + api.PostHook(c) - assert.Equal(g, http.StatusNoContent, c.Writer.Status()) - assert.Equal(g, "true", w.Header().Get("Pipeline-Filtered")) - }) - }) + assert.Equal(t, http.StatusNoContent, c.Writer.Status()) + assert.Equal(t, "true", w.Header().Get("Pipeline-Filtered")) } diff --git a/server/api/login_test.go b/server/api/login_test.go index 3ccb86793..cca5c991d 100644 --- a/server/api/login_test.go +++ b/server/api/login_test.go @@ -9,7 +9,6 @@ import ( "testing" "time" - "github.com/franela/goblin" "github.com/gin-gonic/gin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" @@ -29,346 +28,341 @@ import ( func TestHandleAuth(t *testing.T) { gin.SetMode(gin.TestMode) - g := goblin.Goblin(t) - g.Describe("Login", func() { - user := &model.User{ - ID: 1, - OrgID: 1, - ForgeID: 1, - ForgeRemoteID: "remote-id-1", - Login: "test", - Email: "test@example.com", - Admin: false, - } - org := &model.Org{ - ID: 1, - Name: user.Login, + user := &model.User{ + ID: 1, + OrgID: 1, + ForgeID: 1, + ForgeRemoteID: "remote-id-1", + Login: "test", + Email: "test@example.com", + Admin: false, + } + org := &model.Org{ + ID: 1, + Name: user.Login, + } + + server.Config.Server.SessionExpires = time.Hour + + t.Run("should handle errors from the callback", func(t *testing.T) { + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + + query := url.Values{} + query.Set("error", "invalid_scope") + query.Set("error_description", "The requested scope is invalid, unknown, or malformed") + query.Set("error_uri", "https://developer.atlassian.com/cloud/jira/platform/rest/#api-group-OAuth2-ErrorHandling") + + c.Request = &http.Request{ + Header: make(http.Header), + Method: http.MethodGet, + URL: &url.URL{ + Scheme: "https", + Path: "/authorize", + RawQuery: query.Encode(), + }, } - server.Config.Server.SessionExpires = time.Hour + api.HandleAuth(c) - g.It("should handle errors from the callback", func() { - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, fmt.Sprintf("/login?%s", query.Encode()), c.Writer.Header().Get("Location")) + }) - query := url.Values{} - query.Set("error", "invalid_scope") - query.Set("error_description", "The requested scope is invalid, unknown, or malformed") - query.Set("error_uri", "https://developer.atlassian.com/cloud/jira/platform/rest/#api-group-OAuth2-ErrorHandling") + t.Run("should fail if the state is wrong", func(t *testing.T) { + _manager := mocks_services.NewManager(t) + _store := mocks_store.NewStore(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = true + server.Config.Permissions.Orgs = permissions.NewOrgs(nil) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) - c.Request = &http.Request{ - Header: make(http.Header), - Method: http.MethodGet, - URL: &url.URL{ - Scheme: "https", - Path: "/authorize", - RawQuery: query.Encode(), - }, + query := url.Values{} + query.Set("code", "assumed_to_be_valid_code") + + wrongToken := token.New(token.OAuthStateToken) + wrongToken.Set("forge_id", "1") + signedWrongToken, _ := wrongToken.Sign("wrong_secret") + query.Set("state", signedWrongToken) + + c.Request = &http.Request{ + Header: make(http.Header), + URL: &url.URL{ + Scheme: "https", + RawQuery: query.Encode(), + }, + } + + api.HandleAuth(c) + + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, "/login?error=invalid_state", c.Writer.Header().Get("Location")) + }) + + t.Run("should redirect to forge login page", func(t *testing.T) { + _manager := mocks_services.NewManager(t) + _forge := mocks_forge.NewForge(t) + _store := mocks_store.NewStore(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = true + server.Config.Permissions.Orgs = permissions.NewOrgs(nil) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) + c.Request = &http.Request{ + Header: make(http.Header), + URL: &url.URL{ + Scheme: "https", + }, + } + + _manager.On("ForgeByID", int64(1)).Return(_forge, nil) + + forgeRedirectURL := "" + _forge.On("Login", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + state, ok := args.Get(1).(*forge_types.OAuthRequest) + if ok { + forgeRedirectURL = fmt.Sprintf("https://my-awesome-forge.com/oauth/authorize?client_id=client-id&state=%s", state.State) } + }).Return(nil, func(context.Context, *forge_types.OAuthRequest) string { + return forgeRedirectURL + }, nil) - api.HandleAuth(c) + api.HandleAuth(c) - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, fmt.Sprintf("/login?%s", query.Encode()), c.Writer.Header().Get("Location")) - }) + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, forgeRedirectURL, c.Writer.Header().Get("Location")) + }) - g.It("should fail if the state is wrong", func() { - _manager := mocks_services.NewManager(t) - _store := mocks_store.NewStore(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = true - server.Config.Permissions.Orgs = permissions.NewOrgs(nil) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) + t.Run("should register a new user", func(t *testing.T) { + _manager := mocks_services.NewManager(t) + _forge := mocks_forge.NewForge(t) + _store := mocks_store.NewStore(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = true + server.Config.Permissions.Orgs = permissions.NewOrgs(nil) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) + c.Request = &http.Request{ + Header: make(http.Header), + URL: &url.URL{ + Scheme: "https", + }, + } - query := url.Values{} - query.Set("code", "assumed_to_be_valid_code") + _manager.On("ForgeByID", int64(1)).Return(_forge, nil) + _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) + _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(nil, types.RecordNotExist) + _store.On("CreateUser", mock.Anything).Return(nil) + _store.On("OrgFindByName", user.Login).Return(nil, nil) + _store.On("OrgCreate", mock.Anything).Return(nil) + _store.On("UpdateUser", mock.Anything).Return(nil) + _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) - wrongToken := token.New(token.OAuthStateToken) - wrongToken.Set("forge_id", "1") - signedWrongToken, _ := wrongToken.Sign("wrong_secret") - query.Set("state", signedWrongToken) + api.HandleAuth(c) - c.Request = &http.Request{ - Header: make(http.Header), - URL: &url.URL{ - Scheme: "https", - RawQuery: query.Encode(), - }, - } + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, "/", c.Writer.Header().Get("Location")) + assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie")) + }) - api.HandleAuth(c) + t.Run("should login an existing user", func(t *testing.T) { + _manager := mocks_services.NewManager(t) + _forge := mocks_forge.NewForge(t) + _store := mocks_store.NewStore(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = true + server.Config.Permissions.Orgs = permissions.NewOrgs(nil) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) + c.Request = &http.Request{ + Header: make(http.Header), + URL: &url.URL{ + Scheme: "https", + }, + } - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, "/login?error=invalid_state", c.Writer.Header().Get("Location")) - }) + _manager.On("ForgeByID", int64(1)).Return(_forge, nil) + _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) + _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil) + _store.On("OrgGet", org.ID).Return(org, nil) + _store.On("UpdateUser", mock.Anything).Return(nil) + _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) - g.It("should redirect to forge login page", func() { - _manager := mocks_services.NewManager(t) - _forge := mocks_forge.NewForge(t) - _store := mocks_store.NewStore(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = true - server.Config.Permissions.Orgs = permissions.NewOrgs(nil) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) - c.Request = &http.Request{ - Header: make(http.Header), - URL: &url.URL{ - Scheme: "https", - }, - } + api.HandleAuth(c) - _manager.On("ForgeByID", int64(1)).Return(_forge, nil) + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, "/", c.Writer.Header().Get("Location")) + assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie")) + }) - forgeRedirectURL := "" - _forge.On("Login", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { - state, ok := args.Get(1).(*forge_types.OAuthRequest) - if ok { - forgeRedirectURL = fmt.Sprintf("https://my-awesome-forge.com/oauth/authorize?client_id=client-id&state=%s", state.State) - } - }).Return(nil, func(context.Context, *forge_types.OAuthRequest) string { - return forgeRedirectURL - }, nil) + t.Run("should deny a new user if registration is closed", func(t *testing.T) { + _manager := mocks_services.NewManager(t) + _forge := mocks_forge.NewForge(t) + _store := mocks_store.NewStore(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = false + server.Config.Permissions.Orgs = permissions.NewOrgs(nil) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) + c.Request = &http.Request{ + Header: make(http.Header), + URL: &url.URL{ + Scheme: "https", + }, + } - api.HandleAuth(c) + _manager.On("ForgeByID", int64(1)).Return(_forge, nil) + _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) + _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(nil, types.RecordNotExist) - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, forgeRedirectURL, c.Writer.Header().Get("Location")) - }) + api.HandleAuth(c) - g.It("should register a new user", func() { - _manager := mocks_services.NewManager(t) - _forge := mocks_forge.NewForge(t) - _store := mocks_store.NewStore(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = true - server.Config.Permissions.Orgs = permissions.NewOrgs(nil) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) - c.Request = &http.Request{ - Header: make(http.Header), - URL: &url.URL{ - Scheme: "https", - }, - } + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, "/login?error=registration_closed", c.Writer.Header().Get("Location")) + }) - _manager.On("ForgeByID", int64(1)).Return(_forge, nil) - _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) - _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(nil, types.RecordNotExist) - _store.On("CreateUser", mock.Anything).Return(nil) - _store.On("OrgFindByName", user.Login).Return(nil, nil) - _store.On("OrgCreate", mock.Anything).Return(nil) - _store.On("UpdateUser", mock.Anything).Return(nil) - _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) + t.Run("should deny a user with missing org access", func(t *testing.T) { + _manager := mocks_services.NewManager(t) + _forge := mocks_forge.NewForge(t) + _store := mocks_store.NewStore(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = true + server.Config.Permissions.Orgs = permissions.NewOrgs([]string{"org1"}) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) + c.Request = &http.Request{ + Header: make(http.Header), + URL: &url.URL{ + Scheme: "https", + }, + } - api.HandleAuth(c) + _manager.On("ForgeByID", int64(1)).Return(_forge, nil) + _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) + _forge.On("Teams", mock.Anything, user).Return([]*model.Team{ + { + Login: "org2", + }, + }, nil) - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, "/", c.Writer.Header().Get("Location")) - assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie")) - }) + api.HandleAuth(c) - g.It("should login an existing user", func() { - _manager := mocks_services.NewManager(t) - _forge := mocks_forge.NewForge(t) - _store := mocks_store.NewStore(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = true - server.Config.Permissions.Orgs = permissions.NewOrgs(nil) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) - c.Request = &http.Request{ - Header: make(http.Header), - URL: &url.URL{ - Scheme: "https", - }, - } + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, "/login?error=org_access_denied", c.Writer.Header().Get("Location")) + }) - _manager.On("ForgeByID", int64(1)).Return(_forge, nil) - _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) - _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil) - _store.On("OrgGet", org.ID).Return(org, nil) - _store.On("UpdateUser", mock.Anything).Return(nil) - _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) + t.Run("User org should be created if it does not exists", func(t *testing.T) { + _manager := mocks_services.NewManager(t) + _forge := mocks_forge.NewForge(t) + _store := mocks_store.NewStore(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = true + server.Config.Permissions.Orgs = permissions.NewOrgs(nil) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) + c.Request = &http.Request{ + Header: make(http.Header), + URL: &url.URL{ + Scheme: "https", + }, + } + user.OrgID = 0 - api.HandleAuth(c) + _manager.On("ForgeByID", int64(1)).Return(_forge, nil) + _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) + _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil) + _store.On("OrgFindByName", user.Login).Return(nil, types.RecordNotExist) + _store.On("OrgCreate", mock.Anything).Return(nil) + _store.On("UpdateUser", mock.Anything).Return(nil) + _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, "/", c.Writer.Header().Get("Location")) - assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie")) - }) + api.HandleAuth(c) - g.It("should deny a new user if registration is closed", func() { - _manager := mocks_services.NewManager(t) - _forge := mocks_forge.NewForge(t) - _store := mocks_store.NewStore(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = false - server.Config.Permissions.Orgs = permissions.NewOrgs(nil) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) - c.Request = &http.Request{ - Header: make(http.Header), - URL: &url.URL{ - Scheme: "https", - }, - } + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, "/", c.Writer.Header().Get("Location")) + assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie")) + }) - _manager.On("ForgeByID", int64(1)).Return(_forge, nil) - _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) - _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(nil, types.RecordNotExist) + t.Run("User org should be linked if it has the same name as the user", func(t *testing.T) { + _manager := mocks_services.NewManager(t) + _forge := mocks_forge.NewForge(t) + _store := mocks_store.NewStore(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = true + server.Config.Permissions.Orgs = permissions.NewOrgs(nil) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) + c.Request = &http.Request{ + Header: make(http.Header), + URL: &url.URL{ + Scheme: "https", + }, + } + user.OrgID = 0 - api.HandleAuth(c) + _manager.On("ForgeByID", int64(1)).Return(_forge, nil) + _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) + _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil) + _store.On("OrgFindByName", user.Login).Return(org, nil) + _store.On("OrgUpdate", mock.Anything).Return(nil) + _store.On("UpdateUser", mock.Anything).Return(nil) + _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, "/login?error=registration_closed", c.Writer.Header().Get("Location")) - }) + api.HandleAuth(c) - g.It("should deny a user with missing org access", func() { - _manager := mocks_services.NewManager(t) - _forge := mocks_forge.NewForge(t) - _store := mocks_store.NewStore(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = true - server.Config.Permissions.Orgs = permissions.NewOrgs([]string{"org1"}) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) - c.Request = &http.Request{ - Header: make(http.Header), - URL: &url.URL{ - Scheme: "https", - }, - } + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, "/", c.Writer.Header().Get("Location")) + assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie")) + }) - _manager.On("ForgeByID", int64(1)).Return(_forge, nil) - _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) - _forge.On("Teams", mock.Anything, user).Return([]*model.Team{ - { - Login: "org2", - }, - }, nil) + t.Run("User org should be updated if the user name was changed", func(t *testing.T) { + _manager := mocks_services.NewManager(t) + _forge := mocks_forge.NewForge(t) + _store := mocks_store.NewStore(t) + server.Config.Services.Manager = _manager + server.Config.Permissions.Open = true + server.Config.Permissions.Orgs = permissions.NewOrgs(nil) + server.Config.Permissions.Admins = permissions.NewAdmins(nil) + w := httptest.NewRecorder() + c, _ := gin.CreateTestContext(w) + c.Set("store", _store) + c.Request = &http.Request{ + Header: make(http.Header), + URL: &url.URL{ + Scheme: "https", + }, + } + org.Name = "not-the-user-name" - api.HandleAuth(c) + _manager.On("ForgeByID", int64(1)).Return(_forge, nil) + _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) + _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil) + _store.On("OrgGet", user.OrgID).Return(org, nil) + _store.On("OrgUpdate", mock.Anything).Return(nil) + _store.On("UpdateUser", mock.Anything).Return(nil) + _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, "/login?error=org_access_denied", c.Writer.Header().Get("Location")) - }) + api.HandleAuth(c) - g.Describe("User org", func() { - g.It("should be created if it does not exists", func() { - _manager := mocks_services.NewManager(t) - _forge := mocks_forge.NewForge(t) - _store := mocks_store.NewStore(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = true - server.Config.Permissions.Orgs = permissions.NewOrgs(nil) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) - c.Request = &http.Request{ - Header: make(http.Header), - URL: &url.URL{ - Scheme: "https", - }, - } - user.OrgID = 0 - - _manager.On("ForgeByID", int64(1)).Return(_forge, nil) - _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) - _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil) - _store.On("OrgFindByName", user.Login).Return(nil, types.RecordNotExist) - _store.On("OrgCreate", mock.Anything).Return(nil) - _store.On("UpdateUser", mock.Anything).Return(nil) - _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) - - api.HandleAuth(c) - - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, "/", c.Writer.Header().Get("Location")) - assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie")) - }) - - g.It("should be linked if it has the same name as the user", func() { - _manager := mocks_services.NewManager(t) - _forge := mocks_forge.NewForge(t) - _store := mocks_store.NewStore(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = true - server.Config.Permissions.Orgs = permissions.NewOrgs(nil) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) - c.Request = &http.Request{ - Header: make(http.Header), - URL: &url.URL{ - Scheme: "https", - }, - } - user.OrgID = 0 - - _manager.On("ForgeByID", int64(1)).Return(_forge, nil) - _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) - _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil) - _store.On("OrgFindByName", user.Login).Return(org, nil) - _store.On("OrgUpdate", mock.Anything).Return(nil) - _store.On("UpdateUser", mock.Anything).Return(nil) - _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) - - api.HandleAuth(c) - - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, "/", c.Writer.Header().Get("Location")) - assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie")) - }) - - g.It("should be updated if the user name was changed", func() { - _manager := mocks_services.NewManager(t) - _forge := mocks_forge.NewForge(t) - _store := mocks_store.NewStore(t) - server.Config.Services.Manager = _manager - server.Config.Permissions.Open = true - server.Config.Permissions.Orgs = permissions.NewOrgs(nil) - server.Config.Permissions.Admins = permissions.NewAdmins(nil) - w := httptest.NewRecorder() - c, _ := gin.CreateTestContext(w) - c.Set("store", _store) - c.Request = &http.Request{ - Header: make(http.Header), - URL: &url.URL{ - Scheme: "https", - }, - } - org.Name = "not-the-user-name" - - _manager.On("ForgeByID", int64(1)).Return(_forge, nil) - _forge.On("Login", mock.Anything, mock.Anything).Return(user, "", nil) - _store.On("GetUserRemoteID", user.ForgeRemoteID, user.Login).Return(user, nil) - _store.On("OrgGet", user.OrgID).Return(org, nil) - _store.On("OrgUpdate", mock.Anything).Return(nil) - _store.On("UpdateUser", mock.Anything).Return(nil) - _forge.On("Repos", mock.Anything, mock.Anything).Return(nil, nil) - - api.HandleAuth(c) - - assert.Equal(g, http.StatusSeeOther, c.Writer.Status()) - assert.Equal(g, "/", c.Writer.Header().Get("Location")) - assert.NotEmpty(g, c.Writer.Header().Get("Set-Cookie")) - }) - }) + assert.Equal(t, http.StatusSeeOther, c.Writer.Status()) + assert.Equal(t, "/", c.Writer.Header().Get("Location")) + assert.NotEmpty(t, c.Writer.Header().Get("Set-Cookie")) }) } diff --git a/server/ccmenu/cc_test.go b/server/ccmenu/cc_test.go index e2b17f513..7cecdad63 100644 --- a/server/ccmenu/cc_test.go +++ b/server/ccmenu/cc_test.go @@ -19,82 +19,79 @@ import ( "testing" "time" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/model" ) func TestCC(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("CC", func() { - g.It("Should create a project", func() { - now := time.Now().Unix() - nowFmt := time.Unix(now, 0).Format(time.RFC3339) - r := &model.Repo{ - FullName: "foo/bar", - } - b := &model.Pipeline{ - Status: model.StatusSuccess, - Number: 1, - Started: now, - } - cc := New(r, b, "http://localhost/foo/bar/1") + t.Run("create a project", func(t *testing.T) { + now := time.Now().Unix() + nowFmt := time.Unix(now, 0).Format(time.RFC3339) + r := &model.Repo{ + FullName: "foo/bar", + } + b := &model.Pipeline{ + Status: model.StatusSuccess, + Number: 1, + Started: now, + } + cc := New(r, b, "http://localhost/foo/bar/1") - g.Assert(cc.Project.Name).Equal("foo/bar") - g.Assert(cc.Project.Activity).Equal("Sleeping") - g.Assert(cc.Project.LastBuildStatus).Equal("Success") - g.Assert(cc.Project.LastBuildLabel).Equal("1") - g.Assert(cc.Project.LastBuildTime).Equal(nowFmt) - g.Assert(cc.Project.WebURL).Equal("http://localhost/foo/bar/1") - }) + assert.Equal(t, "foo/bar", cc.Project.Name) + assert.Equal(t, "Sleeping", cc.Project.Activity) + assert.Equal(t, "Success", cc.Project.LastBuildStatus) + assert.Equal(t, "1", cc.Project.LastBuildLabel) + assert.Equal(t, nowFmt, cc.Project.LastBuildTime) + assert.Equal(t, "http://localhost/foo/bar/1", cc.Project.WebURL) + }) - g.It("Should properly label exceptions", func() { - r := &model.Repo{FullName: "foo/bar"} - b := &model.Pipeline{ - Status: model.StatusError, - Number: 1, - Started: 1257894000, - } - cc := New(r, b, "http://localhost/foo/bar/1") - g.Assert(cc.Project.LastBuildStatus).Equal("Exception") - g.Assert(cc.Project.Activity).Equal("Sleeping") - }) + t.Run("properly label exceptions", func(t *testing.T) { + r := &model.Repo{FullName: "foo/bar"} + b := &model.Pipeline{ + Status: model.StatusError, + Number: 1, + Started: 1257894000, + } + cc := New(r, b, "http://localhost/foo/bar/1") + assert.Equal(t, "Exception", cc.Project.LastBuildStatus) + assert.Equal(t, "Sleeping", cc.Project.Activity) + }) - g.It("Should properly label success", func() { - r := &model.Repo{FullName: "foo/bar"} - b := &model.Pipeline{ - Status: model.StatusSuccess, - Number: 1, - Started: 1257894000, - } - cc := New(r, b, "http://localhost/foo/bar/1") - g.Assert(cc.Project.LastBuildStatus).Equal("Success") - g.Assert(cc.Project.Activity).Equal("Sleeping") - }) + t.Run("properly label success", func(t *testing.T) { + r := &model.Repo{FullName: "foo/bar"} + b := &model.Pipeline{ + Status: model.StatusSuccess, + Number: 1, + Started: 1257894000, + } + cc := New(r, b, "http://localhost/foo/bar/1") + assert.Equal(t, "Success", cc.Project.LastBuildStatus) + assert.Equal(t, "Sleeping", cc.Project.Activity) + }) - g.It("Should properly label failure", func() { - r := &model.Repo{FullName: "foo/bar"} - b := &model.Pipeline{ - Status: model.StatusFailure, - Number: 1, - Started: 1257894000, - } - cc := New(r, b, "http://localhost/foo/bar/1") - g.Assert(cc.Project.LastBuildStatus).Equal("Failure") - g.Assert(cc.Project.Activity).Equal("Sleeping") - }) + t.Run("properly label failure", func(t *testing.T) { + r := &model.Repo{FullName: "foo/bar"} + b := &model.Pipeline{ + Status: model.StatusFailure, + Number: 1, + Started: 1257894000, + } + cc := New(r, b, "http://localhost/foo/bar/1") + assert.Equal(t, "Failure", cc.Project.LastBuildStatus) + assert.Equal(t, "Sleeping", cc.Project.Activity) + }) - g.It("Should properly label running", func() { - r := &model.Repo{FullName: "foo/bar"} - b := &model.Pipeline{ - Status: model.StatusRunning, - Number: 1, - Started: 1257894000, - } - cc := New(r, b, "http://localhost/foo/bar/1") - g.Assert(cc.Project.Activity).Equal("Building") - g.Assert(cc.Project.LastBuildStatus).Equal("Unknown") - g.Assert(cc.Project.LastBuildLabel).Equal("Unknown") - }) + t.Run("properly label running", func(t *testing.T) { + r := &model.Repo{FullName: "foo/bar"} + b := &model.Pipeline{ + Status: model.StatusRunning, + Number: 1, + Started: 1257894000, + } + cc := New(r, b, "http://localhost/foo/bar/1") + assert.Equal(t, "Building", cc.Project.Activity) + assert.Equal(t, "Unknown", cc.Project.LastBuildStatus) + assert.Equal(t, "Unknown", cc.Project.LastBuildLabel) }) } diff --git a/server/forge/bitbucket/bitbucket_test.go b/server/forge/bitbucket/bitbucket_test.go index a4fe537d1..c074cfcf2 100644 --- a/server/forge/bitbucket/bitbucket_test.go +++ b/server/forge/bitbucket/bitbucket_test.go @@ -18,13 +18,12 @@ package bitbucket import ( "bytes" "context" - "errors" "net/http" "net/http/httptest" "testing" - "github.com/franela/goblin" "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/internal" @@ -32,263 +31,182 @@ import ( "go.woodpecker-ci.org/woodpecker/v3/server/model" ) -func Test_bitbucket(t *testing.T) { +func TestNew(t *testing.T) { + forge, _ := New(&Opts{Client: "4vyW6b49Z", Secret: "a5012f6c6"}) + + f, _ := forge.(*config) + assert.Equal(t, DefaultURL, f.url) + assert.Equal(t, DefaultAPI, f.API) + assert.Equal(t, "4vyW6b49Z", f.Client) + assert.Equal(t, "a5012f6c6", f.Secret) +} + +func TestBitbucket(t *testing.T) { gin.SetMode(gin.TestMode) s := httptest.NewServer(fixtures.Handler()) + defer s.Close() c := &config{url: s.URL, API: s.URL} - g := goblin.Goblin(t) ctx := context.Background() - g.Describe("Bitbucket client", func() { - g.After(func() { - s.Close() - }) - g.It("Should return client with default endpoint", func() { - forge, _ := New(&Opts{Client: "4vyW6b49Z", Secret: "a5012f6c6"}) + forge, _ := New(&Opts{}) + netrc, _ := forge.Netrc(fakeUser, fakeRepo) + assert.Equal(t, "bitbucket.org", netrc.Machine) + assert.Equal(t, "x-token-auth", netrc.Login) + assert.Equal(t, fakeUser.AccessToken, netrc.Password) - f, _ := forge.(*config) - g.Assert(f.url).Equal(DefaultURL) - g.Assert(f.API).Equal(DefaultAPI) - g.Assert(f.Client).Equal("4vyW6b49Z") - g.Assert(f.Secret).Equal("a5012f6c6") - }) + user, _, err := c.Login(ctx, &types.OAuthRequest{}) + assert.NoError(t, err) + assert.Nil(t, user) - g.It("Should return the netrc file", func() { - forge, _ := New(&Opts{}) - netrc, _ := forge.Netrc(fakeUser, fakeRepo) - g.Assert(netrc.Machine).Equal("bitbucket.org") - g.Assert(netrc.Login).Equal("x-token-auth") - g.Assert(netrc.Password).Equal(fakeUser.AccessToken) - }) - - g.Describe("Given an authorization request", func() { - g.It("Should redirect to authorize", func() { - user, _, err := c.Login(ctx, &types.OAuthRequest{}) - g.Assert(err).IsNil() - g.Assert(user).IsNil() - }) - g.It("Should return authenticated user", func() { - u, _, err := c.Login(ctx, &types.OAuthRequest{ - Code: "code", - }) - g.Assert(err).IsNil() - g.Assert(u.Login).Equal(fakeUser.Login) - g.Assert(u.AccessToken).Equal("2YotnFZFEjr1zCsicMWpAA") - g.Assert(u.RefreshToken).Equal("tGzv3JOkF0XG5Qx2TlKWIA") - }) - g.It("Should handle failure to exchange code", func() { - _, _, err := c.Login(ctx, &types.OAuthRequest{ - Code: "code_bad_request", - }) - g.Assert(err).IsNotNil() - }) - g.It("Should handle failure to resolve user", func() { - _, _, err := c.Login(ctx, &types.OAuthRequest{ - Code: "code_user_not_found", - }) - g.Assert(err).IsNotNil() - }) - }) - - g.Describe("Given an access token", func() { - g.It("Should return the authenticated user", func() { - login, err := c.Auth(ctx, fakeUser.AccessToken, fakeUser.RefreshToken) - g.Assert(err).IsNil() - g.Assert(login).Equal(fakeUser.Login) - }) - g.It("Should handle a failure to resolve user", func() { - _, err := c.Auth(ctx, fakeUserNotFound.AccessToken, fakeUserNotFound.RefreshToken) - g.Assert(err).IsNotNil() - }) - }) - - g.Describe("Given a refresh token", func() { - g.It("Should return a refresh access token", func() { - ok, err := c.Refresh(ctx, fakeUserRefresh) - g.Assert(err).IsNil() - g.Assert(ok).IsTrue() - g.Assert(fakeUserRefresh.AccessToken).Equal("2YotnFZFEjr1zCsicMWpAA") - g.Assert(fakeUserRefresh.RefreshToken).Equal("tGzv3JOkF0XG5Qx2TlKWIA") - }) - g.It("Should handle an empty access token", func() { - ok, err := c.Refresh(ctx, fakeUserRefreshEmpty) - g.Assert(err).IsNotNil() - g.Assert(ok).IsFalse() - }) - g.It("Should handle a failure to refresh", func() { - ok, err := c.Refresh(ctx, fakeUserRefreshFail) - g.Assert(err).IsNotNil() - g.Assert(ok).IsFalse() - }) - }) - - g.Describe("When requesting a repository", func() { - g.It("Should return the details", func() { - repo, err := c.Repo(ctx, fakeUser, "", fakeRepo.Owner, fakeRepo.Name) - g.Assert(err).IsNil() - g.Assert(repo.FullName).Equal(fakeRepo.FullName) - }) - g.It("Should handle not found errors", func() { - _, err := c.Repo(ctx, fakeUser, "", fakeRepoNotFound.Owner, fakeRepoNotFound.Name) - g.Assert(err).IsNotNil() - }) - }) - - g.Describe("When requesting user repositories", func() { - g.It("Should return the details", func() { - repos, err := c.Repos(ctx, fakeUser) - g.Assert(err).IsNil() - g.Assert(repos[0].FullName).Equal(fakeRepo.FullName) - }) - g.It("Should handle organization not found errors", func() { - _, err := c.Repos(ctx, fakeUserNoTeams) - g.Assert(err).IsNotNil() - }) - g.It("Should handle not found errors", func() { - _, err := c.Repos(ctx, fakeUserNoRepos) - g.Assert(err).IsNotNil() - }) - }) - - g.Describe("When requesting user teams", func() { - g.It("Should return the details", func() { - teams, err := c.Teams(ctx, fakeUser) - g.Assert(err).IsNil() - g.Assert(teams[0].Login).Equal("ueberdev42") - g.Assert(teams[0].Avatar).Equal("https://bitbucket.org/workspaces/ueberdev42/avatar/?ts=1658761964") - }) - g.It("Should handle not found error", func() { - _, err := c.Teams(ctx, fakeUserNoTeams) - g.Assert(err).IsNotNil() - }) - }) - - g.Describe("When downloading a file", func() { - g.It("Should return the bytes", func() { - raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, "file") - g.Assert(err).IsNil() - g.Assert(len(raw) != 0).IsTrue() - }) - g.It("Should handle not found error", func() { - _, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, "file_not_found") - g.Assert(err).IsNotNil() - g.Assert(errors.Is(err, &types.ErrConfigNotFound{})).IsTrue() - }) - }) - - g.Describe("When requesting repo branch HEAD", func() { - g.It("Should return the details", func() { - branchHead, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_name") - g.Assert(err).IsNil() - g.Assert(branchHead.SHA).Equal("branch_head_name") - g.Assert(branchHead.ForgeURL).Equal("https://bitbucket.org/commitlink") - }) - g.It("Should handle not found errors", func() { - _, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_not_found") - g.Assert(err).IsNotNil() - }) - }) - - g.Describe("When requesting repo pull requests", func() { - listOpts := model.ListOptions{ - All: false, - Page: 1, - PerPage: 10, - } - g.It("Should return the details", func() { - repoPRs, err := c.PullRequests(ctx, fakeUser, fakeRepo, &listOpts) - g.Assert(err).IsNil() - g.Assert(repoPRs[0].Title).Equal("PRs title") - g.Assert(repoPRs[0].Index).Equal(model.ForgeRemoteID("123")) - }) - g.It("Should handle not found errors", func() { - _, err := c.PullRequests(ctx, fakeUser, fakeRepoNotFound, &listOpts) - g.Assert(err).IsNotNil() - }) - }) - - g.Describe("When requesting repo directory contents", func() { - g.It("Should return the details", func() { - files, err := c.Dir(ctx, fakeUser, fakeRepo, fakePipeline, "dir") - g.Assert(err).IsNil() - g.Assert(len(files)).Equal(3) - g.Assert(files[0].Name).Equal("README.md") - g.Assert(string(files[0].Data)).Equal("dummy payload") - }) - g.It("Should handle not found errors", func() { - _, err := c.Dir(ctx, fakeUser, fakeRepo, fakePipeline, "dir_not_found") - g.Assert(err).IsNotNil() - g.Assert(errors.Is(err, &types.ErrConfigNotFound{})).IsTrue() - }) - }) - - g.Describe("When activating a repository", func() { - g.It("Should error when malformed hook", func() { - err := c.Activate(ctx, fakeUser, fakeRepo, "%gh&%ij") - g.Assert(err).IsNotNil() - }) - g.It("Should create the hook", func() { - err := c.Activate(ctx, fakeUser, fakeRepo, "http://127.0.0.1") - g.Assert(err).IsNil() - }) - }) - - g.Describe("When deactivating a repository", func() { - g.It("Should error when listing hooks fails", func() { - err := c.Deactivate(ctx, fakeUser, fakeRepoNoHooks, "http://127.0.0.1") - g.Assert(err).IsNotNil() - }) - g.It("Should successfully remove hooks", func() { - err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://127.0.0.1") - g.Assert(err).IsNil() - }) - g.It("Should successfully deactivate when hook already removed", func() { - err := c.Deactivate(ctx, fakeUser, fakeRepoEmptyHook, "http://127.0.0.1") - g.Assert(err).IsNil() - }) - }) - - g.Describe("Given a list of hooks", func() { - g.It("Should return the matching hook", func() { - hooks := []*internal.Hook{ - {URL: "http://127.0.0.1/hook"}, - } - hook := matchingHooks(hooks, "http://127.0.0.1/") - g.Assert(hook).Equal(hooks[0]) - }) - g.It("Should handle no matches", func() { - hooks := []*internal.Hook{ - {URL: "http://localhost/hook"}, - } - hook := matchingHooks(hooks, "http://127.0.0.1/") - g.Assert(hook).IsNil() - }) - g.It("Should handle malformed hook urls", func() { - var hooks []*internal.Hook - hook := matchingHooks(hooks, "%gh&%ij") - g.Assert(hook).IsNil() - }) - }) - - g.It("Should update the status", func() { - err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow) - g.Assert(err).IsNil() - }) - - g.It("Should parse the hook", func() { - buf := bytes.NewBufferString(fixtures.HookPush) - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPush) - - r, b, err := c.Hook(ctx, req) - g.Assert(err).IsNil() - g.Assert(r.FullName).Equal("martinherren1984/publictestrepo") - g.Assert(b.Commit).Equal("c14c1bb05dfb1fdcdf06b31485fff61b0ea44277") - }) + u, _, err := c.Login(ctx, &types.OAuthRequest{ + Code: "code", }) + assert.NoError(t, err) + assert.Equal(t, fakeUser.Login, u.Login) + assert.Equal(t, "2YotnFZFEjr1zCsicMWpAA", u.AccessToken) + assert.Equal(t, "tGzv3JOkF0XG5Qx2TlKWIA", u.RefreshToken) + + _, _, err = c.Login(ctx, &types.OAuthRequest{ + Code: "code_bad_request", + }) + assert.Error(t, err) + + _, _, err = c.Login(ctx, &types.OAuthRequest{ + Code: "code_user_not_found", + }) + assert.Error(t, err) + + login, err := c.Auth(ctx, fakeUser.AccessToken, fakeUser.RefreshToken) + assert.NoError(t, err) + assert.Equal(t, fakeUser.Login, login) + + _, err = c.Auth(ctx, fakeUserNotFound.AccessToken, fakeUserNotFound.RefreshToken) + assert.Error(t, err) + + ok, err := c.Refresh(ctx, fakeUserRefresh) + assert.NoError(t, err) + assert.True(t, ok) + assert.Equal(t, "2YotnFZFEjr1zCsicMWpAA", fakeUserRefresh.AccessToken) + assert.Equal(t, "tGzv3JOkF0XG5Qx2TlKWIA", fakeUserRefresh.RefreshToken) + + ok, err = c.Refresh(ctx, fakeUserRefreshEmpty) + assert.Error(t, err) + assert.False(t, ok) + + ok, err = c.Refresh(ctx, fakeUserRefreshFail) + assert.Error(t, err) + assert.False(t, ok) + + repo, err := c.Repo(ctx, fakeUser, "", fakeRepo.Owner, fakeRepo.Name) + assert.NoError(t, err) + assert.Equal(t, fakeRepo.FullName, repo.FullName) + + _, err = c.Repo(ctx, fakeUser, "", fakeRepoNotFound.Owner, fakeRepoNotFound.Name) + assert.Error(t, err) + + repos, err := c.Repos(ctx, fakeUser) + assert.NoError(t, err) + assert.Equal(t, fakeRepo.FullName, repos[0].FullName) + + _, err = c.Repos(ctx, fakeUserNoTeams) + assert.Error(t, err) + + _, err = c.Repos(ctx, fakeUserNoRepos) + assert.Error(t, err) + + teams, err := c.Teams(ctx, fakeUser) + assert.NoError(t, err) + assert.Equal(t, "ueberdev42", teams[0].Login) + assert.Equal(t, "https://bitbucket.org/workspaces/ueberdev42/avatar/?ts=1658761964", teams[0].Avatar) + + _, err = c.Teams(ctx, fakeUserNoTeams) + assert.Error(t, err) + + raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, "file") + assert.NoError(t, err) + assert.True(t, len(raw) != 0) + + _, err = c.File(ctx, fakeUser, fakeRepo, fakePipeline, "file_not_found") + assert.Error(t, err) + assert.ErrorIs(t, err, &types.ErrConfigNotFound{}) + + branchHead, err := c.BranchHead(ctx, fakeUser, fakeRepo, "branch_name") + assert.NoError(t, err) + assert.Equal(t, "branch_head_name", branchHead.SHA) + assert.Equal(t, "https://bitbucket.org/commitlink", branchHead.ForgeURL) + + _, err = c.BranchHead(ctx, fakeUser, fakeRepo, "branch_not_found") + assert.Error(t, err) + + listOpts := model.ListOptions{ + All: false, + Page: 1, + PerPage: 10, + } + + repoPRs, err := c.PullRequests(ctx, fakeUser, fakeRepo, &listOpts) + assert.NoError(t, err) + assert.Equal(t, "PRs title", repoPRs[0].Title) + assert.Equal(t, model.ForgeRemoteID("123"), repoPRs[0].Index) + + _, err = c.PullRequests(ctx, fakeUser, fakeRepoNotFound, &listOpts) + assert.Error(t, err) + + files, err := c.Dir(ctx, fakeUser, fakeRepo, fakePipeline, "dir") + assert.NoError(t, err) + assert.Len(t, files, 3) + assert.Equal(t, "README.md", files[0].Name) + assert.Equal(t, "dummy payload", string(files[0].Data)) + + _, err = c.Dir(ctx, fakeUser, fakeRepo, fakePipeline, "dir_not_found") + assert.Error(t, err) + assert.ErrorIs(t, err, &types.ErrConfigNotFound{}) + + err = c.Activate(ctx, fakeUser, fakeRepo, "%gh&%ij") + assert.Error(t, err) + + err = c.Activate(ctx, fakeUser, fakeRepo, "http://127.0.0.1") + assert.NoError(t, err) + + err = c.Deactivate(ctx, fakeUser, fakeRepoNoHooks, "http://127.0.0.1") + assert.Error(t, err) + + err = c.Deactivate(ctx, fakeUser, fakeRepo, "http://127.0.0.1") + assert.NoError(t, err) + + err = c.Deactivate(ctx, fakeUser, fakeRepoEmptyHook, "http://127.0.0.1") + assert.NoError(t, err) + + hooks := []*internal.Hook{ + {URL: "http://127.0.0.1/hook"}, + } + hook := matchingHooks(hooks, "http://127.0.0.1/") + assert.Equal(t, hooks[0], hook) + + hooks = []*internal.Hook{ + {URL: "http://localhost/hook"}, + } + hook = matchingHooks(hooks, "http://127.0.0.1/") + assert.Nil(t, hook) + + hooks = nil + hook = matchingHooks(hooks, "%gh&%ij") + assert.Nil(t, hook) + + err = c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow) + assert.NoError(t, err) + + buf := bytes.NewBufferString(fixtures.HookPush) + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPush) + + r, b, err := c.Hook(ctx, req) + assert.NoError(t, err) + assert.Equal(t, "martinherren1984/publictestrepo", r.FullName) + assert.Equal(t, "c14c1bb05dfb1fdcdf06b31485fff61b0ea44277", b.Commit) } var ( diff --git a/server/forge/bitbucket/convert_test.go b/server/forge/bitbucket/convert_test.go index e28d3926d..5f450cc03 100644 --- a/server/forge/bitbucket/convert_test.go +++ b/server/forge/bitbucket/convert_test.go @@ -19,169 +19,158 @@ import ( "testing" "time" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" "golang.org/x/oauth2" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/internal" "go.woodpecker-ci.org/woodpecker/v3/server/model" ) -func Test_helper(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("Bitbucket converter", func() { - g.It("should convert passing status", func() { - g.Assert(convertStatus(model.StatusSuccess)).Equal(statusSuccess) - }) - - g.It("should convert pending status", func() { - g.Assert(convertStatus(model.StatusPending)).Equal(statusPending) - g.Assert(convertStatus(model.StatusRunning)).Equal(statusPending) - }) - - g.It("should convert failing status", func() { - g.Assert(convertStatus(model.StatusFailure)).Equal(statusFailure) - g.Assert(convertStatus(model.StatusKilled)).Equal(statusFailure) - g.Assert(convertStatus(model.StatusError)).Equal(statusFailure) - }) - - g.It("should convert repository", func() { - from := &internal.Repo{ - FullName: "octocat/hello-world", - IsPrivate: true, - Scm: "git", - } - from.Owner.Links.Avatar.Href = "http://..." - from.Links.HTML.Href = "https://bitbucket.org/foo/bar" - fromPerm := &internal.RepoPerm{ - Permission: "write", - } - - to := convertRepo(from, fromPerm) - g.Assert(to.Avatar).Equal(from.Owner.Links.Avatar.Href) - g.Assert(to.FullName).Equal(from.FullName) - g.Assert(to.Owner).Equal("octocat") - g.Assert(to.Name).Equal("hello-world") - g.Assert(to.IsSCMPrivate).Equal(from.IsPrivate) - g.Assert(to.Clone).Equal(from.Links.HTML.Href) - g.Assert(to.ForgeURL).Equal(from.Links.HTML.Href) - g.Assert(to.Perm.Push).IsTrue() - g.Assert(to.Perm.Admin).IsFalse() - }) - - g.It("should convert team", func() { - from := &internal.Workspace{Slug: "octocat"} - from.Links.Avatar.Href = "http://..." - to := convertWorkspace(from) - g.Assert(to.Avatar).Equal(from.Links.Avatar.Href) - g.Assert(to.Login).Equal(from.Slug) - }) - - g.It("should convert team list", func() { - from := &internal.Workspace{Slug: "octocat"} - from.Links.Avatar.Href = "http://..." - to := convertWorkspaceList([]*internal.Workspace{from}) - g.Assert(to[0].Avatar).Equal(from.Links.Avatar.Href) - g.Assert(to[0].Login).Equal(from.Slug) - }) - - g.It("should convert user", func() { - token := &oauth2.Token{ - AccessToken: "foo", - RefreshToken: "bar", - Expiry: time.Now(), - } - user := &internal.Account{Login: "octocat"} - user.Links.Avatar.Href = "http://..." - - result := convertUser(user, token) - g.Assert(result.Avatar).Equal(user.Links.Avatar.Href) - g.Assert(result.Login).Equal(user.Login) - g.Assert(result.AccessToken).Equal(token.AccessToken) - g.Assert(result.RefreshToken).Equal(token.RefreshToken) - g.Assert(result.Expiry).Equal(token.Expiry.UTC().Unix()) - }) - - g.It("should use clone url", func() { - repo := &internal.Repo{} - repo.Links.Clone = append(repo.Links.Clone, internal.Link{ - Name: "https", - Href: "https://bitbucket.org/foo/bar.git", - }) - link := cloneLink(repo) - g.Assert(link).Equal(repo.Links.Clone[0].Href) - }) - - g.It("should build clone url", func() { - repo := &internal.Repo{} - repo.Links.HTML.Href = "https://foo:bar@bitbucket.org/foo/bar.git" - link := cloneLink(repo) - g.Assert(link).Equal("https://bitbucket.org/foo/bar.git") - }) - - g.It("should convert pull hook to pipeline", func() { - hook := &internal.PullRequestHook{} - hook.Actor.Login = "octocat" - hook.Actor.Links.Avatar.Href = "https://..." - hook.PullRequest.Dest.Commit.Hash = "73f9c44d" - hook.PullRequest.Dest.Branch.Name = "main" - hook.PullRequest.Dest.Repo.Links.HTML.Href = "https://bitbucket.org/foo/bar" - hook.PullRequest.Source.Branch.Name = "change" - hook.PullRequest.Source.Repo.FullName = "baz/bar" - hook.PullRequest.Source.Commit.Hash = "c8411d7" - hook.PullRequest.Links.HTML.Href = "https://bitbucket.org/foo/bar/pulls/5" - hook.PullRequest.Title = "updated README" - hook.PullRequest.Updated = time.Now() - hook.PullRequest.ID = 1 - - pipeline := convertPullHook(hook) - g.Assert(pipeline.Event).Equal(model.EventPull) - g.Assert(pipeline.Author).Equal(hook.Actor.Login) - g.Assert(pipeline.Avatar).Equal(hook.Actor.Links.Avatar.Href) - g.Assert(pipeline.Commit).Equal(hook.PullRequest.Source.Commit.Hash) - g.Assert(pipeline.Branch).Equal(hook.PullRequest.Source.Branch.Name) - g.Assert(pipeline.ForgeURL).Equal(hook.PullRequest.Links.HTML.Href) - g.Assert(pipeline.Ref).Equal("refs/pull-requests/1/from") - g.Assert(pipeline.Refspec).Equal("change:main") - g.Assert(pipeline.Message).Equal(hook.PullRequest.Title) - g.Assert(pipeline.Timestamp).Equal(hook.PullRequest.Updated.Unix()) - }) - - g.It("should convert push hook to pipeline", func() { - change := internal.Change{} - change.New.Target.Hash = "73f9c44d" - change.New.Name = "main" - change.New.Target.Links.HTML.Href = "https://bitbucket.org/foo/bar/commits/73f9c44d" - change.New.Target.Message = "updated README" - change.New.Target.Date = time.Now() - change.New.Target.Author.Raw = "Test " - - hook := internal.PushHook{} - hook.Actor.Login = "octocat" - hook.Actor.Links.Avatar.Href = "https://..." - - pipeline := convertPushHook(&hook, &change) - g.Assert(pipeline.Event).Equal(model.EventPush) - g.Assert(pipeline.Email).Equal("test@domain.tld") - g.Assert(pipeline.Author).Equal(hook.Actor.Login) - g.Assert(pipeline.Avatar).Equal(hook.Actor.Links.Avatar.Href) - g.Assert(pipeline.Commit).Equal(change.New.Target.Hash) - g.Assert(pipeline.Branch).Equal(change.New.Name) - g.Assert(pipeline.ForgeURL).Equal(change.New.Target.Links.HTML.Href) - g.Assert(pipeline.Ref).Equal("refs/heads/main") - g.Assert(pipeline.Message).Equal(change.New.Target.Message) - g.Assert(pipeline.Timestamp).Equal(change.New.Target.Date.Unix()) - }) - - g.It("should convert tag hook to pipeline", func() { - change := internal.Change{} - change.New.Name = "v1.0.0" - change.New.Type = "tag" - - hook := internal.PushHook{} - - pipeline := convertPushHook(&hook, &change) - g.Assert(pipeline.Event).Equal(model.EventTag) - g.Assert(pipeline.Ref).Equal("refs/tags/v1.0.0") - }) - }) +func Test_convertStatus(t *testing.T) { + assert.Equal(t, statusSuccess, convertStatus(model.StatusSuccess)) + assert.Equal(t, statusPending, convertStatus(model.StatusPending)) + assert.Equal(t, statusPending, convertStatus(model.StatusRunning)) + assert.Equal(t, statusFailure, convertStatus(model.StatusFailure)) + assert.Equal(t, statusFailure, convertStatus(model.StatusKilled)) + assert.Equal(t, statusFailure, convertStatus(model.StatusError)) +} + +func Test_convertRepo(t *testing.T) { + from := &internal.Repo{ + FullName: "octocat/hello-world", + IsPrivate: true, + Scm: "git", + } + from.Owner.Links.Avatar.Href = "http://..." + from.Links.HTML.Href = "https://bitbucket.org/foo/bar" + from.MainBranch.Name = "default" + fromPerm := &internal.RepoPerm{ + Permission: "write", + } + + to := convertRepo(from, fromPerm) + assert.Equal(t, from.Owner.Links.Avatar.Href, to.Avatar) + assert.Equal(t, from.FullName, to.FullName) + assert.Equal(t, "octocat", to.Owner) + assert.Equal(t, "hello-world", to.Name) + assert.Equal(t, "default", to.Branch) + assert.Equal(t, from.IsPrivate, to.IsSCMPrivate) + assert.Equal(t, from.Links.HTML.Href, to.Clone) + assert.Equal(t, from.Links.HTML.Href, to.ForgeURL) + assert.True(t, to.Perm.Push) + assert.False(t, to.Perm.Admin) +} + +func Test_convertWorkspace(t *testing.T) { + from := &internal.Workspace{Slug: "octocat"} + from.Links.Avatar.Href = "http://..." + to := convertWorkspace(from) + assert.Equal(t, from.Links.Avatar.Href, to.Avatar) + assert.Equal(t, from.Slug, to.Login) +} + +func Test_convertWorkspaceList(t *testing.T) { + from := &internal.Workspace{Slug: "octocat"} + from.Links.Avatar.Href = "http://..." + to := convertWorkspaceList([]*internal.Workspace{from}) + assert.Equal(t, from.Links.Avatar.Href, to[0].Avatar) + assert.Equal(t, from.Slug, to[0].Login) +} + +func Test_convertUser(t *testing.T) { + token := &oauth2.Token{ + AccessToken: "foo", + RefreshToken: "bar", + Expiry: time.Now(), + } + user := &internal.Account{Login: "octocat"} + user.Links.Avatar.Href = "http://..." + + result := convertUser(user, token) + assert.Equal(t, user.Links.Avatar.Href, result.Avatar) + assert.Equal(t, user.Login, result.Login) + assert.Equal(t, token.AccessToken, result.AccessToken) + assert.Equal(t, token.RefreshToken, result.RefreshToken) + assert.Equal(t, token.Expiry.UTC().Unix(), result.Expiry) +} + +func Test_cloneLink(t *testing.T) { + repo := &internal.Repo{} + repo.Links.Clone = append(repo.Links.Clone, internal.Link{ + Name: "https", + Href: "https://bitbucket.org/foo/bar.git", + }) + link := cloneLink(repo) + assert.Equal(t, repo.Links.Clone[0].Href, link) + + repo = &internal.Repo{} + repo.Links.HTML.Href = "https://foo:bar@bitbucket.org/foo/bar.git" + link = cloneLink(repo) + assert.Equal(t, "https://bitbucket.org/foo/bar.git", link) +} + +func Test_convertPullHook(t *testing.T) { + hook := &internal.PullRequestHook{} + hook.Actor.Login = "octocat" + hook.Actor.Links.Avatar.Href = "https://..." + hook.PullRequest.Dest.Commit.Hash = "73f9c44d" + hook.PullRequest.Dest.Branch.Name = "main" + hook.PullRequest.Dest.Repo.Links.HTML.Href = "https://bitbucket.org/foo/bar" + hook.PullRequest.Source.Branch.Name = "change" + hook.PullRequest.Source.Repo.FullName = "baz/bar" + hook.PullRequest.Source.Commit.Hash = "c8411d7" + hook.PullRequest.Links.HTML.Href = "https://bitbucket.org/foo/bar/pulls/5" + hook.PullRequest.Title = "updated README" + hook.PullRequest.Updated = time.Now() + hook.PullRequest.ID = 1 + + pipeline := convertPullHook(hook) + assert.Equal(t, model.EventPull, pipeline.Event) + assert.Equal(t, hook.Actor.Login, pipeline.Author) + assert.Equal(t, hook.Actor.Links.Avatar.Href, pipeline.Avatar) + assert.Equal(t, hook.PullRequest.Source.Commit.Hash, pipeline.Commit) + assert.Equal(t, hook.PullRequest.Source.Branch.Name, pipeline.Branch) + assert.Equal(t, hook.PullRequest.Links.HTML.Href, pipeline.ForgeURL) + assert.Equal(t, "refs/pull-requests/1/from", pipeline.Ref) + assert.Equal(t, "change:main", pipeline.Refspec) + assert.Equal(t, hook.PullRequest.Title, pipeline.Message) + assert.Equal(t, hook.PullRequest.Updated.Unix(), pipeline.Timestamp) +} + +func Test_convertPushHook(t *testing.T) { + change := internal.Change{} + change.New.Target.Hash = "73f9c44d" + change.New.Name = "main" + change.New.Target.Links.HTML.Href = "https://bitbucket.org/foo/bar/commits/73f9c44d" + change.New.Target.Message = "updated README" + change.New.Target.Date = time.Now() + change.New.Target.Author.Raw = "Test " + + hook := internal.PushHook{} + hook.Actor.Login = "octocat" + hook.Actor.Links.Avatar.Href = "https://..." + + pipeline := convertPushHook(&hook, &change) + assert.Equal(t, model.EventPush, pipeline.Event) + assert.Equal(t, "test@domain.tld", pipeline.Email) + assert.Equal(t, hook.Actor.Login, pipeline.Author) + assert.Equal(t, hook.Actor.Links.Avatar.Href, pipeline.Avatar) + assert.Equal(t, change.New.Target.Hash, pipeline.Commit) + assert.Equal(t, change.New.Name, pipeline.Branch) + assert.Equal(t, change.New.Target.Links.HTML.Href, pipeline.ForgeURL) + assert.Equal(t, "refs/heads/main", pipeline.Ref) + assert.Equal(t, change.New.Target.Message, pipeline.Message) + assert.Equal(t, change.New.Target.Date.Unix(), pipeline.Timestamp) +} + +func Test_convertPushHookTag(t *testing.T) { + change := internal.Change{} + change.New.Name = "v1.0.0" + change.New.Type = "tag" + + hook := internal.PushHook{} + + pipeline := convertPushHook(&hook, &change) + assert.Equal(t, model.EventTag, pipeline.Event) + assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref) } diff --git a/server/forge/bitbucket/parse_test.go b/server/forge/bitbucket/parse_test.go index 0a92ef734..f0afb5102 100644 --- a/server/forge/bitbucket/parse_test.go +++ b/server/forge/bitbucket/parse_test.go @@ -1,4 +1,4 @@ -// Copyright 2018 Drone.IO Inc. +// // Copyright 2018 Drone.IO Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ import ( "net/http" "testing" - "github.com/franela/goblin" "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucket/fixtures" @@ -27,112 +26,101 @@ import ( "go.woodpecker-ci.org/woodpecker/v3/server/model" ) -func Test_parser(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("Bitbucket parser", func() { - g.It("should ignore unsupported hook", func() { - buf := bytes.NewBufferString(fixtures.HookPush) - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, "issue:created") +func Test_parseHook(t *testing.T) { + t.Run("unsupported hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPush) + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, "issue:created") - r, b, err := parseHook(req) - g.Assert(r).IsNil() - g.Assert(b).IsNil() - assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) - }) + r, b, err := parseHook(req) + assert.Nil(t, r) + assert.Nil(t, b) + assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) + }) - g.Describe("Given a pull-request hook payload", func() { - g.It("should return err when malformed", func() { - buf := bytes.NewBufferString("[]") - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPullCreated) + t.Run("malformed pull-request hook", func(t *testing.T) { + buf := bytes.NewBufferString("[]") + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPullCreated) - _, _, err := parseHook(req) - g.Assert(err).IsNotNil() - }) + _, _, err := parseHook(req) + assert.Error(t, err) + }) - g.It("should return pull-request details", func() { - buf := bytes.NewBufferString(fixtures.HookPull) - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPullCreated) + t.Run("pull-request", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPull) + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPullCreated) - r, b, err := parseHook(req) - g.Assert(err).IsNil() - g.Assert(r.FullName).Equal("user_name/repo_name") - g.Assert(b.Event).Equal(model.EventPull) - g.Assert(b.Commit).Equal("d3022fc0ca3d") - }) + r, b, err := parseHook(req) + assert.NoError(t, err) + assert.Equal(t, "user_name/repo_name", r.FullName) + assert.Equal(t, model.EventPull, b.Event) + assert.Equal(t, "d3022fc0ca3d", b.Commit) + }) - g.It("should return pull-request details for a pull-request merged payload", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequestMerged) - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPullMerged) + t.Run("pull-request merged", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequestMerged) + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPullMerged) - r, b, err := parseHook(req) - g.Assert(err).IsNil() - g.Assert(r.FullName).Equal("anbraten/test-2") - g.Assert(b.Event).Equal(model.EventPullClosed) - g.Assert(b.Commit).Equal("006704dbeab2") - }) + r, b, err := parseHook(req) + assert.NoError(t, err) + assert.Equal(t, "anbraten/test-2", r.FullName) + assert.Equal(t, model.EventPullClosed, b.Event) + assert.Equal(t, "006704dbeab2", b.Commit) + }) - g.It("should return pull-request details for a pull-request closed payload", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequestDeclined) - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPullDeclined) + t.Run("pull-request closed", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequestDeclined) + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPullDeclined) - r, b, err := parseHook(req) - g.Assert(err).IsNil() - g.Assert(r.FullName).Equal("anbraten/test-2") - g.Assert(b.Event).Equal(model.EventPullClosed) - g.Assert(b.Commit).Equal("f90e18fc9d45") - }) - }) + r, b, err := parseHook(req) + assert.NoError(t, err) + assert.Equal(t, "anbraten/test-2", r.FullName) + assert.Equal(t, model.EventPullClosed, b.Event) + assert.Equal(t, "f90e18fc9d45", b.Commit) + }) - g.Describe("Given a push hook payload", func() { - g.It("should return err when malformed", func() { - buf := bytes.NewBufferString("[]") - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPush) + t.Run("malformed push", func(t *testing.T) { + buf := bytes.NewBufferString("[]") + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPush) - _, _, err := parseHook(req) - g.Assert(err).IsNotNil() - }) + _, _, err := parseHook(req) + assert.Error(t, err) + }) - g.It("should return nil if missing commit sha", func() { - buf := bytes.NewBufferString(fixtures.HookPushEmptyHash) - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPush) + t.Run("missing commit sha", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPushEmptyHash) + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPush) - r, b, err := parseHook(req) - g.Assert(r).IsNil() - g.Assert(b).IsNil() - g.Assert(err).IsNil() - }) + r, b, err := parseHook(req) + assert.Nil(t, r) + assert.Nil(t, b) + assert.NoError(t, err) + }) - g.It("should return push details", func() { - buf := bytes.NewBufferString(fixtures.HookPush) - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPush) + t.Run("push hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPush) + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPush) - r, b, err := parseHook(req) - g.Assert(err).IsNil() - g.Assert(r.FullName).Equal("martinherren1984/publictestrepo") - g.Assert(r.Clone).Equal("https://bitbucket.org/martinherren1984/publictestrepo") - g.Assert(b.Commit).Equal("c14c1bb05dfb1fdcdf06b31485fff61b0ea44277") - g.Assert(b.Message).Equal("a\n") - }) - }) - - g.Describe("Given a tag hook payload", func() { - // TODO - }) + r, b, err := parseHook(req) + assert.NoError(t, err) + assert.Equal(t, "martinherren1984/publictestrepo", r.FullName) + assert.Equal(t, "https://bitbucket.org/martinherren1984/publictestrepo", r.Clone) + assert.Equal(t, "c14c1bb05dfb1fdcdf06b31485fff61b0ea44277", b.Commit) + assert.Equal(t, "a\n", b.Message) }) } diff --git a/server/forge/bitbucketdatacenter/bitbucketdatacenter_test.go b/server/forge/bitbucketdatacenter/bitbucketdatacenter_test.go index 9ccdf1910..b85c1ebd3 100644 --- a/server/forge/bitbucketdatacenter/bitbucketdatacenter_test.go +++ b/server/forge/bitbucketdatacenter/bitbucketdatacenter_test.go @@ -19,75 +19,74 @@ import ( "testing" "time" - "github.com/franela/goblin" "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/forge/bitbucketdatacenter/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/model" ) +func TestNew(t *testing.T) { + forge, err := New(Opts{ + URL: "http://localhost:8080", + Username: "0ZXh0IjoiI", + Password: "I1NiIsInR5", + ClientID: "client-id", + ClientSecret: "client-secret", + }) + assert.NoError(t, err) + assert.NotNil(t, forge) + cl, ok := forge.(*client) + assert.True(t, ok) + assert.Equal(t, &client{ + url: "http://localhost:8080", + urlAPI: "http://localhost:8080/rest", + username: "0ZXh0IjoiI", + password: "I1NiIsInR5", + clientID: "client-id", + clientSecret: "client-secret", + }, cl) +} + func TestBitbucketDC(t *testing.T) { gin.SetMode(gin.TestMode) s := fixtures.Server() + defer s.Close() c := &client{ urlAPI: s.URL, } ctx := context.Background() - g := goblin.Goblin(t) - g.Describe("Bitbucket DataCenter/Server", func() { - g.After(func() { - s.Close() - }) - g.Describe("Creating a forge", func() { - g.It("Should return client with specified options", func() { - forge, err := New(Opts{ - URL: "http://localhost:8080", - Username: "0ZXh0IjoiI", - Password: "I1NiIsInR5", - ClientID: "client-id", - ClientSecret: "client-secret", - }) - g.Assert(err).IsNil() - g.Assert(forge).IsNotNil() - cl, ok := forge.(*client) - g.Assert(ok).IsTrue() - g.Assert(cl.url).Equal("http://localhost:8080") - g.Assert(cl.username).Equal("0ZXh0IjoiI") - g.Assert(cl.password).Equal("I1NiIsInR5") - g.Assert(cl.clientID).Equal("client-id") - g.Assert(cl.clientSecret).Equal("client-secret") - }) - }) + repo, err := c.Repo(ctx, fakeUser, model.ForgeRemoteID("1234"), "PRJ", "repo-slug") + assert.NoError(t, err) + assert.Equal(t, &model.Repo{ + Name: "repo-slug-2", + Owner: "PRJ", + Perm: &model.Perm{Pull: true, Push: true}, + Branch: "main", + IsSCMPrivate: true, + PREnabled: true, + ForgeRemoteID: model.ForgeRemoteID("1234"), + FullName: "PRJ/repo-slug-2", + }, repo) - g.Describe("Requesting a repository", func() { - g.It("should return repository details", func() { - repo, err := c.Repo(ctx, fakeUser, model.ForgeRemoteID("1234"), "PRJ", "repo-slug") - g.Assert(err).IsNil() - g.Assert(repo.Name).Equal("repo-slug-2") - g.Assert(repo.Owner).Equal("PRJ") - g.Assert(repo.Perm).Equal(&model.Perm{Pull: true, Push: true}) - g.Assert(repo.Branch).Equal("main") - }) - }) + // org + org, err := c.Org(ctx, fakeUser, "ORG") + assert.NoError(t, err) + assert.Equal(t, &model.Org{ + Name: "ORG", + IsUser: false, + }, org) - g.Describe("Getting organization", func() { - g.It("should map organization", func() { - org, err := c.Org(ctx, fakeUser, "ORG") - g.Assert(err).IsNil() - g.Assert(org.Name).Equal("ORG") - g.Assert(org.IsUser).IsFalse() - }) - g.It("should map user organization", func() { - org, err := c.Org(ctx, fakeUser, "~ORG") - g.Assert(err).IsNil() - g.Assert(org.Name).Equal("~ORG") - g.Assert(org.IsUser).IsTrue() - }) - }) - }) + // user + org, err = c.Org(ctx, fakeUser, "~ORG") + assert.NoError(t, err) + assert.Equal(t, &model.Org{ + Name: "~ORG", + IsUser: true, + }, org) } var fakeUser = &model.User{ diff --git a/server/forge/bitbucketdatacenter/convert_test.go b/server/forge/bitbucketdatacenter/convert_test.go index cefd006bb..10ba54999 100644 --- a/server/forge/bitbucketdatacenter/convert_test.go +++ b/server/forge/bitbucketdatacenter/convert_test.go @@ -18,288 +18,299 @@ import ( "testing" "time" - "github.com/franela/goblin" bb "github.com/neticdk/go-bitbucket/bitbucket" + "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/model" ) -//nolint:misspell -func TestHelper(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("Bitbucket Server converter", func() { - g.It("should convert status", func() { - tests := []struct { - from model.StatusValue - to bb.BuildStatusState - }{ - { - from: model.StatusPending, - to: bb.BuildStatusStateInProgress, - }, - { - from: model.StatusRunning, - to: bb.BuildStatusStateInProgress, - }, - { - from: model.StatusSuccess, - to: bb.BuildStatusStateSuccessful, - }, - { - from: model.StatusValue("other"), - to: bb.BuildStatusStateFailed, - }, - } - for _, tt := range tests { - to := convertStatus(tt.from) - g.Assert(to).Equal(tt.to) - } - }) - - g.It("should convert repository", func() { - from := &bb.Repository{ - ID: uint64(1234), - Slug: "REPO", - Project: &bb.Project{ - Key: "PRJ", - }, - Links: map[string][]bb.Link{ - "clone": { - { - Name: "http", - Href: "https://user@git.domain/clone", - }, - }, - "self": { - { - Href: "https://git.domain/self", - }, - }, - }, - } - perm := &model.Perm{} - to := convertRepo(from, perm, "main") - g.Assert(to.ForgeRemoteID).Equal(model.ForgeRemoteID("1234")) - g.Assert(to.Name).Equal("REPO") - g.Assert(to.Owner).Equal("PRJ") - g.Assert(to.Branch).Equal("main") - g.Assert(to.FullName).Equal("PRJ/REPO") - g.Assert(to.Perm).Equal(perm) - g.Assert(to.Clone).Equal("https://git.domain/clone") - }) - - g.It("should convert repository push event", func() { - now := time.Now() - tests := []struct { - from *bb.RepositoryPushEvent - to *model.Pipeline - }{ - { - from: &bb.RepositoryPushEvent{}, - to: nil, - }, - { - from: &bb.RepositoryPushEvent{ - Changes: []bb.RepositoryPushEventChange{ - { - FromHash: "1234567890abcdef", - ToHash: "0000000000000000000000000000000000000000", - }, - }, - }, - to: nil, - }, - { - from: &bb.RepositoryPushEvent{ - Changes: []bb.RepositoryPushEventChange{ - { - FromHash: "0000000000000000000000000000000000000000", - ToHash: "1234567890abcdef", - Type: bb.RepositoryPushEventChangeTypeDelete, - }, - }, - }, - to: nil, - }, - { - from: &bb.RepositoryPushEvent{ - Event: bb.Event{ - Date: bb.ISOTime(now), - Actor: bb.User{ - Name: "John Doe", - Email: "john.doe@mail.com", - Slug: "john.doe_mail.com", - }, - }, - Repository: bb.Repository{ - Slug: "REPO", - Project: &bb.Project{ - Key: "PRJ", - }, - }, - Changes: []bb.RepositoryPushEventChange{ - { - Ref: bb.RepositoryPushEventRef{ - ID: "refs/head/branch", - DisplayID: "branch", - }, - RefId: "refs/head/branch", - ToHash: "1234567890abcdef", - }, - }, - }, - to: &model.Pipeline{ - Commit: "1234567890abcdef", - Branch: "branch", - Message: "", - Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", - Author: "John Doe", - Email: "john.doe@mail.com", - Timestamp: now.UTC().Unix(), - Ref: "refs/head/branch", - ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", - Event: model.EventPush, - }, - }, - } - for _, tt := range tests { - to := convertRepositoryPushEvent(tt.from, "https://base.url") - g.Assert(to).Equal(tt.to) - } - }) - - g.It("should convert pull request event", func() { - now := time.Now() - from := &bb.PullRequestEvent{ - Event: bb.Event{ - Date: bb.ISOTime(now), - EventKey: bb.EventKeyPullRequestFrom, - Actor: bb.User{ - Name: "John Doe", - Email: "john.doe@mail.com", - Slug: "john.doe_mail.com", - }, - }, - PullRequest: bb.PullRequest{ - ID: 123, - Title: "my title", - Source: bb.PullRequestRef{ - ID: "refs/head/branch", - DisplayID: "branch", - Latest: "1234567890abcdef", - Repository: bb.Repository{ - Slug: "REPO", - Project: &bb.Project{ - Key: "PRJ", - }, - }, - }, - Target: bb.PullRequestRef{ - ID: "refs/head/main", - DisplayID: "main", - Latest: "abcdef1234567890", - Repository: bb.Repository{ - Slug: "REPO", - Project: &bb.Project{ - Key: "PRJ", - }, - }, - }, - }, - } - to := convertPullRequestEvent(from, "https://base.url") - g.Assert(to.Commit).Equal("1234567890abcdef") - g.Assert(to.Branch).Equal("branch") - g.Assert(to.Avatar).Equal("https://base.url/users/john.doe_mail.com/avatar.png") - g.Assert(to.Author).Equal("John Doe") - g.Assert(to.Email).Equal("john.doe@mail.com") - g.Assert(to.Timestamp).Equal(now.UTC().Unix()) - g.Assert(to.Ref).Equal("refs/pull-requests/123/from") - g.Assert(to.ForgeURL).Equal("https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef") - g.Assert(to.Event).Equal(model.EventPull) - g.Assert(to.Refspec).Equal("branch:main") - }) - - g.It("should close pull request", func() { - now := time.Now() - from := &bb.PullRequestEvent{ - Event: bb.Event{ - Date: bb.ISOTime(now), - EventKey: bb.EventKeyPullRequestMerged, - Actor: bb.User{ - Name: "John Doe", - Email: "john.doe@mail.com", - Slug: "john.doe_mail.com", - }, - }, - PullRequest: bb.PullRequest{ - ID: 123, - Title: "my title", - Source: bb.PullRequestRef{ - ID: "refs/head/branch", - DisplayID: "branch", - Latest: "1234567890abcdef", - Repository: bb.Repository{ - Slug: "REPO", - Project: &bb.Project{ - Key: "PRJ", - }, - }, - }, - Target: bb.PullRequestRef{ - ID: "refs/head/main", - DisplayID: "main", - Latest: "abcdef1234567890", - Repository: bb.Repository{ - Slug: "REPO", - Project: &bb.Project{ - Key: "PRJ", - }, - }, - }, - }, - } - to := convertPullRequestEvent(from, "https://base.url") - g.Assert(to.Commit).Equal("1234567890abcdef") - g.Assert(to.Branch).Equal("branch") - g.Assert(to.Avatar).Equal("https://base.url/users/john.doe_mail.com/avatar.png") - g.Assert(to.Author).Equal("John Doe") - g.Assert(to.Email).Equal("john.doe@mail.com") - g.Assert(to.Timestamp).Equal(now.UTC().Unix()) - g.Assert(to.Ref).Equal("refs/pull-requests/123/from") - g.Assert(to.ForgeURL).Equal("https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef") - g.Assert(to.Event).Equal(model.EventPullClosed) - g.Assert(to.Refspec).Equal("branch:main") - }) - - g.It("should truncate author", func() { - tests := []struct { - from string - to string - }{ - { - from: "Some Short Author", - to: "Some Short Author", - }, - { - from: "Some Very Long Author That May Include Multiple Names Here", - to: "Some Very Long Author That May Includ...", - }, - } - for _, tt := range tests { - g.Assert(authorLabel(tt.from)).Equal(tt.to) - } - }) - - g.It("should convert user", func() { - from := &bb.User{ - Slug: "slug", - Email: "john.doe@mail.com", - } - to := convertUser(from, "https://base.url") - g.Assert(to.Login).Equal("slug") - g.Assert(to.Avatar).Equal("https://base.url/users/slug/avatar.png") - g.Assert(to.Email).Equal("john.doe@mail.com") - }) - }) +func Test_convertStatus(t *testing.T) { + tests := []struct { + from model.StatusValue + to bb.BuildStatusState + }{ + { + from: model.StatusPending, + to: bb.BuildStatusStateInProgress, + }, + { + from: model.StatusRunning, + to: bb.BuildStatusStateInProgress, + }, + { + from: model.StatusSuccess, + to: bb.BuildStatusStateSuccessful, + }, + { + from: model.StatusValue("other"), + to: bb.BuildStatusStateFailed, + }, + } + for _, tt := range tests { + to := convertStatus(tt.from) + assert.Equal(t, tt.to, to) + } +} + +func Test_convertRepo(t *testing.T) { + from := &bb.Repository{ + ID: uint64(1234), + Slug: "REPO", + Project: &bb.Project{ + Key: "PRJ", + }, + Links: map[string][]bb.Link{ + "clone": { + { + Name: "http", + Href: "https://user@git.domain/clone", + }, + }, + "self": { + { + Href: "https://git.domain/self", + }, + }, + }, + } + perm := &model.Perm{} + to := convertRepo(from, perm, "main") + + assert.Equal(t, &model.Repo{ + ForgeRemoteID: model.ForgeRemoteID("1234"), + Name: "REPO", + Owner: "PRJ", + Branch: "main", + FullName: "PRJ/REPO", + Perm: perm, + Clone: "https://git.domain/clone", + ForgeURL: "https://git.domain/self", + PREnabled: true, + IsSCMPrivate: true, + }, to) +} + +func Test_convertRepositoryPushEvent(t *testing.T) { + now := time.Now() + tests := []struct { + from *bb.RepositoryPushEvent + to *model.Pipeline + }{ + { + from: &bb.RepositoryPushEvent{}, + to: nil, + }, + { + from: &bb.RepositoryPushEvent{ + Changes: []bb.RepositoryPushEventChange{ + { + FromHash: "1234567890abcdef", + ToHash: "0000000000000000000000000000000000000000", + }, + }, + }, + to: nil, + }, + { + from: &bb.RepositoryPushEvent{ + Changes: []bb.RepositoryPushEventChange{ + { + FromHash: "0000000000000000000000000000000000000000", + ToHash: "1234567890abcdef", + Type: bb.RepositoryPushEventChangeTypeDelete, + }, + }, + }, + to: nil, + }, + { + from: &bb.RepositoryPushEvent{ + Event: bb.Event{ + Date: bb.ISOTime(now), + Actor: bb.User{ + Name: "John Doe", + Email: "john.doe@mail.com", + Slug: "john.doe_mail.com", + }, + }, + Repository: bb.Repository{ + Slug: "REPO", + Project: &bb.Project{ + Key: "PRJ", + }, + }, + Changes: []bb.RepositoryPushEventChange{ + { + Ref: bb.RepositoryPushEventRef{ + ID: "refs/head/branch", + DisplayID: "branch", + }, + RefId: "refs/head/branch", + ToHash: "1234567890abcdef", + }, + }, + }, + to: &model.Pipeline{ + Commit: "1234567890abcdef", + Branch: "branch", + Message: "", + Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", + Author: "John Doe", + Email: "john.doe@mail.com", + Timestamp: now.UTC().Unix(), + Ref: "refs/head/branch", + ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", + Event: model.EventPush, + }, + }, + } + for _, tt := range tests { + to := convertRepositoryPushEvent(tt.from, "https://base.url") + assert.Equal(t, tt.to, to) + } +} + +func Test_convertPullRequestEvent(t *testing.T) { + now := time.Now() + from := &bb.PullRequestEvent{ + Event: bb.Event{ + Date: bb.ISOTime(now), + EventKey: bb.EventKeyPullRequestFrom, + Actor: bb.User{ + Name: "John Doe", + Email: "john.doe@mail.com", + Slug: "john.doe_mail.com", + }, + }, + PullRequest: bb.PullRequest{ + ID: 123, + Title: "my title", + Source: bb.PullRequestRef{ + ID: "refs/head/branch", + DisplayID: "branch", + Latest: "1234567890abcdef", + Repository: bb.Repository{ + Slug: "REPO", + Project: &bb.Project{ + Key: "PRJ", + }, + }, + }, + Target: bb.PullRequestRef{ + ID: "refs/head/main", + DisplayID: "main", + Latest: "abcdef1234567890", + Repository: bb.Repository{ + Slug: "REPO", + Project: &bb.Project{ + Key: "PRJ", + }, + }, + }, + }, + } + to := convertPullRequestEvent(from, "https://base.url") + assert.Equal(t, &model.Pipeline{ + Commit: "1234567890abcdef", + Branch: "branch", + Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", + Author: "John Doe", + Email: "john.doe@mail.com", + Timestamp: now.UTC().Unix(), + Ref: "refs/pull-requests/123/from", + ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", + Event: model.EventPull, + Refspec: "branch:main", + Title: "my title", + }, to) +} + +func Test_convertPullRequestCloseEvent(t *testing.T) { + now := time.Now() + from := &bb.PullRequestEvent{ + Event: bb.Event{ + Date: bb.ISOTime(now), + EventKey: bb.EventKeyPullRequestMerged, + Actor: bb.User{ + Name: "John Doe", + Email: "john.doe@mail.com", + Slug: "john.doe_mail.com", + }, + }, + PullRequest: bb.PullRequest{ + ID: 123, + Title: "my title", + Source: bb.PullRequestRef{ + ID: "refs/head/branch", + DisplayID: "branch", + Latest: "1234567890abcdef", + Repository: bb.Repository{ + Slug: "REPO", + Project: &bb.Project{ + Key: "PRJ", + }, + }, + }, + Target: bb.PullRequestRef{ + ID: "refs/head/main", + DisplayID: "main", + Latest: "abcdef1234567890", + Repository: bb.Repository{ + Slug: "REPO", + Project: &bb.Project{ + Key: "PRJ", + }, + }, + }, + }, + } + to := convertPullRequestEvent(from, "https://base.url") + assert.Equal(t, &model.Pipeline{ + Commit: "1234567890abcdef", + Branch: "branch", + Avatar: "https://base.url/users/john.doe_mail.com/avatar.png", + Author: "John Doe", + Email: "john.doe@mail.com", + Timestamp: now.UTC().Unix(), + Ref: "refs/pull-requests/123/from", + ForgeURL: "https://base.url/projects/PRJ/repos/REPO/commits/1234567890abcdef", + Event: model.EventPullClosed, + Refspec: "branch:main", + Title: "my title", + }, to) +} + +func Test_authorLabel(t *testing.T) { + tests := []struct { + from string + to string + }{ + { + from: "Some Short Author", + to: "Some Short Author", + }, + { + from: "Some Very Long Author That May Include Multiple Names Here", + //nolint:misspell + to: "Some Very Long Author That May Includ...", + }, + } + for _, tt := range tests { + assert.Equal(t, tt.to, authorLabel(tt.from)) + } +} + +func Test_convertUser(t *testing.T) { + from := &bb.User{ + Slug: "slug", + Email: "john.doe@mail.com", + ID: 1, + } + to := convertUser(from, "https://base.url") + assert.Equal(t, &model.User{ + Login: "slug", + Avatar: "https://base.url/users/slug/avatar.png", + Email: "john.doe@mail.com", + ForgeRemoteID: "1", + }, to) } diff --git a/server/forge/bitbucketdatacenter/internal/client_test.go b/server/forge/bitbucketdatacenter/internal/client_test.go index d8412e3c6..94f01f084 100644 --- a/server/forge/bitbucketdatacenter/internal/client_test.go +++ b/server/forge/bitbucketdatacenter/internal/client_test.go @@ -20,7 +20,7 @@ import ( "net/http/httptest" "testing" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" "golang.org/x/oauth2" ) @@ -30,20 +30,14 @@ func TestCurrentUser(t *testing.T) { _, _ = w.Write([]byte(`tal@netic.dk`)) })) - g := goblin.Goblin(t) - g.Describe("Bitbucket Current User", func() { - g.After(func() { - s.Close() - }) - g.It("should return current user id", func() { - ctx := context.Background() - ts := mockSource("bearer-token") - client := NewClientWithToken(ctx, ts, s.URL) - uid, err := client.FindCurrentUser(ctx) - g.Assert(err).IsNil() - g.Assert(uid).Equal("tal_netic.dk") - }) - }) + defer s.Close() + + ctx := context.Background() + ts := mockSource("bearer-token") + client := NewClientWithToken(ctx, ts, s.URL) + uid, err := client.FindCurrentUser(ctx) + assert.NoError(t, err) + assert.Equal(t, "tal_netic.dk", uid) } type mockSource string diff --git a/server/forge/forgejo/forgejo_test.go b/server/forge/forgejo/forgejo_test.go index 1941e646e..0dcbc49fb 100644 --- a/server/forge/forgejo/forgejo_test.go +++ b/server/forge/forgejo/forgejo_test.go @@ -21,21 +21,32 @@ import ( "net/http/httptest" "testing" - "github.com/franela/goblin" "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "go.woodpecker-ci.org/woodpecker/v3/server/forge/forgejo/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/store" mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks" - "go.woodpecker-ci.org/woodpecker/v3/shared/utils" ) +func TestNew(t *testing.T) { + forge, _ := New(Opts{ + URL: "http://localhost:8080", + SkipVerify: true, + }) + + f, _ := forge.(*Forgejo) + assert.Equal(t, "http://localhost:8080", f.url) + assert.True(t, f.SkipVerify) +} + func Test_forgejo(t *testing.T) { gin.SetMode(gin.TestMode) s := httptest.NewServer(fixtures.Handler()) + defer s.Close() c, _ := New(Opts{ URL: s.URL, SkipVerify: true, @@ -44,122 +55,83 @@ func Test_forgejo(t *testing.T) { mockStore := mocks_store.NewStore(t) ctx := store.InjectToContext(context.Background(), mockStore) - g := goblin.Goblin(t) - g.Describe("Forgejo", func() { - g.After(func() { - s.Close() - }) + t.Run("netrc with user token", func(t *testing.T) { + forge, _ := New(Opts{}) + netrc, _ := forge.Netrc(fakeUser, fakeRepo) + assert.Equal(t, "forgejo.org", netrc.Machine) + assert.Equal(t, fakeUser.Login, netrc.Login) + assert.Equal(t, fakeUser.AccessToken, netrc.Password) + }) + t.Run("netrc with machine account", func(t *testing.T) { + forge, _ := New(Opts{}) + netrc, _ := forge.Netrc(nil, fakeRepo) + assert.Equal(t, "forgejo.org", netrc.Machine) + assert.Empty(t, netrc.Login) + assert.Empty(t, netrc.Password) + }) - g.Describe("Creating a forge", func() { - g.It("Should return client with specified options", func() { - forge, _ := New(Opts{ - URL: "http://localhost:8080", - SkipVerify: true, - }) + t.Run("repository details", func(t *testing.T) { + repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name) + assert.NoError(t, err) + assert.Equal(t, fakeRepo.Owner, repo.Owner) + assert.Equal(t, fakeRepo.Name, repo.Name) + assert.Equal(t, fakeRepo.Owner+"/"+fakeRepo.Name, repo.FullName) + assert.True(t, repo.IsSCMPrivate) + assert.Equal(t, "http://localhost/test_name/repo_name.git", repo.Clone) + assert.Equal(t, "http://localhost/test_name/repo_name", repo.ForgeURL) + }) + t.Run("repo not found", func(t *testing.T) { + _, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name) + assert.Error(t, err) + }) - f, _ := forge.(*Forgejo) - g.Assert(f.url).Equal("http://localhost:8080") - g.Assert(f.SkipVerify).Equal(true) - }) - }) + t.Run("repository list", func(t *testing.T) { + repos, err := c.Repos(ctx, fakeUser) + assert.NoError(t, err) + assert.Equal(t, fakeRepo.ForgeRemoteID, repos[0].ForgeRemoteID) + assert.Equal(t, fakeRepo.Owner, repos[0].Owner) + assert.Equal(t, fakeRepo.Name, repos[0].Name) + assert.Equal(t, fakeRepo.Owner+"/"+fakeRepo.Name, repos[0].FullName) + }) + t.Run("not found error", func(t *testing.T) { + _, err := c.Repos(ctx, fakeUserNoRepos) + assert.Error(t, err) + }) - g.Describe("Generating a netrc file", func() { - g.It("Should return a netrc with the user token", func() { - forge, _ := New(Opts{}) - netrc, _ := forge.Netrc(fakeUser, fakeRepo) - g.Assert(netrc.Machine).Equal("forgejo.org") - g.Assert(netrc.Login).Equal(fakeUser.Login) - g.Assert(netrc.Password).Equal(fakeUser.AccessToken) - }) - g.It("Should return a netrc with the machine account", func() { - forge, _ := New(Opts{}) - netrc, _ := forge.Netrc(nil, fakeRepo) - g.Assert(netrc.Machine).Equal("forgejo.org") - g.Assert(netrc.Login).Equal("") - g.Assert(netrc.Password).Equal("") - }) - }) + t.Run("register repository", func(t *testing.T) { + err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost") + assert.NoError(t, err) + }) - g.Describe("Requesting a repository", func() { - g.It("Should return the repository details", func() { - repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name) - g.Assert(err).IsNil() - g.Assert(repo.Owner).Equal(fakeRepo.Owner) - g.Assert(repo.Name).Equal(fakeRepo.Name) - g.Assert(repo.FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name) - g.Assert(repo.IsSCMPrivate).IsTrue() - g.Assert(repo.Clone).Equal("http://localhost/test_name/repo_name.git") - g.Assert(repo.ForgeURL).Equal("http://localhost/test_name/repo_name") - }) - g.It("Should handle a not found error", func() { - _, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name) - g.Assert(err).IsNotNil() - }) - }) + t.Run("remove hooks", func(t *testing.T) { + err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost") + assert.NoError(t, err) + }) - g.Describe("Requesting a repository list", func() { - g.It("Should return the repository list", func() { - repos, err := c.Repos(ctx, fakeUser) - g.Assert(err).IsNil() - g.Assert(repos[0].ForgeRemoteID).Equal(fakeRepo.ForgeRemoteID) - g.Assert(repos[0].Owner).Equal(fakeRepo.Owner) - g.Assert(repos[0].Name).Equal(fakeRepo.Name) - g.Assert(repos[0].FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name) - }) - g.It("Should handle a not found error", func() { - _, err := c.Repos(ctx, fakeUserNoRepos) - g.Assert(err).IsNotNil() - }) - }) + t.Run("repository file", func(t *testing.T) { + raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml") + assert.NoError(t, err) + assert.Equal(t, "{ platform: linux/amd64 }", string(raw)) + }) - g.It("Should register repository hooks", func() { - err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost") - g.Assert(err).IsNil() - }) + t.Run("pipeline status", func(t *testing.T) { + err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow) + assert.NoError(t, err) + }) - g.It("Should remove repository hooks", func() { - err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost") - g.Assert(err).IsNil() - }) - - g.It("Should return a repository file", func() { - raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml") - g.Assert(err).IsNil() - g.Assert(string(raw)).Equal("{ platform: linux/amd64 }") - }) - - g.It("Should return nil from send pipeline status", func() { - err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow) - g.Assert(err).IsNil() - }) - - g.Describe("Given an authentication request", func() { - g.It("Should redirect to login form") - g.It("Should create an access token") - g.It("Should handle an access token error") - g.It("Should return the authenticated user") - }) - - g.Describe("Given a repository hook", func() { - g.It("Should skip non-push events") - g.It("Should return push details") - g.It("Should handle a parsing error") - }) - - g.It("Given a PR hook", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequest) - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPullRequest) - mockStore.On("GetRepoNameFallback", mock.Anything, mock.Anything).Return(fakeRepo, nil) - mockStore.On("GetUser", mock.Anything).Return(fakeUser, nil) - r, b, err := c.Hook(ctx, req) - g.Assert(r).IsNotNil() - g.Assert(b).IsNotNil() - g.Assert(err).IsNil() - g.Assert(b.Event).Equal(model.EventPull) - g.Assert(utils.EqualSliceValues(b.ChangedFiles, []string{"README.md"})).IsTrue() - }) + t.Run("PR hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequest) + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPullRequest) + mockStore.On("GetRepoNameFallback", mock.Anything, mock.Anything).Return(fakeRepo, nil) + mockStore.On("GetUser", mock.Anything).Return(fakeUser, nil) + r, b, err := c.Hook(ctx, req) + assert.NotNil(t, r) + assert.NotNil(t, b) + assert.NoError(t, err) + assert.Equal(t, model.EventPull, b.Event) + assert.Equal(t, []string{"README.md"}, b.ChangedFiles) }) } diff --git a/server/forge/forgejo/helper_test.go b/server/forge/forgejo/helper_test.go index 8f0ae2316..b7414a504 100644 --- a/server/forge/forgejo/helper_test.go +++ b/server/forge/forgejo/helper_test.go @@ -19,255 +19,252 @@ import ( "testing" "codeberg.org/mvdkleijn/forgejo-sdk/forgejo" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/forge/forgejo/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/model" - "go.woodpecker-ci.org/woodpecker/v3/shared/utils" ) -func Test_parse(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("Forgejo", func() { - g.It("Should parse push hook payload", func() { - buf := bytes.NewBufferString(fixtures.HookPush) - hook, err := parsePush(buf) - g.Assert(err).IsNil() - g.Assert(hook.Ref).Equal("refs/heads/main") - g.Assert(hook.After).Equal("ef98532add3b2feb7a137426bba1248724367df5") - g.Assert(hook.Before).Equal("4b2626259b5a97b6b4eab5e6cca66adb986b672b") - g.Assert(hook.Compare).Equal("http://forgejo.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5") - g.Assert(hook.Repo.Name).Equal("hello-world") - g.Assert(hook.Repo.HTMLURL).Equal("http://forgejo.golang.org/gordon/hello-world") - g.Assert(hook.Repo.Owner.UserName).Equal("gordon") - g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") - g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") - g.Assert(hook.Repo.Private).Equal(true) - g.Assert(hook.Pusher.Email).Equal("gordon@golang.org") - g.Assert(hook.Pusher.UserName).Equal("gordon") - g.Assert(hook.Sender.UserName).Equal("gordon") - g.Assert(hook.Sender.AvatarURL).Equal("http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - }) +func Test_parsePush(t *testing.T) { + t.Run("Should parse push hook payload", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPush) + hook, err := parsePush(buf) + assert.NoError(t, err) + assert.Equal(t, "refs/heads/main", hook.Ref) + assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.After) + assert.Equal(t, "4b2626259b5a97b6b4eab5e6cca66adb986b672b", hook.Before) + assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5", hook.Compare) + assert.Equal(t, "hello-world", hook.Repo.Name) + assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world", hook.Repo.HTMLURL) + assert.Equal(t, "gordon", hook.Repo.Owner.UserName) + assert.Equal(t, "gordon/hello-world", hook.Repo.FullName) + assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email) + assert.True(t, hook.Repo.Private) + assert.Equal(t, "gordon@golang.org", hook.Pusher.Email) + assert.Equal(t, "gordon", hook.Pusher.UserName) + assert.Equal(t, "gordon", hook.Sender.UserName) + assert.Equal(t, "http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL) + }) + t.Run("Should parse tag hook payload", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookTag) + hook, err := parsePush(buf) + assert.NoError(t, err) + assert.Equal(t, "v1.0.0", hook.Ref) + assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.Sha) + assert.Equal(t, "hello-world", hook.Repo.Name) + assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world", hook.Repo.HTMLURL) + assert.Equal(t, "gordon/hello-world", hook.Repo.FullName) + assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email) + assert.Equal(t, "gordon", hook.Repo.Owner.UserName) + assert.True(t, hook.Repo.Private) + assert.Equal(t, "gordon", hook.Sender.UserName) + assert.Equal(t, "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL) + }) - g.It("Should parse tag hook payload", func() { - buf := bytes.NewBufferString(fixtures.HookTag) - hook, err := parsePush(buf) - g.Assert(err).IsNil() - g.Assert(hook.Ref).Equal("v1.0.0") - g.Assert(hook.Sha).Equal("ef98532add3b2feb7a137426bba1248724367df5") - g.Assert(hook.Repo.Name).Equal("hello-world") - g.Assert(hook.Repo.HTMLURL).Equal("http://forgejo.golang.org/gordon/hello-world") - g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") - g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") - g.Assert(hook.Repo.Owner.UserName).Equal("gordon") - g.Assert(hook.Repo.Private).Equal(true) - g.Assert(hook.Sender.UserName).Equal("gordon") - g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - }) + t.Run("Should return a Pipeline struct from a push hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPush) + hook, _ := parsePush(buf) + pipeline := pipelineFromPush(hook) + assert.Equal(t, model.EventPush, pipeline.Event) + assert.Equal(t, hook.After, pipeline.Commit) + assert.Equal(t, hook.Ref, pipeline.Ref) + assert.Equal(t, hook.Commits[0].URL, pipeline.ForgeURL) + assert.Equal(t, "main", pipeline.Branch) + assert.Equal(t, hook.Commits[0].Message, pipeline.Message) + assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar) + assert.Equal(t, hook.Sender.UserName, pipeline.Author) + assert.Equal(t, []string{"CHANGELOG.md", "app/controller/application.rb"}, pipeline.ChangedFiles) + }) - g.It("Should parse pull_request hook payload", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequest) - hook, err := parsePullRequest(buf) - g.Assert(err).IsNil() - g.Assert(hook.Action).Equal("opened") - g.Assert(hook.Number).Equal(int64(1)) + t.Run("Should return a Repo struct from a push hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPush) + hook, _ := parsePush(buf) + repo := toRepo(hook.Repo) + assert.Equal(t, hook.Repo.Name, repo.Name) + assert.Equal(t, hook.Repo.Owner.UserName, repo.Owner) + assert.Equal(t, "gordon/hello-world", repo.FullName) + assert.Equal(t, hook.Repo.HTMLURL, repo.ForgeURL) + }) - g.Assert(hook.Repo.Name).Equal("hello-world") - g.Assert(hook.Repo.HTMLURL).Equal("http://forgejo.golang.org/gordon/hello-world") - g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") - g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") - g.Assert(hook.Repo.Owner.UserName).Equal("gordon") - g.Assert(hook.Repo.Private).Equal(true) - g.Assert(hook.Sender.UserName).Equal("gordon") - g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - - g.Assert(hook.PullRequest.Title).Equal("Update the README with new information") - g.Assert(hook.PullRequest.Body).Equal("please merge") - g.Assert(hook.PullRequest.State).Equal(forgejo.StateOpen) - g.Assert(hook.PullRequest.Poster.UserName).Equal("gordon") - g.Assert(hook.PullRequest.Base.Name).Equal("main") - g.Assert(hook.PullRequest.Base.Ref).Equal("main") - g.Assert(hook.PullRequest.Head.Name).Equal("feature/changes") - g.Assert(hook.PullRequest.Head.Ref).Equal("feature/changes") - }) - - g.It("Should return a Pipeline struct from a push hook", func() { - buf := bytes.NewBufferString(fixtures.HookPush) - hook, _ := parsePush(buf) - pipeline := pipelineFromPush(hook) - g.Assert(pipeline.Event).Equal(model.EventPush) - g.Assert(pipeline.Commit).Equal(hook.After) - g.Assert(pipeline.Ref).Equal(hook.Ref) - g.Assert(pipeline.ForgeURL).Equal(hook.Commits[0].URL) - g.Assert(pipeline.Branch).Equal("main") - g.Assert(pipeline.Message).Equal(hook.Commits[0].Message) - g.Assert(pipeline.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - g.Assert(pipeline.Author).Equal(hook.Sender.UserName) - g.Assert(utils.EqualSliceValues(pipeline.ChangedFiles, []string{"CHANGELOG.md", "app/controller/application.rb"})).IsTrue() - }) - - g.It("Should return a Repo struct from a push hook", func() { - buf := bytes.NewBufferString(fixtures.HookPush) - hook, _ := parsePush(buf) - repo := toRepo(hook.Repo) - g.Assert(repo.Name).Equal(hook.Repo.Name) - g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName) - g.Assert(repo.FullName).Equal("gordon/hello-world") - g.Assert(repo.ForgeURL).Equal(hook.Repo.HTMLURL) - }) - - g.It("Should return a Pipeline struct from a tag hook", func() { - buf := bytes.NewBufferString(fixtures.HookTag) - hook, _ := parsePush(buf) - pipeline := pipelineFromTag(hook) - g.Assert(pipeline.Event).Equal(model.EventTag) - g.Assert(pipeline.Commit).Equal(hook.Sha) - g.Assert(pipeline.Ref).Equal("refs/tags/v1.0.0") - g.Assert(pipeline.Branch).Equal("") - g.Assert(pipeline.ForgeURL).Equal("http://forgejo.golang.org/gordon/hello-world/src/tag/v1.0.0") - g.Assert(pipeline.Message).Equal("created tag v1.0.0") - }) - - g.It("Should return a Pipeline struct from a pull_request hook", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequest) - hook, _ := parsePullRequest(buf) - pipeline := pipelineFromPullRequest(hook) - g.Assert(pipeline.Event).Equal(model.EventPull) - g.Assert(pipeline.Commit).Equal(hook.PullRequest.Head.Sha) - g.Assert(pipeline.Ref).Equal("refs/pull/1/head") - g.Assert(pipeline.ForgeURL).Equal("http://forgejo.golang.org/gordon/hello-world/pull/1") - g.Assert(pipeline.Branch).Equal("main") - g.Assert(pipeline.Refspec).Equal("feature/changes:main") - g.Assert(pipeline.Message).Equal(hook.PullRequest.Title) - g.Assert(pipeline.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - g.Assert(pipeline.Author).Equal(hook.PullRequest.Poster.UserName) - }) - - g.It("Should return a Repo struct from a pull_request hook", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequest) - hook, _ := parsePullRequest(buf) - repo := toRepo(hook.Repo) - g.Assert(repo.Name).Equal(hook.Repo.Name) - g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName) - g.Assert(repo.FullName).Equal("gordon/hello-world") - g.Assert(repo.ForgeURL).Equal(hook.Repo.HTMLURL) - }) - - g.It("Should return a Perm struct from a Forgejo Perm", func() { - perms := []forgejo.Permission{ - { - Admin: true, - Push: true, - Pull: true, - }, - { - Admin: true, - Push: true, - Pull: false, - }, - { - Admin: true, - Push: false, - Pull: false, - }, - } - for _, from := range perms { - perm := toPerm(&from) - g.Assert(perm.Pull).Equal(from.Pull) - g.Assert(perm.Push).Equal(from.Push) - g.Assert(perm.Admin).Equal(from.Admin) - } - }) - - g.It("Should return a Team struct from a Forgejo Org", func() { - from := &forgejo.Organization{ - UserName: "woodpecker", - AvatarURL: "/avatars/1", - } - - to := toTeam(from, "http://localhost:80") - g.Assert(to.Login).Equal(from.UserName) - g.Assert(to.Avatar).Equal("http://localhost:80/avatars/1") - }) - - g.It("Should return a Repo struct from a Forgejo Repo", func() { - from := forgejo.Repository{ - FullName: "gophers/hello-world", - Owner: &forgejo.User{ - UserName: "gordon", - AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - }, - CloneURL: "http://forgejo.golang.org/gophers/hello-world.git", - HTMLURL: "http://forgejo.golang.org/gophers/hello-world", - Private: true, - DefaultBranch: "main", - Permissions: &forgejo.Permission{Admin: true}, - } - repo := toRepo(&from) - g.Assert(repo.FullName).Equal(from.FullName) - g.Assert(repo.Owner).Equal(from.Owner.UserName) - g.Assert(repo.Name).Equal("hello-world") - g.Assert(repo.Branch).Equal("main") - g.Assert(repo.ForgeURL).Equal(from.HTMLURL) - g.Assert(repo.Clone).Equal(from.CloneURL) - g.Assert(repo.Avatar).Equal(from.Owner.AvatarURL) - g.Assert(repo.IsSCMPrivate).Equal(from.Private) - g.Assert(repo.Perm.Admin).IsTrue() - }) - - g.It("Should correct a malformed avatar url", func() { - urls := []struct { - Before string - After string - }{ - { - "http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - }, - { - "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - }, - { - "http://forgejo.golang.org/avatars/1", - "http://forgejo.golang.org/avatars/1", - }, - { - "http://forgejo.golang.org//avatars/1", - "http://forgejo.golang.org/avatars/1", - }, - } - - for _, url := range urls { - got := fixMalformedAvatar(url.Before) - g.Assert(got).Equal(url.After) - } - }) - - g.It("Should expand the avatar url", func() { - urls := []struct { - Before string - After string - }{ - { - "/avatars/1", - "http://forgejo.io/avatars/1", - }, - { - "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - }, - { - "/forgejo/avatars/2", - "http://forgejo.io/forgejo/avatars/2", - }, - } - - repo := "http://forgejo.io/foo/bar" - for _, url := range urls { - got := expandAvatar(repo, url.Before) - g.Assert(got).Equal(url.After) - } - }) + t.Run("Should return a Pipeline struct from a tag hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookTag) + hook, _ := parsePush(buf) + pipeline := pipelineFromTag(hook) + assert.Equal(t, model.EventTag, pipeline.Event) + assert.Equal(t, hook.Sha, pipeline.Commit) + assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref) + assert.Empty(t, pipeline.Branch) + assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/src/tag/v1.0.0", pipeline.ForgeURL) + assert.Equal(t, "created tag v1.0.0", pipeline.Message) }) } + +func Test_parsePullRequest(t *testing.T) { + t.Run("Should parse pull_request hook payload", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequest) + hook, err := parsePullRequest(buf) + assert.NoError(t, err) + assert.Equal(t, "opened", hook.Action) + assert.Equal(t, int64(1), hook.Number) + + assert.Equal(t, "hello-world", hook.Repo.Name) + assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world", hook.Repo.HTMLURL) + assert.Equal(t, "gordon/hello-world", hook.Repo.FullName) + assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email) + assert.Equal(t, "gordon", hook.Repo.Owner.UserName) + assert.True(t, hook.Repo.Private) + assert.Equal(t, "gordon", hook.Sender.UserName) + assert.Equal(t, "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL) + + assert.Equal(t, "Update the README with new information", hook.PullRequest.Title) + assert.Equal(t, "please merge", hook.PullRequest.Body) + assert.Equal(t, forgejo.StateOpen, hook.PullRequest.State) + assert.Equal(t, "gordon", hook.PullRequest.Poster.UserName) + assert.Equal(t, "main", hook.PullRequest.Base.Name) + assert.Equal(t, "main", hook.PullRequest.Base.Ref) + assert.Equal(t, "feature/changes", hook.PullRequest.Head.Name) + assert.Equal(t, "feature/changes", hook.PullRequest.Head.Ref) + }) + + t.Run("Should return a Pipeline struct from a pull_request hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequest) + hook, _ := parsePullRequest(buf) + pipeline := pipelineFromPullRequest(hook) + assert.Equal(t, model.EventPull, pipeline.Event) + assert.Equal(t, hook.PullRequest.Head.Sha, pipeline.Commit) + assert.Equal(t, "refs/pull/1/head", pipeline.Ref) + assert.Equal(t, "http://forgejo.golang.org/gordon/hello-world/pull/1", pipeline.ForgeURL) + assert.Equal(t, "main", pipeline.Branch) + assert.Equal(t, "feature/changes:main", pipeline.Refspec) + assert.Equal(t, hook.PullRequest.Title, pipeline.Message) + assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar) + assert.Equal(t, hook.PullRequest.Poster.UserName, pipeline.Author) + }) + + t.Run("Should return a Repo struct from a pull_request hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequest) + hook, _ := parsePullRequest(buf) + repo := toRepo(hook.Repo) + assert.Equal(t, hook.Repo.Name, repo.Name) + assert.Equal(t, hook.Repo.Owner.UserName, repo.Owner) + assert.Equal(t, "gordon/hello-world", repo.FullName) + assert.Equal(t, hook.Repo.HTMLURL, repo.ForgeURL) + }) +} + +func Test_toPerm(t *testing.T) { + perms := []forgejo.Permission{ + { + Admin: true, + Push: true, + Pull: true, + }, + { + Admin: true, + Push: true, + Pull: false, + }, + { + Admin: true, + Push: false, + Pull: false, + }, + } + for _, from := range perms { + perm := toPerm(&from) + assert.Equal(t, from.Pull, perm.Pull) + assert.Equal(t, from.Push, perm.Push) + assert.Equal(t, from.Admin, perm.Admin) + } +} + +func Test_toTeam(t *testing.T) { + from := &forgejo.Organization{ + UserName: "woodpecker", + AvatarURL: "/avatars/1", + } + + to := toTeam(from, "http://localhost:80") + assert.Equal(t, from.UserName, to.Login) + assert.Equal(t, "http://localhost:80/avatars/1", to.Avatar) +} + +func Test_toRepo(t *testing.T) { + from := forgejo.Repository{ + FullName: "gophers/hello-world", + Owner: &forgejo.User{ + UserName: "gordon", + AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + }, + CloneURL: "http://forgejo.golang.org/gophers/hello-world.git", + HTMLURL: "http://forgejo.golang.org/gophers/hello-world", + Private: true, + DefaultBranch: "main", + Permissions: &forgejo.Permission{Admin: true}, + } + repo := toRepo(&from) + assert.Equal(t, from.FullName, repo.FullName) + assert.Equal(t, from.Owner.UserName, repo.Owner) + assert.Equal(t, "hello-world", repo.Name) + assert.Equal(t, "main", repo.Branch) + assert.Equal(t, from.HTMLURL, repo.ForgeURL) + assert.Equal(t, from.CloneURL, repo.Clone) + assert.Equal(t, from.Owner.AvatarURL, repo.Avatar) + assert.Equal(t, from.Private, repo.IsSCMPrivate) + assert.True(t, repo.Perm.Admin) +} + +func Test_fixMalformedAvatar(t *testing.T) { + urls := []struct { + Before string + After string + }{ + { + "http://forgejo.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + }, + { + "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + }, + { + "http://forgejo.golang.org/avatars/1", + "http://forgejo.golang.org/avatars/1", + }, + { + "http://forgejo.golang.org//avatars/1", + "http://forgejo.golang.org/avatars/1", + }, + } + + for _, url := range urls { + got := fixMalformedAvatar(url.Before) + assert.Equal(t, url.After, got) + } +} + +func Test_expandAvatar(t *testing.T) { + urls := []struct { + Before string + After string + }{ + { + "/avatars/1", + "http://forgejo.io/avatars/1", + }, + { + "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + }, + { + "/forgejo/avatars/2", + "http://forgejo.io/forgejo/avatars/2", + }, + } + + repo := "http://forgejo.io/foo/bar" + for _, url := range urls { + got := expandAvatar(repo, url.Before) + assert.Equal(t, url.After, got) + } +} diff --git a/server/forge/gitea/gitea_test.go b/server/forge/gitea/gitea_test.go index 7b7f20dce..1892c5fcc 100644 --- a/server/forge/gitea/gitea_test.go +++ b/server/forge/gitea/gitea_test.go @@ -22,21 +22,32 @@ import ( "net/http/httptest" "testing" - "github.com/franela/goblin" "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "go.woodpecker-ci.org/woodpecker/v3/server/forge/gitea/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/model" "go.woodpecker-ci.org/woodpecker/v3/server/store" mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks" - "go.woodpecker-ci.org/woodpecker/v3/shared/utils" ) +func TestNew(t *testing.T) { + forge, _ := New(Opts{ + URL: "http://localhost:8080", + SkipVerify: true, + }) + + f, _ := forge.(*Gitea) + assert.Equal(t, "http://localhost:8080", f.url) + assert.True(t, f.SkipVerify) +} + func Test_gitea(t *testing.T) { gin.SetMode(gin.TestMode) s := httptest.NewServer(fixtures.Handler()) + defer s.Close() c, _ := New(Opts{ URL: s.URL, SkipVerify: true, @@ -45,122 +56,83 @@ func Test_gitea(t *testing.T) { mockStore := mocks_store.NewStore(t) ctx := store.InjectToContext(context.Background(), mockStore) - g := goblin.Goblin(t) - g.Describe("Gitea", func() { - g.After(func() { - s.Close() - }) + t.Run("netrc with user token", func(t *testing.T) { + forge, _ := New(Opts{}) + netrc, _ := forge.Netrc(fakeUser, fakeRepo) + assert.Equal(t, "gitea.com", netrc.Machine) + assert.Equal(t, fakeUser.Login, netrc.Login) + assert.Equal(t, fakeUser.AccessToken, netrc.Password) + }) + t.Run("netrc with machine account", func(t *testing.T) { + forge, _ := New(Opts{}) + netrc, _ := forge.Netrc(nil, fakeRepo) + assert.Equal(t, "gitea.com", netrc.Machine) + assert.Empty(t, netrc.Login) + assert.Empty(t, netrc.Password) + }) - g.Describe("Creating a forge", func() { - g.It("Should return client with specified options", func() { - forge, _ := New(Opts{ - URL: "http://localhost:8080", - SkipVerify: true, - }) + t.Run("repository details", func(t *testing.T) { + repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name) + assert.NoError(t, err) + assert.Equal(t, fakeRepo.Owner, repo.Owner) + assert.Equal(t, fakeRepo.Name, repo.Name) + assert.Equal(t, fakeRepo.Owner+"/"+fakeRepo.Name, repo.FullName) + assert.True(t, repo.IsSCMPrivate) + assert.Equal(t, "http://localhost/test_name/repo_name.git", repo.Clone) + assert.Equal(t, "http://localhost/test_name/repo_name", repo.ForgeURL) + }) + t.Run("repo not found", func(t *testing.T) { + _, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name) + assert.Error(t, err) + }) - f, _ := forge.(*Gitea) - g.Assert(f.url).Equal("http://localhost:8080") - g.Assert(f.SkipVerify).Equal(true) - }) - }) + t.Run("repository list", func(t *testing.T) { + repos, err := c.Repos(ctx, fakeUser) + assert.NoError(t, err) + assert.Equal(t, fakeRepo.ForgeRemoteID, repos[0].ForgeRemoteID) + assert.Equal(t, fakeRepo.Owner, repos[0].Owner) + assert.Equal(t, fakeRepo.Name, repos[0].Name) + assert.Equal(t, fakeRepo.Owner+"/"+fakeRepo.Name, repos[0].FullName) + }) + t.Run("not found error", func(t *testing.T) { + _, err := c.Repos(ctx, fakeUserNoRepos) + assert.Error(t, err) + }) - g.Describe("Generating a netrc file", func() { - g.It("Should return a netrc with the user token", func() { - forge, _ := New(Opts{}) - netrc, _ := forge.Netrc(fakeUser, fakeRepo) - g.Assert(netrc.Machine).Equal("gitea.com") - g.Assert(netrc.Login).Equal(fakeUser.Login) - g.Assert(netrc.Password).Equal(fakeUser.AccessToken) - }) - g.It("Should return a netrc with the machine account", func() { - forge, _ := New(Opts{}) - netrc, _ := forge.Netrc(nil, fakeRepo) - g.Assert(netrc.Machine).Equal("gitea.com") - g.Assert(netrc.Login).Equal("") - g.Assert(netrc.Password).Equal("") - }) - }) + t.Run("register repository", func(t *testing.T) { + err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost") + assert.NoError(t, err) + }) - g.Describe("Requesting a repository", func() { - g.It("Should return the repository details", func() { - repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name) - g.Assert(err).IsNil() - g.Assert(repo.Owner).Equal(fakeRepo.Owner) - g.Assert(repo.Name).Equal(fakeRepo.Name) - g.Assert(repo.FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name) - g.Assert(repo.IsSCMPrivate).IsTrue() - g.Assert(repo.Clone).Equal("http://localhost/test_name/repo_name.git") - g.Assert(repo.ForgeURL).Equal("http://localhost/test_name/repo_name") - }) - g.It("Should handle a not found error", func() { - _, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name) - g.Assert(err).IsNotNil() - }) - }) + t.Run("remove hooks", func(t *testing.T) { + err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost") + assert.NoError(t, err) + }) - g.Describe("Requesting a repository list", func() { - g.It("Should return the repository list", func() { - repos, err := c.Repos(ctx, fakeUser) - g.Assert(err).IsNil() - g.Assert(repos[0].ForgeRemoteID).Equal(fakeRepo.ForgeRemoteID) - g.Assert(repos[0].Owner).Equal(fakeRepo.Owner) - g.Assert(repos[0].Name).Equal(fakeRepo.Name) - g.Assert(repos[0].FullName).Equal(fakeRepo.Owner + "/" + fakeRepo.Name) - }) - g.It("Should handle a not found error", func() { - _, err := c.Repos(ctx, fakeUserNoRepos) - g.Assert(err).IsNotNil() - }) - }) + t.Run("repository file", func(t *testing.T) { + raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml") + assert.NoError(t, err) + assert.Equal(t, "{ platform: linux/amd64 }", string(raw)) + }) - g.It("Should register repository hooks", func() { - err := c.Activate(ctx, fakeUser, fakeRepo, "http://localhost") - g.Assert(err).IsNil() - }) + t.Run("pipeline status", func(t *testing.T) { + err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow) + assert.NoError(t, err) + }) - g.It("Should remove repository hooks", func() { - err := c.Deactivate(ctx, fakeUser, fakeRepo, "http://localhost") - g.Assert(err).IsNil() - }) - - g.It("Should return a repository file", func() { - raw, err := c.File(ctx, fakeUser, fakeRepo, fakePipeline, ".woodpecker.yml") - g.Assert(err).IsNil() - g.Assert(string(raw)).Equal("{ platform: linux/amd64 }") - }) - - g.It("Should return nil from send pipeline status", func() { - err := c.Status(ctx, fakeUser, fakeRepo, fakePipeline, fakeWorkflow) - g.Assert(err).IsNil() - }) - - g.Describe("Given an authentication request", func() { - g.It("Should redirect to login form") - g.It("Should create an access token") - g.It("Should handle an access token error") - g.It("Should return the authenticated user") - }) - - g.Describe("Given a repository hook", func() { - g.It("Should skip non-push events") - g.It("Should return push details") - g.It("Should handle a parsing error") - }) - - g.It("Given a PR hook", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequest) - req, _ := http.NewRequest(http.MethodPost, "/hook", buf) - req.Header = http.Header{} - req.Header.Set(hookEvent, hookPullRequest) - mockStore.On("GetRepoNameFallback", mock.Anything, mock.Anything).Return(fakeRepo, nil) - mockStore.On("GetUser", mock.Anything).Return(fakeUser, nil) - r, b, err := c.Hook(ctx, req) - g.Assert(r).IsNotNil() - g.Assert(b).IsNotNil() - g.Assert(err).IsNil() - g.Assert(b.Event).Equal(model.EventPull) - g.Assert(utils.EqualSliceValues(b.ChangedFiles, []string{"README.md"})).IsTrue() - }) + t.Run("PR hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequest) + req, _ := http.NewRequest(http.MethodPost, "/hook", buf) + req.Header = http.Header{} + req.Header.Set(hookEvent, hookPullRequest) + mockStore.On("GetRepoNameFallback", mock.Anything, mock.Anything).Return(fakeRepo, nil) + mockStore.On("GetUser", mock.Anything).Return(fakeUser, nil) + r, b, err := c.Hook(ctx, req) + assert.NotNil(t, r) + assert.NotNil(t, b) + assert.NoError(t, err) + assert.Equal(t, model.EventPull, b.Event) + assert.Equal(t, []string{"README.md"}, b.ChangedFiles) }) } diff --git a/server/forge/gitea/helper_test.go b/server/forge/gitea/helper_test.go index 2f1cb94fd..b728699ae 100644 --- a/server/forge/gitea/helper_test.go +++ b/server/forge/gitea/helper_test.go @@ -20,255 +20,252 @@ import ( "testing" "code.gitea.io/sdk/gitea" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/forge/gitea/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/model" - "go.woodpecker-ci.org/woodpecker/v3/shared/utils" ) -func Test_parse(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("Gitea", func() { - g.It("Should parse push hook payload", func() { - buf := bytes.NewBufferString(fixtures.HookPush) - hook, err := parsePush(buf) - g.Assert(err).IsNil() - g.Assert(hook.Ref).Equal("refs/heads/main") - g.Assert(hook.After).Equal("ef98532add3b2feb7a137426bba1248724367df5") - g.Assert(hook.Before).Equal("4b2626259b5a97b6b4eab5e6cca66adb986b672b") - g.Assert(hook.Compare).Equal("http://gitea.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5") - g.Assert(hook.Repo.Name).Equal("hello-world") - g.Assert(hook.Repo.HTMLURL).Equal("http://gitea.golang.org/gordon/hello-world") - g.Assert(hook.Repo.Owner.UserName).Equal("gordon") - g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") - g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") - g.Assert(hook.Repo.Private).Equal(true) - g.Assert(hook.Pusher.Email).Equal("gordon@golang.org") - g.Assert(hook.Pusher.UserName).Equal("gordon") - g.Assert(hook.Sender.UserName).Equal("gordon") - g.Assert(hook.Sender.AvatarURL).Equal("http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - }) +func Test_parsePush(t *testing.T) { + t.Run("Should parse push hook payload", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPush) + hook, err := parsePush(buf) + assert.NoError(t, err) + assert.Equal(t, "refs/heads/main", hook.Ref) + assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.After) + assert.Equal(t, "4b2626259b5a97b6b4eab5e6cca66adb986b672b", hook.Before) + assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/compare/4b2626259b5a97b6b4eab5e6cca66adb986b672b...ef98532add3b2feb7a137426bba1248724367df5", hook.Compare) + assert.Equal(t, "hello-world", hook.Repo.Name) + assert.Equal(t, "http://gitea.golang.org/gordon/hello-world", hook.Repo.HTMLURL) + assert.Equal(t, "gordon", hook.Repo.Owner.UserName) + assert.Equal(t, "gordon/hello-world", hook.Repo.FullName) + assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email) + assert.True(t, hook.Repo.Private) + assert.Equal(t, "gordon@golang.org", hook.Pusher.Email) + assert.Equal(t, "gordon", hook.Pusher.UserName) + assert.Equal(t, "gordon", hook.Sender.UserName) + assert.Equal(t, "http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL) + }) + t.Run("Should parse tag hook payload", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookTag) + hook, err := parsePush(buf) + assert.NoError(t, err) + assert.Equal(t, "v1.0.0", hook.Ref) + assert.Equal(t, "ef98532add3b2feb7a137426bba1248724367df5", hook.Sha) + assert.Equal(t, "hello-world", hook.Repo.Name) + assert.Equal(t, "http://gitea.golang.org/gordon/hello-world", hook.Repo.HTMLURL) + assert.Equal(t, "gordon/hello-world", hook.Repo.FullName) + assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email) + assert.Equal(t, "gordon", hook.Repo.Owner.UserName) + assert.True(t, hook.Repo.Private) + assert.Equal(t, "gordon", hook.Sender.UserName) + assert.Equal(t, "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL) + }) - g.It("Should parse tag hook payload", func() { - buf := bytes.NewBufferString(fixtures.HookTag) - hook, err := parsePush(buf) - g.Assert(err).IsNil() - g.Assert(hook.Ref).Equal("v1.0.0") - g.Assert(hook.Sha).Equal("ef98532add3b2feb7a137426bba1248724367df5") - g.Assert(hook.Repo.Name).Equal("hello-world") - g.Assert(hook.Repo.HTMLURL).Equal("http://gitea.golang.org/gordon/hello-world") - g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") - g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") - g.Assert(hook.Repo.Owner.UserName).Equal("gordon") - g.Assert(hook.Repo.Private).Equal(true) - g.Assert(hook.Sender.UserName).Equal("gordon") - g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - }) + t.Run("Should return a Pipeline struct from a push hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPush) + hook, _ := parsePush(buf) + pipeline := pipelineFromPush(hook) + assert.Equal(t, model.EventPush, pipeline.Event) + assert.Equal(t, hook.After, pipeline.Commit) + assert.Equal(t, hook.Ref, pipeline.Ref) + assert.Equal(t, hook.Commits[0].URL, pipeline.ForgeURL) + assert.Equal(t, "main", pipeline.Branch) + assert.Equal(t, hook.Commits[0].Message, pipeline.Message) + assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar) + assert.Equal(t, hook.Sender.UserName, pipeline.Author) + assert.Equal(t, []string{"CHANGELOG.md", "app/controller/application.rb"}, pipeline.ChangedFiles) + }) - g.It("Should parse pull_request hook payload", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequest) - hook, err := parsePullRequest(buf) - g.Assert(err).IsNil() - g.Assert(hook.Action).Equal("opened") - g.Assert(hook.Number).Equal(int64(1)) + t.Run("Should return a Repo struct from a push hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPush) + hook, _ := parsePush(buf) + repo := toRepo(hook.Repo) + assert.Equal(t, hook.Repo.Name, repo.Name) + assert.Equal(t, hook.Repo.Owner.UserName, repo.Owner) + assert.Equal(t, "gordon/hello-world", repo.FullName) + assert.Equal(t, hook.Repo.HTMLURL, repo.ForgeURL) + }) - g.Assert(hook.Repo.Name).Equal("hello-world") - g.Assert(hook.Repo.HTMLURL).Equal("http://gitea.golang.org/gordon/hello-world") - g.Assert(hook.Repo.FullName).Equal("gordon/hello-world") - g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org") - g.Assert(hook.Repo.Owner.UserName).Equal("gordon") - g.Assert(hook.Repo.Private).Equal(true) - g.Assert(hook.Sender.UserName).Equal("gordon") - g.Assert(hook.Sender.AvatarURL).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - - g.Assert(hook.PullRequest.Title).Equal("Update the README with new information") - g.Assert(hook.PullRequest.Body).Equal("please merge") - g.Assert(hook.PullRequest.State).Equal(gitea.StateOpen) - g.Assert(hook.PullRequest.Poster.UserName).Equal("gordon") - g.Assert(hook.PullRequest.Base.Name).Equal("main") - g.Assert(hook.PullRequest.Base.Ref).Equal("main") - g.Assert(hook.PullRequest.Head.Name).Equal("feature/changes") - g.Assert(hook.PullRequest.Head.Ref).Equal("feature/changes") - }) - - g.It("Should return a Pipeline struct from a push hook", func() { - buf := bytes.NewBufferString(fixtures.HookPush) - hook, _ := parsePush(buf) - pipeline := pipelineFromPush(hook) - g.Assert(pipeline.Event).Equal(model.EventPush) - g.Assert(pipeline.Commit).Equal(hook.After) - g.Assert(pipeline.Ref).Equal(hook.Ref) - g.Assert(pipeline.ForgeURL).Equal(hook.Commits[0].URL) - g.Assert(pipeline.Branch).Equal("main") - g.Assert(pipeline.Message).Equal(hook.Commits[0].Message) - g.Assert(pipeline.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - g.Assert(pipeline.Author).Equal(hook.Sender.UserName) - g.Assert(utils.EqualSliceValues(pipeline.ChangedFiles, []string{"CHANGELOG.md", "app/controller/application.rb"})).IsTrue() - }) - - g.It("Should return a Repo struct from a push hook", func() { - buf := bytes.NewBufferString(fixtures.HookPush) - hook, _ := parsePush(buf) - repo := toRepo(hook.Repo) - g.Assert(repo.Name).Equal(hook.Repo.Name) - g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName) - g.Assert(repo.FullName).Equal("gordon/hello-world") - g.Assert(repo.ForgeURL).Equal(hook.Repo.HTMLURL) - }) - - g.It("Should return a Pipeline struct from a tag hook", func() { - buf := bytes.NewBufferString(fixtures.HookTag) - hook, _ := parsePush(buf) - pipeline := pipelineFromTag(hook) - g.Assert(pipeline.Event).Equal(model.EventTag) - g.Assert(pipeline.Commit).Equal(hook.Sha) - g.Assert(pipeline.Ref).Equal("refs/tags/v1.0.0") - g.Assert(pipeline.Branch).Equal("") - g.Assert(pipeline.ForgeURL).Equal("http://gitea.golang.org/gordon/hello-world/src/tag/v1.0.0") - g.Assert(pipeline.Message).Equal("created tag v1.0.0") - }) - - g.It("Should return a Pipeline struct from a pull_request hook", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequest) - hook, _ := parsePullRequest(buf) - pipeline := pipelineFromPullRequest(hook) - g.Assert(pipeline.Event).Equal(model.EventPull) - g.Assert(pipeline.Commit).Equal(hook.PullRequest.Head.Sha) - g.Assert(pipeline.Ref).Equal("refs/pull/1/head") - g.Assert(pipeline.ForgeURL).Equal("http://gitea.golang.org/gordon/hello-world/pull/1") - g.Assert(pipeline.Branch).Equal("main") - g.Assert(pipeline.Refspec).Equal("feature/changes:main") - g.Assert(pipeline.Message).Equal(hook.PullRequest.Title) - g.Assert(pipeline.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87") - g.Assert(pipeline.Author).Equal(hook.PullRequest.Poster.UserName) - }) - - g.It("Should return a Repo struct from a pull_request hook", func() { - buf := bytes.NewBufferString(fixtures.HookPullRequest) - hook, _ := parsePullRequest(buf) - repo := toRepo(hook.Repo) - g.Assert(repo.Name).Equal(hook.Repo.Name) - g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName) - g.Assert(repo.FullName).Equal("gordon/hello-world") - g.Assert(repo.ForgeURL).Equal(hook.Repo.HTMLURL) - }) - - g.It("Should return a Perm struct from a Gitea Perm", func() { - perms := []gitea.Permission{ - { - Admin: true, - Push: true, - Pull: true, - }, - { - Admin: true, - Push: true, - Pull: false, - }, - { - Admin: true, - Push: false, - Pull: false, - }, - } - for _, from := range perms { - perm := toPerm(&from) - g.Assert(perm.Pull).Equal(from.Pull) - g.Assert(perm.Push).Equal(from.Push) - g.Assert(perm.Admin).Equal(from.Admin) - } - }) - - g.It("Should return a Team struct from a Gitea Org", func() { - from := &gitea.Organization{ - UserName: "woodpecker", - AvatarURL: "/avatars/1", - } - - to := toTeam(from, "http://localhost:80") - g.Assert(to.Login).Equal(from.UserName) - g.Assert(to.Avatar).Equal("http://localhost:80/avatars/1") - }) - - g.It("Should return a Repo struct from a Gitea Repo", func() { - from := gitea.Repository{ - FullName: "gophers/hello-world", - Owner: &gitea.User{ - UserName: "gordon", - AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - }, - CloneURL: "http://gitea.golang.org/gophers/hello-world.git", - HTMLURL: "http://gitea.golang.org/gophers/hello-world", - Private: true, - DefaultBranch: "main", - Permissions: &gitea.Permission{Admin: true}, - } - repo := toRepo(&from) - g.Assert(repo.FullName).Equal(from.FullName) - g.Assert(repo.Owner).Equal(from.Owner.UserName) - g.Assert(repo.Name).Equal("hello-world") - g.Assert(repo.Branch).Equal("main") - g.Assert(repo.ForgeURL).Equal(from.HTMLURL) - g.Assert(repo.Clone).Equal(from.CloneURL) - g.Assert(repo.Avatar).Equal(from.Owner.AvatarURL) - g.Assert(repo.IsSCMPrivate).Equal(from.Private) - g.Assert(repo.Perm.Admin).IsTrue() - }) - - g.It("Should correct a malformed avatar url", func() { - urls := []struct { - Before string - After string - }{ - { - "http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - }, - { - "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - }, - { - "http://gitea.golang.org/avatars/1", - "http://gitea.golang.org/avatars/1", - }, - { - "http://gitea.golang.org//avatars/1", - "http://gitea.golang.org/avatars/1", - }, - } - - for _, url := range urls { - got := fixMalformedAvatar(url.Before) - g.Assert(got).Equal(url.After) - } - }) - - g.It("Should expand the avatar url", func() { - urls := []struct { - Before string - After string - }{ - { - "/avatars/1", - "http://gitea.io/avatars/1", - }, - { - "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", - }, - { - "/gitea/avatars/2", - "http://gitea.io/gitea/avatars/2", - }, - } - - repo := "http://gitea.io/foo/bar" - for _, url := range urls { - got := expandAvatar(repo, url.Before) - g.Assert(got).Equal(url.After) - } - }) + t.Run("Should return a Pipeline struct from a tag hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookTag) + hook, _ := parsePush(buf) + pipeline := pipelineFromTag(hook) + assert.Equal(t, model.EventTag, pipeline.Event) + assert.Equal(t, hook.Sha, pipeline.Commit) + assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref) + assert.Empty(t, pipeline.Branch) + assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/src/tag/v1.0.0", pipeline.ForgeURL) + assert.Equal(t, "created tag v1.0.0", pipeline.Message) }) } + +func Test_parsePullRequest(t *testing.T) { + t.Run("Should parse pull_request hook payload", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequest) + hook, err := parsePullRequest(buf) + assert.NoError(t, err) + assert.Equal(t, "opened", hook.Action) + assert.Equal(t, int64(1), hook.Number) + + assert.Equal(t, "hello-world", hook.Repo.Name) + assert.Equal(t, "http://gitea.golang.org/gordon/hello-world", hook.Repo.HTMLURL) + assert.Equal(t, "gordon/hello-world", hook.Repo.FullName) + assert.Equal(t, "gordon@golang.org", hook.Repo.Owner.Email) + assert.Equal(t, "gordon", hook.Repo.Owner.UserName) + assert.True(t, hook.Repo.Private) + assert.Equal(t, "gordon", hook.Sender.UserName) + assert.Equal(t, "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", hook.Sender.AvatarURL) + + assert.Equal(t, "Update the README with new information", hook.PullRequest.Title) + assert.Equal(t, "please merge", hook.PullRequest.Body) + assert.Equal(t, gitea.StateOpen, hook.PullRequest.State) + assert.Equal(t, "gordon", hook.PullRequest.Poster.UserName) + assert.Equal(t, "main", hook.PullRequest.Base.Name) + assert.Equal(t, "main", hook.PullRequest.Base.Ref) + assert.Equal(t, "feature/changes", hook.PullRequest.Head.Name) + assert.Equal(t, "feature/changes", hook.PullRequest.Head.Ref) + }) + + t.Run("Should return a Pipeline struct from a pull_request hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequest) + hook, _ := parsePullRequest(buf) + pipeline := pipelineFromPullRequest(hook) + assert.Equal(t, model.EventPull, pipeline.Event) + assert.Equal(t, hook.PullRequest.Head.Sha, pipeline.Commit) + assert.Equal(t, "refs/pull/1/head", pipeline.Ref) + assert.Equal(t, "http://gitea.golang.org/gordon/hello-world/pull/1", pipeline.ForgeURL) + assert.Equal(t, "main", pipeline.Branch) + assert.Equal(t, "feature/changes:main", pipeline.Refspec) + assert.Equal(t, hook.PullRequest.Title, pipeline.Message) + assert.Equal(t, "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", pipeline.Avatar) + assert.Equal(t, hook.PullRequest.Poster.UserName, pipeline.Author) + }) + + t.Run("Should return a Repo struct from a pull_request hook", func(t *testing.T) { + buf := bytes.NewBufferString(fixtures.HookPullRequest) + hook, _ := parsePullRequest(buf) + repo := toRepo(hook.Repo) + assert.Equal(t, hook.Repo.Name, repo.Name) + assert.Equal(t, hook.Repo.Owner.UserName, repo.Owner) + assert.Equal(t, "gordon/hello-world", repo.FullName) + assert.Equal(t, hook.Repo.HTMLURL, repo.ForgeURL) + }) +} + +func Test_toPerm(t *testing.T) { + perms := []gitea.Permission{ + { + Admin: true, + Push: true, + Pull: true, + }, + { + Admin: true, + Push: true, + Pull: false, + }, + { + Admin: true, + Push: false, + Pull: false, + }, + } + for _, from := range perms { + perm := toPerm(&from) + assert.Equal(t, from.Pull, perm.Pull) + assert.Equal(t, from.Push, perm.Push) + assert.Equal(t, from.Admin, perm.Admin) + } +} + +func Test_toTeam(t *testing.T) { + from := &gitea.Organization{ + UserName: "woodpecker", + AvatarURL: "/avatars/1", + } + + to := toTeam(from, "http://localhost:80") + assert.Equal(t, from.UserName, to.Login) + assert.Equal(t, "http://localhost:80/avatars/1", to.Avatar) +} + +func Test_toRepo(t *testing.T) { + from := gitea.Repository{ + FullName: "gophers/hello-world", + Owner: &gitea.User{ + UserName: "gordon", + AvatarURL: "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + }, + CloneURL: "http://gitea.golang.org/gophers/hello-world.git", + HTMLURL: "http://gitea.golang.org/gophers/hello-world", + Private: true, + DefaultBranch: "main", + Permissions: &gitea.Permission{Admin: true}, + } + repo := toRepo(&from) + assert.Equal(t, from.FullName, repo.FullName) + assert.Equal(t, from.Owner.UserName, repo.Owner) + assert.Equal(t, "hello-world", repo.Name) + assert.Equal(t, "main", repo.Branch) + assert.Equal(t, from.HTMLURL, repo.ForgeURL) + assert.Equal(t, from.CloneURL, repo.Clone) + assert.Equal(t, from.Owner.AvatarURL, repo.Avatar) + assert.Equal(t, from.Private, repo.IsSCMPrivate) + assert.True(t, repo.Perm.Admin) +} + +func Test_fixMalformedAvatar(t *testing.T) { + urls := []struct { + Before string + After string + }{ + { + "http://gitea.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + }, + { + "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + }, + { + "http://gitea.golang.org/avatars/1", + "http://gitea.golang.org/avatars/1", + }, + { + "http://gitea.golang.org//avatars/1", + "http://gitea.golang.org/avatars/1", + }, + } + + for _, url := range urls { + got := fixMalformedAvatar(url.Before) + assert.Equal(t, url.After, got) + } +} + +func Test_expandAvatar(t *testing.T) { + urls := []struct { + Before string + After string + }{ + { + "/avatars/1", + "http://gitea.io/avatars/1", + }, + { + "//1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + "http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87", + }, + { + "/gitea/avatars/2", + "http://gitea.io/gitea/avatars/2", + }, + } + + repo := "http://gitea.io/foo/bar" + for _, url := range urls { + got := expandAvatar(repo, url.Before) + assert.Equal(t, url.After, got) + } +} diff --git a/server/forge/github/convert_test.go b/server/forge/github/convert_test.go index 2b4998bb5..816cec9d0 100644 --- a/server/forge/github/convert_test.go +++ b/server/forge/github/convert_test.go @@ -18,280 +18,261 @@ package github import ( "testing" - "github.com/franela/goblin" "github.com/google/go-github/v68/github" + "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/model" ) -func Test_helper(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("GitHub converter", func() { - g.It("should convert passing status", func() { - g.Assert(convertStatus(model.StatusSuccess)).Equal(statusSuccess) - }) +func Test_convertStatus(t *testing.T) { + assert.Equal(t, statusSuccess, convertStatus(model.StatusSuccess)) + assert.Equal(t, statusPending, convertStatus(model.StatusPending)) + assert.Equal(t, statusPending, convertStatus(model.StatusRunning)) + assert.Equal(t, statusFailure, convertStatus(model.StatusFailure)) + assert.Equal(t, statusError, convertStatus(model.StatusKilled)) + assert.Equal(t, statusError, convertStatus(model.StatusError)) +} - g.It("should convert pending status", func() { - g.Assert(convertStatus(model.StatusPending)).Equal(statusPending) - g.Assert(convertStatus(model.StatusRunning)).Equal(statusPending) - }) +func Test_convertDesc(t *testing.T) { + assert.Equal(t, descSuccess, convertDesc(model.StatusSuccess)) + assert.Equal(t, descPending, convertDesc(model.StatusPending)) + assert.Equal(t, descPending, convertDesc(model.StatusRunning)) + assert.Equal(t, descFailure, convertDesc(model.StatusFailure)) + assert.Equal(t, descError, convertDesc(model.StatusKilled)) + assert.Equal(t, descError, convertDesc(model.StatusError)) +} - g.It("should convert failing status", func() { - g.Assert(convertStatus(model.StatusFailure)).Equal(statusFailure) - }) - - g.It("should convert error status", func() { - g.Assert(convertStatus(model.StatusKilled)).Equal(statusError) - g.Assert(convertStatus(model.StatusError)).Equal(statusError) - }) - - g.It("should convert passing desc", func() { - g.Assert(convertDesc(model.StatusSuccess)).Equal(descSuccess) - }) - - g.It("should convert pending desc", func() { - g.Assert(convertDesc(model.StatusPending)).Equal(descPending) - g.Assert(convertDesc(model.StatusRunning)).Equal(descPending) - }) - - g.It("should convert failing desc", func() { - g.Assert(convertDesc(model.StatusFailure)).Equal(descFailure) - }) - - g.It("should convert error desc", func() { - g.Assert(convertDesc(model.StatusKilled)).Equal(descError) - g.Assert(convertDesc(model.StatusError)).Equal(descError) - }) - - g.It("should convert repository list", func() { - from := []*github.Repository{ - { - Private: github.Ptr(false), - FullName: github.Ptr("octocat/hello-world"), - Name: github.Ptr("hello-world"), - Owner: &github.User{ - AvatarURL: github.Ptr("http://..."), - Login: github.Ptr("octocat"), - }, - HTMLURL: github.Ptr("https://github.com/octocat/hello-world"), - CloneURL: github.Ptr("https://github.com/octocat/hello-world.git"), - Permissions: map[string]bool{ - "push": true, - "pull": true, - "admin": true, - }, - }, - } - - to := convertRepoList(from) - g.Assert(to[0].Avatar).Equal("http://...") - g.Assert(to[0].FullName).Equal("octocat/hello-world") - g.Assert(to[0].Owner).Equal("octocat") - g.Assert(to[0].Name).Equal("hello-world") - }) - - g.It("should convert repository", func() { - from := github.Repository{ - FullName: github.Ptr("octocat/hello-world"), - Name: github.Ptr("hello-world"), - HTMLURL: github.Ptr("https://github.com/octocat/hello-world"), - CloneURL: github.Ptr("https://github.com/octocat/hello-world.git"), - DefaultBranch: github.Ptr("develop"), - Private: github.Ptr(true), - Owner: &github.User{ - AvatarURL: github.Ptr("http://..."), - Login: github.Ptr("octocat"), - }, - Permissions: map[string]bool{ - "push": true, - "pull": true, - "admin": true, - }, - } - - to := convertRepo(&from) - g.Assert(to.Avatar).Equal("http://...") - g.Assert(to.FullName).Equal("octocat/hello-world") - g.Assert(to.Owner).Equal("octocat") - g.Assert(to.Name).Equal("hello-world") - g.Assert(to.Branch).Equal("develop") - g.Assert(to.IsSCMPrivate).IsTrue() - g.Assert(to.Clone).Equal("https://github.com/octocat/hello-world.git") - g.Assert(to.ForgeURL).Equal("https://github.com/octocat/hello-world") - }) - - g.It("should convert repository permissions", func() { - from := &github.Repository{ - Permissions: map[string]bool{ - "admin": true, - "push": true, - "pull": true, - }, - } - - to := convertPerm(from.GetPermissions()) - g.Assert(to.Push).IsTrue() - g.Assert(to.Pull).IsTrue() - g.Assert(to.Admin).IsTrue() - }) - - g.It("should convert team", func() { - from := &github.Organization{ - Login: github.Ptr("octocat"), +func Test_convertRepoList(t *testing.T) { + from := []*github.Repository{ + { + Private: github.Ptr(false), + FullName: github.Ptr("octocat/hello-world"), + Name: github.Ptr("hello-world"), + Owner: &github.User{ AvatarURL: github.Ptr("http://..."), - } - to := convertTeam(from) - g.Assert(to.Login).Equal("octocat") - g.Assert(to.Avatar).Equal("http://...") - }) + Login: github.Ptr("octocat"), + }, + HTMLURL: github.Ptr("https://github.com/octocat/hello-world"), + CloneURL: github.Ptr("https://github.com/octocat/hello-world.git"), + Permissions: map[string]bool{ + "push": true, + "pull": true, + "admin": true, + }, + }, + } - g.It("should convert team list", func() { - from := []*github.Organization{ - { - Login: github.Ptr("octocat"), - AvatarURL: github.Ptr("http://..."), - }, - } - to := convertTeamList(from) - g.Assert(to[0].Login).Equal("octocat") - g.Assert(to[0].Avatar).Equal("http://...") - }) + to := convertRepoList(from) + assert.Equal(t, "http://...", to[0].Avatar) + assert.Equal(t, "octocat/hello-world", to[0].FullName) + assert.Equal(t, "octocat", to[0].Owner) + assert.Equal(t, "hello-world", to[0].Name) +} - g.It("should convert a repository from webhook", func() { - from := &github.PushEventRepository{Owner: &github.User{}} - from.Owner.Login = github.Ptr("octocat") - from.Owner.Name = github.Ptr("octocat") - from.Name = github.Ptr("hello-world") - from.FullName = github.Ptr("octocat/hello-world") - from.Private = github.Ptr(true) - from.HTMLURL = github.Ptr("https://github.com/octocat/hello-world") - from.CloneURL = github.Ptr("https://github.com/octocat/hello-world.git") - from.DefaultBranch = github.Ptr("develop") +func Test_convertRepo(t *testing.T) { + from := github.Repository{ + FullName: github.Ptr("octocat/hello-world"), + Name: github.Ptr("hello-world"), + HTMLURL: github.Ptr("https://github.com/octocat/hello-world"), + CloneURL: github.Ptr("https://github.com/octocat/hello-world.git"), + DefaultBranch: github.Ptr("develop"), + Private: github.Ptr(true), + Owner: &github.User{ + AvatarURL: github.Ptr("http://..."), + Login: github.Ptr("octocat"), + }, + Permissions: map[string]bool{ + "push": true, + "pull": true, + "admin": true, + }, + } - repo := convertRepoHook(from) - g.Assert(repo.Owner).Equal(*from.Owner.Login) - g.Assert(repo.Name).Equal(*from.Name) - g.Assert(repo.FullName).Equal(*from.FullName) - g.Assert(repo.IsSCMPrivate).Equal(*from.Private) - g.Assert(repo.ForgeURL).Equal(*from.HTMLURL) - g.Assert(repo.Clone).Equal(*from.CloneURL) - g.Assert(repo.Branch).Equal(*from.DefaultBranch) - }) + to := convertRepo(&from) + assert.Equal(t, "http://...", to.Avatar) + assert.Equal(t, "octocat/hello-world", to.FullName) + assert.Equal(t, "octocat", to.Owner) + assert.Equal(t, "hello-world", to.Name) + assert.Equal(t, "develop", to.Branch) + assert.True(t, to.IsSCMPrivate) + assert.Equal(t, "https://github.com/octocat/hello-world.git", to.Clone) + assert.Equal(t, "https://github.com/octocat/hello-world", to.ForgeURL) +} - g.It("should convert a pull request from webhook", func() { - from := &github.PullRequestEvent{ - Action: github.Ptr(actionOpen), - PullRequest: &github.PullRequest{ - State: github.Ptr(stateOpen), - HTMLURL: github.Ptr("https://github.com/octocat/hello-world/pulls/42"), - Number: github.Ptr(42), - Title: github.Ptr("Updated README.md"), - Base: &github.PullRequestBranch{ - Ref: github.Ptr("main"), - }, - Head: &github.PullRequestBranch{ - Ref: github.Ptr("changes"), - SHA: github.Ptr("f72fc19"), - Repo: &github.Repository{ - CloneURL: github.Ptr("https://github.com/octocat/hello-world-fork"), - }, - }, - User: &github.User{ - Login: github.Ptr("octocat"), - AvatarURL: github.Ptr("https://avatars1.githubusercontent.com/u/583231"), - }, - }, Sender: &github.User{ - Login: github.Ptr("octocat"), - }, - } - pull, _, pipeline, err := parsePullHook(from, true) - g.Assert(err).IsNil() - g.Assert(pull).IsNotNil() - g.Assert(pipeline.Event).Equal(model.EventPull) - g.Assert(pipeline.Branch).Equal(*from.PullRequest.Base.Ref) - g.Assert(pipeline.Ref).Equal("refs/pull/42/merge") - g.Assert(pipeline.Refspec).Equal("changes:main") - g.Assert(pipeline.Commit).Equal(*from.PullRequest.Head.SHA) - g.Assert(pipeline.Message).Equal(*from.PullRequest.Title) - g.Assert(pipeline.Title).Equal(*from.PullRequest.Title) - g.Assert(pipeline.Author).Equal(*from.PullRequest.User.Login) - g.Assert(pipeline.Avatar).Equal(*from.PullRequest.User.AvatarURL) - g.Assert(pipeline.Sender).Equal(*from.Sender.Login) - }) +func Test_convertPerm(t *testing.T) { + from := &github.Repository{ + Permissions: map[string]bool{ + "admin": true, + "push": true, + "pull": true, + }, + } - g.It("should convert a deployment from webhook", func() { - from := &github.DeploymentEvent{Deployment: &github.Deployment{}, Sender: &github.User{}} - from.Deployment.Description = github.Ptr(":shipit:") - from.Deployment.Environment = github.Ptr("production") - from.Deployment.Task = github.Ptr("deploy") - from.Deployment.ID = github.Ptr(int64(42)) - from.Deployment.Ref = github.Ptr("main") - from.Deployment.SHA = github.Ptr("f72fc19") - from.Deployment.URL = github.Ptr("https://github.com/octocat/hello-world") - from.Sender.Login = github.Ptr("octocat") - from.Sender.AvatarURL = github.Ptr("https://avatars1.githubusercontent.com/u/583231") + to := convertPerm(from.GetPermissions()) + assert.True(t, to.Push) + assert.True(t, to.Pull) + assert.True(t, to.Admin) +} - _, pipeline := parseDeployHook(from) - g.Assert(pipeline.Event).Equal(model.EventDeploy) - g.Assert(pipeline.Branch).Equal("main") - g.Assert(pipeline.Ref).Equal("refs/heads/main") - g.Assert(pipeline.Commit).Equal(*from.Deployment.SHA) - g.Assert(pipeline.Message).Equal(*from.Deployment.Description) - g.Assert(pipeline.ForgeURL).Equal(*from.Deployment.URL) - g.Assert(pipeline.Author).Equal(*from.Sender.Login) - g.Assert(pipeline.Avatar).Equal(*from.Sender.AvatarURL) - }) +func Test_convertTeam(t *testing.T) { + from := &github.Organization{ + Login: github.Ptr("octocat"), + AvatarURL: github.Ptr("http://..."), + } + to := convertTeam(from) + assert.Equal(t, "octocat", to.Login) + assert.Equal(t, "http://...", to.Avatar) +} - g.It("should convert a push from webhook", func() { - from := &github.PushEvent{Sender: &github.User{}, Repo: &github.PushEventRepository{}, HeadCommit: &github.HeadCommit{Author: &github.CommitAuthor{}}} - from.Sender.Login = github.Ptr("octocat") - from.Sender.AvatarURL = github.Ptr("https://avatars1.githubusercontent.com/u/583231") - from.Repo.CloneURL = github.Ptr("https://github.com/octocat/hello-world.git") - from.HeadCommit.Author.Email = github.Ptr("github.Ptr(octocat@github.com") - from.HeadCommit.Message = github.Ptr("updated README.md") - from.HeadCommit.URL = github.Ptr("https://github.com/octocat/hello-world") - from.HeadCommit.ID = github.Ptr("f72fc19") - from.Ref = github.Ptr("refs/heads/main") +func Test_convertTeamList(t *testing.T) { + from := []*github.Organization{ + { + Login: github.Ptr("octocat"), + AvatarURL: github.Ptr("http://..."), + }, + } + to := convertTeamList(from) + assert.Equal(t, "octocat", to[0].Login) + assert.Equal(t, "http://...", to[0].Avatar) +} - _, pipeline := parsePushHook(from) - g.Assert(pipeline.Event).Equal(model.EventPush) - g.Assert(pipeline.Branch).Equal("main") - g.Assert(pipeline.Ref).Equal("refs/heads/main") - g.Assert(pipeline.Commit).Equal(*from.HeadCommit.ID) - g.Assert(pipeline.Message).Equal(*from.HeadCommit.Message) - g.Assert(pipeline.ForgeURL).Equal(*from.HeadCommit.URL) - g.Assert(pipeline.Author).Equal(*from.Sender.Login) - g.Assert(pipeline.Avatar).Equal(*from.Sender.AvatarURL) - g.Assert(pipeline.Email).Equal(*from.HeadCommit.Author.Email) - }) +func Test_convertRepoHook(t *testing.T) { + t.Run("should convert a repository from webhook", func(t *testing.T) { + from := &github.PushEventRepository{Owner: &github.User{}} + from.Owner.Login = github.Ptr("octocat") + from.Owner.Name = github.Ptr("octocat") + from.Name = github.Ptr("hello-world") + from.FullName = github.Ptr("octocat/hello-world") + from.Private = github.Ptr(true) + from.HTMLURL = github.Ptr("https://github.com/octocat/hello-world") + from.CloneURL = github.Ptr("https://github.com/octocat/hello-world.git") + from.DefaultBranch = github.Ptr("develop") - g.It("should convert a tag from webhook", func() { - from := &github.PushEvent{} - from.Ref = github.Ptr("refs/tags/v1.0.0") - - _, pipeline := parsePushHook(from) - g.Assert(pipeline.Event).Equal(model.EventTag) - g.Assert(pipeline.Ref).Equal("refs/tags/v1.0.0") - }) - - g.It("should convert tag's base branch from webhook to pipeline's branch ", func() { - from := &github.PushEvent{} - from.Ref = github.Ptr("refs/tags/v1.0.0") - from.BaseRef = github.Ptr("refs/heads/main") - - _, pipeline := parsePushHook(from) - g.Assert(pipeline.Event).Equal(model.EventTag) - g.Assert(pipeline.Branch).Equal("main") - }) - - g.It("should not convert tag's base_ref from webhook if not prefixed with 'ref/heads/'", func() { - from := &github.PushEvent{} - from.Ref = github.Ptr("refs/tags/v1.0.0") - from.BaseRef = github.Ptr("refs/refs/main") - - _, pipeline := parsePushHook(from) - g.Assert(pipeline.Event).Equal(model.EventTag) - g.Assert(pipeline.Branch).Equal("refs/tags/v1.0.0") - }) + repo := convertRepoHook(from) + assert.Equal(t, *from.Owner.Login, repo.Owner) + assert.Equal(t, *from.Name, repo.Name) + assert.Equal(t, *from.FullName, repo.FullName) + assert.Equal(t, *from.Private, repo.IsSCMPrivate) + assert.Equal(t, *from.HTMLURL, repo.ForgeURL) + assert.Equal(t, *from.CloneURL, repo.Clone) + assert.Equal(t, *from.DefaultBranch, repo.Branch) + }) +} + +func Test_parsePullHook(t *testing.T) { + from := &github.PullRequestEvent{ + Action: github.Ptr(actionOpen), + PullRequest: &github.PullRequest{ + State: github.Ptr(stateOpen), + HTMLURL: github.Ptr("https://github.com/octocat/hello-world/pulls/42"), + Number: github.Ptr(42), + Title: github.Ptr("Updated README.md"), + Base: &github.PullRequestBranch{ + Ref: github.Ptr("main"), + }, + Head: &github.PullRequestBranch{ + Ref: github.Ptr("changes"), + SHA: github.Ptr("f72fc19"), + Repo: &github.Repository{ + CloneURL: github.Ptr("https://github.com/octocat/hello-world-fork"), + }, + }, + User: &github.User{ + Login: github.Ptr("octocat"), + AvatarURL: github.Ptr("https://avatars1.githubusercontent.com/u/583231"), + }, + }, Sender: &github.User{ + Login: github.Ptr("octocat"), + }, + } + pull, _, pipeline, err := parsePullHook(from, true) + assert.NoError(t, err) + assert.NotNil(t, pull) + assert.Equal(t, model.EventPull, pipeline.Event) + assert.Equal(t, *from.PullRequest.Base.Ref, pipeline.Branch) + assert.Equal(t, "refs/pull/42/merge", pipeline.Ref) + assert.Equal(t, "changes:main", pipeline.Refspec) + assert.Equal(t, *from.PullRequest.Head.SHA, pipeline.Commit) + assert.Equal(t, *from.PullRequest.Title, pipeline.Message) + assert.Equal(t, *from.PullRequest.Title, pipeline.Title) + assert.Equal(t, *from.PullRequest.User.Login, pipeline.Author) + assert.Equal(t, *from.PullRequest.User.AvatarURL, pipeline.Avatar) + assert.Equal(t, *from.Sender.Login, pipeline.Sender) +} + +func Test_parseDeployHook(t *testing.T) { + from := &github.DeploymentEvent{Deployment: &github.Deployment{}, Sender: &github.User{}} + from.Deployment.Description = github.Ptr(":shipit:") + from.Deployment.Environment = github.Ptr("production") + from.Deployment.Task = github.Ptr("deploy") + from.Deployment.ID = github.Ptr(int64(42)) + from.Deployment.Ref = github.Ptr("main") + from.Deployment.SHA = github.Ptr("f72fc19") + from.Deployment.URL = github.Ptr("https://github.com/octocat/hello-world") + from.Sender.Login = github.Ptr("octocat") + from.Sender.AvatarURL = github.Ptr("https://avatars1.githubusercontent.com/u/583231") + + _, pipeline := parseDeployHook(from) + assert.Equal(t, model.EventDeploy, pipeline.Event) + assert.Equal(t, "main", pipeline.Branch) + assert.Equal(t, "refs/heads/main", pipeline.Ref) + assert.Equal(t, *from.Deployment.SHA, pipeline.Commit) + assert.Equal(t, *from.Deployment.Description, pipeline.Message) + assert.Equal(t, *from.Deployment.URL, pipeline.ForgeURL) + assert.Equal(t, *from.Sender.Login, pipeline.Author) + assert.Equal(t, *from.Sender.AvatarURL, pipeline.Avatar) +} + +func Test_parsePushHook(t *testing.T) { + t.Run("convert push from webhook", func(t *testing.T) { + from := &github.PushEvent{Sender: &github.User{}, Repo: &github.PushEventRepository{}, HeadCommit: &github.HeadCommit{Author: &github.CommitAuthor{}}} + from.Sender.Login = github.Ptr("octocat") + from.Sender.AvatarURL = github.Ptr("https://avatars1.githubusercontent.com/u/583231") + from.Repo.CloneURL = github.Ptr("https://github.com/octocat/hello-world.git") + from.HeadCommit.Author.Email = github.Ptr("github.Ptr(octocat@github.com") + from.HeadCommit.Message = github.Ptr("updated README.md") + from.HeadCommit.URL = github.Ptr("https://github.com/octocat/hello-world") + from.HeadCommit.ID = github.Ptr("f72fc19") + from.Ref = github.Ptr("refs/heads/main") + + _, pipeline := parsePushHook(from) + assert.Equal(t, model.EventPush, pipeline.Event) + assert.Equal(t, "main", pipeline.Branch) + assert.Equal(t, "refs/heads/main", pipeline.Ref) + assert.Equal(t, *from.HeadCommit.ID, pipeline.Commit) + assert.Equal(t, *from.HeadCommit.Message, pipeline.Message) + assert.Equal(t, *from.HeadCommit.URL, pipeline.ForgeURL) + assert.Equal(t, *from.Sender.Login, pipeline.Author) + assert.Equal(t, *from.Sender.AvatarURL, pipeline.Avatar) + assert.Equal(t, *from.HeadCommit.Author.Email, pipeline.Email) + }) + + t.Run("convert tag from webhook", func(t *testing.T) { + from := &github.PushEvent{} + from.Ref = github.Ptr("refs/tags/v1.0.0") + + _, pipeline := parsePushHook(from) + assert.Equal(t, model.EventTag, pipeline.Event) + assert.Equal(t, "refs/tags/v1.0.0", pipeline.Ref) + }) + + t.Run("convert tag's base branch to pipeline's branch ", func(t *testing.T) { + from := &github.PushEvent{} + from.Ref = github.Ptr("refs/tags/v1.0.0") + from.BaseRef = github.Ptr("refs/heads/main") + + _, pipeline := parsePushHook(from) + assert.Equal(t, model.EventTag, pipeline.Event) + assert.Equal(t, "main", pipeline.Branch) + }) + + t.Run("not convert tag's base_ref from webhook if not prefixed with 'ref/heads/'", func(t *testing.T) { + from := &github.PushEvent{} + from.Ref = github.Ptr("refs/tags/v1.0.0") + from.BaseRef = github.Ptr("refs/refs/main") + + _, pipeline := parsePushHook(from) + assert.Equal(t, model.EventTag, pipeline.Event) + assert.Equal(t, "refs/tags/v1.0.0", pipeline.Branch) }) } diff --git a/server/forge/github/github_test.go b/server/forge/github/github_test.go index c2d46bfc7..59751978b 100644 --- a/server/forge/github/github_test.go +++ b/server/forge/github/github_test.go @@ -20,13 +20,28 @@ import ( "net/http/httptest" "testing" - "github.com/franela/goblin" "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/forge/github/fixtures" "go.woodpecker-ci.org/woodpecker/v3/server/model" ) +func TestNew(t *testing.T) { + forge, _ := New(Opts{ + URL: "http://localhost:8080/", + Client: "0ZXh0IjoiI", + Secret: "I1NiIsInR5", + SkipVerify: true, + }) + f, _ := forge.(*client) + assert.Equal(t, "http://localhost:8080", f.url) + assert.Equal(t, "http://localhost:8080/api/v3/", f.API) + assert.Equal(t, "0ZXh0IjoiI", f.Client) + assert.Equal(t, "I1NiIsInR5", f.Secret) + assert.True(t, f.SkipVerify) +} + func Test_github(t *testing.T) { gin.SetMode(gin.TestMode) @@ -36,80 +51,39 @@ func Test_github(t *testing.T) { SkipVerify: true, }) + defer s.Close() + ctx := context.Background() - g := goblin.Goblin(t) - g.Describe("GitHub", func() { - g.After(func() { - s.Close() - }) - g.Describe("Creating a forge", func() { - g.It("Should return client with specified options", func() { - forge, _ := New(Opts{ - URL: "http://localhost:8080/", - Client: "0ZXh0IjoiI", - Secret: "I1NiIsInR5", - SkipVerify: true, - }) - f, _ := forge.(*client) - g.Assert(f.url).Equal("http://localhost:8080") - g.Assert(f.API).Equal("http://localhost:8080/api/v3/") - g.Assert(f.Client).Equal("0ZXh0IjoiI") - g.Assert(f.Secret).Equal("I1NiIsInR5") - g.Assert(f.SkipVerify).Equal(true) - }) - }) + t.Run("netrc with user token", func(t *testing.T) { + forge, _ := New(Opts{}) + netrc, _ := forge.Netrc(fakeUser, fakeRepo) + assert.Equal(t, "github.com", netrc.Machine) + assert.Equal(t, fakeUser.AccessToken, netrc.Login) + assert.Equal(t, "x-oauth-basic", netrc.Password) + }) + t.Run("netrc with machine account", func(t *testing.T) { + forge, _ := New(Opts{}) + netrc, _ := forge.Netrc(nil, fakeRepo) + assert.Equal(t, "github.com", netrc.Machine) + assert.Empty(t, netrc.Login) + assert.Empty(t, netrc.Password) + }) - g.Describe("Generating a netrc file", func() { - g.It("Should return a netrc with the user token", func() { - forge, _ := New(Opts{}) - netrc, _ := forge.Netrc(fakeUser, fakeRepo) - g.Assert(netrc.Machine).Equal("github.com") - g.Assert(netrc.Login).Equal(fakeUser.AccessToken) - g.Assert(netrc.Password).Equal("x-oauth-basic") - }) - g.It("Should return a netrc with the machine account", func() { - forge, _ := New(Opts{}) - netrc, _ := forge.Netrc(nil, fakeRepo) - g.Assert(netrc.Machine).Equal("github.com") - g.Assert(netrc.Login).Equal("") - g.Assert(netrc.Password).Equal("") - }) - }) - - g.Describe("Requesting a repository", func() { - g.It("Should return the repository details", func() { - repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name) - g.Assert(err).IsNil() - g.Assert(repo.ForgeRemoteID).Equal(fakeRepo.ForgeRemoteID) - g.Assert(repo.Owner).Equal(fakeRepo.Owner) - g.Assert(repo.Name).Equal(fakeRepo.Name) - g.Assert(repo.FullName).Equal(fakeRepo.FullName) - g.Assert(repo.IsSCMPrivate).IsTrue() - g.Assert(repo.Clone).Equal(fakeRepo.Clone) - g.Assert(repo.ForgeURL).Equal(fakeRepo.ForgeURL) - }) - g.It("Should handle a not found error", func() { - _, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name) - g.Assert(err).IsNotNil() - }) - }) - - g.It("Should return a user repository list") - - g.It("Should return a user team list") - - g.It("Should register repository hooks") - - g.It("Should return a repository file") - - g.Describe("Given an authentication request", func() { - g.It("Should redirect to the GitHub login page") - g.It("Should create an access token") - g.It("Should handle an access token error") - g.It("Should return the authenticated user") - g.It("Should handle authentication errors") - }) + t.Run("Should return the repository details", func(t *testing.T) { + repo, err := c.Repo(ctx, fakeUser, fakeRepo.ForgeRemoteID, fakeRepo.Owner, fakeRepo.Name) + assert.NoError(t, err) + assert.Equal(t, fakeRepo.ForgeRemoteID, repo.ForgeRemoteID) + assert.Equal(t, fakeRepo.Owner, repo.Owner) + assert.Equal(t, fakeRepo.Name, repo.Name) + assert.Equal(t, fakeRepo.FullName, repo.FullName) + assert.True(t, repo.IsSCMPrivate) + assert.Equal(t, fakeRepo.Clone, repo.Clone) + assert.Equal(t, fakeRepo.ForgeURL, repo.ForgeURL) + }) + t.Run("repo not found error", func(t *testing.T) { + _, err := c.Repo(ctx, fakeUser, "0", fakeRepoNotFound.Owner, fakeRepoNotFound.Name) + assert.Error(t, err) }) } diff --git a/server/forge/github/parse_test.go b/server/forge/github/parse_test.go index c316dd9ab..a48f0ff5a 100644 --- a/server/forge/github/parse_test.go +++ b/server/forge/github/parse_test.go @@ -22,7 +22,6 @@ import ( "strings" "testing" - "github.com/franela/goblin" "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/forge/github/fixtures" @@ -46,96 +45,85 @@ func testHookRequest(payload []byte, event string) *http.Request { return req } -func Test_parser(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("GitHub parser", func() { - g.It("should ignore unsupported hook events", func() { - req := testHookRequest([]byte(fixtures.HookPullRequest), "issues") - p, r, b, err := parseHook(req, false) - g.Assert(r).IsNil() - g.Assert(b).IsNil() - g.Assert(p).IsNil() - assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) - }) +func Test_parseHook(t *testing.T) { + t.Run("ignore unsupported hook events", func(t *testing.T) { + req := testHookRequest([]byte(fixtures.HookPullRequest), "issues") + p, r, b, err := parseHook(req, false) + assert.Nil(t, r) + assert.Nil(t, b) + assert.Nil(t, p) + assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) + }) - g.Describe("given a push hook", func() { - g.It("should skip when action is deleted", func() { - req := testHookRequest([]byte(fixtures.HookPushDeleted), hookPush) - p, r, b, err := parseHook(req, false) - g.Assert(r).IsNil() - g.Assert(b).IsNil() - g.Assert(err).IsNil() - g.Assert(p).IsNil() - }) - g.It("should extract repository and pipeline details", func() { - req := testHookRequest([]byte(fixtures.HookPush), hookPush) - p, r, b, err := parseHook(req, false) - g.Assert(err).IsNil() - g.Assert(p).IsNil() - g.Assert(r).IsNotNil() - g.Assert(b).IsNotNil() - g.Assert(b.Event).Equal(model.EventPush) - sort.Strings(b.ChangedFiles) - g.Assert(b.ChangedFiles).Equal([]string{"pipeline/shared/replace_secrets.go", "pipeline/shared/replace_secrets_test.go"}) - }) - }) + t.Run("skip skip push hook when action is deleted", func(t *testing.T) { + req := testHookRequest([]byte(fixtures.HookPushDeleted), hookPush) + p, r, b, err := parseHook(req, false) + assert.Nil(t, r) + assert.Nil(t, b) + assert.NoError(t, err) + assert.Nil(t, p) + }) + t.Run("push hook", func(t *testing.T) { + req := testHookRequest([]byte(fixtures.HookPush), hookPush) + p, r, b, err := parseHook(req, false) + assert.NoError(t, err) + assert.Nil(t, p) + assert.NotNil(t, r) + assert.NotNil(t, b) + assert.Equal(t, model.EventPush, b.Event) + sort.Strings(b.ChangedFiles) + assert.Equal(t, []string{"pipeline/shared/replace_secrets.go", "pipeline/shared/replace_secrets_test.go"}, b.ChangedFiles) + }) - g.Describe("given a pull request hook", func() { - g.It("should handle a PR hook when PR got opened or pushed to", func() { - req := testHookRequest([]byte(fixtures.HookPullRequest), hookPull) - p, r, b, err := parseHook(req, false) - g.Assert(err).IsNil() - g.Assert(r).IsNotNil() - g.Assert(b).IsNotNil() - g.Assert(p).IsNotNil() - g.Assert(b.Event).Equal(model.EventPull) - }) - g.It("should handle a PR closed hook when PR got closed", func() { - req := testHookRequest([]byte(fixtures.HookPullRequestClosed), hookPull) - p, r, b, err := parseHook(req, false) - g.Assert(err).IsNil() - g.Assert(r).IsNotNil() - g.Assert(b).IsNotNil() - g.Assert(p).IsNotNil() - g.Assert(b.Event).Equal(model.EventPullClosed) - }) - g.It("should handle a PR closed hook when PR got merged", func() { - req := testHookRequest([]byte(fixtures.HookPullRequestMerged), hookPull) - p, r, b, err := parseHook(req, false) - g.Assert(err).IsNil() - g.Assert(r).IsNotNil() - g.Assert(b).IsNotNil() - g.Assert(p).IsNotNil() - g.Assert(b.Event).Equal(model.EventPullClosed) - }) - }) + t.Run("PR hook", func(t *testing.T) { + req := testHookRequest([]byte(fixtures.HookPullRequest), hookPull) + p, r, b, err := parseHook(req, false) + assert.NoError(t, err) + assert.NotNil(t, r) + assert.NotNil(t, b) + assert.NotNil(t, p) + assert.Equal(t, model.EventPull, b.Event) + }) + t.Run("PR closed hook", func(t *testing.T) { + req := testHookRequest([]byte(fixtures.HookPullRequestClosed), hookPull) + p, r, b, err := parseHook(req, false) + assert.NoError(t, err) + assert.NotNil(t, r) + assert.NotNil(t, b) + assert.NotNil(t, p) + assert.Equal(t, model.EventPullClosed, b.Event) + }) + t.Run("PR merged hook", func(t *testing.T) { + req := testHookRequest([]byte(fixtures.HookPullRequestMerged), hookPull) + p, r, b, err := parseHook(req, false) + assert.NoError(t, err) + assert.NotNil(t, r) + assert.NotNil(t, b) + assert.NotNil(t, p) + assert.Equal(t, model.EventPullClosed, b.Event) + }) - g.Describe("given a deployment hook", func() { - g.It("should extract repository and pipeline details", func() { - req := testHookRequest([]byte(fixtures.HookDeploy), hookDeploy) - p, r, b, err := parseHook(req, false) - g.Assert(err).IsNil() - g.Assert(r).IsNotNil() - g.Assert(b).IsNotNil() - g.Assert(p).IsNil() - g.Assert(b.Event).Equal(model.EventDeploy) - g.Assert(b.DeployTo).Equal("production") - g.Assert(b.DeployTask).Equal("deploy") - }) - }) + t.Run("deploy hook", func(t *testing.T) { + req := testHookRequest([]byte(fixtures.HookDeploy), hookDeploy) + p, r, b, err := parseHook(req, false) + assert.NoError(t, err) + assert.NotNil(t, r) + assert.NotNil(t, b) + assert.Nil(t, p) + assert.Equal(t, model.EventDeploy, b.Event) + assert.Equal(t, "production", b.DeployTo) + assert.Equal(t, "deploy", b.DeployTask) + }) - g.Describe("given a release hook", func() { - g.It("should extract repository and build details", func() { - req := testHookRequest([]byte(fixtures.HookRelease), hookRelease) - p, r, b, err := parseHook(req, false) - g.Assert(err).IsNil() - g.Assert(r).IsNotNil() - g.Assert(b).IsNotNil() - g.Assert(p).IsNil() - g.Assert(b.Event).Equal(model.EventRelease) - g.Assert(len(strings.Split(b.Ref, "/")) == 3).IsTrue() - g.Assert(strings.HasPrefix(b.Ref, "refs/tags/")).IsTrue() - }) - }) + t.Run("release hook", func(t *testing.T) { + req := testHookRequest([]byte(fixtures.HookRelease), hookRelease) + p, r, b, err := parseHook(req, false) + assert.NoError(t, err) + assert.NotNil(t, r) + assert.NotNil(t, b) + assert.Nil(t, p) + assert.Equal(t, model.EventRelease, b.Event) + assert.Len(t, strings.Split(b.Ref, "/"), 3) + assert.True(t, strings.HasPrefix(b.Ref, "refs/tags/")) }) } diff --git a/server/forge/gitlab/gitlab_test.go b/server/forge/gitlab/gitlab_test.go index 04619acaf..876696ca7 100644 --- a/server/forge/gitlab/gitlab_test.go +++ b/server/forge/gitlab/gitlab_test.go @@ -23,7 +23,6 @@ import ( "strconv" "testing" - "github.com/franela/goblin" "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/forge/gitlab/testdata" @@ -70,234 +69,214 @@ func Test_GitLab(t *testing.T) { } ctx := context.Background() - g := goblin.Goblin(t) - g.Describe("GitLab Plugin", func() { - // Test projects method - g.Describe("AllProjects", func() { - g.It("Should return only non-archived projects is hidden", func() { - client.HideArchives = true - _projects, err := client.Repos(ctx, &user) - assert.NoError(t, err) - assert.Len(t, _projects, 1) - }) + // Test projects method + t.Run("Should return only non-archived projects is hidden", func(t *testing.T) { + client.HideArchives = true + _projects, err := client.Repos(ctx, &user) + assert.NoError(t, err) + assert.Len(t, _projects, 1) + }) - g.It("Should return all the projects", func() { - client.HideArchives = false - _projects, err := client.Repos(ctx, &user) + t.Run("Should return all the projects", func(t *testing.T) { + client.HideArchives = false + _projects, err := client.Repos(ctx, &user) - g.Assert(err).IsNil() - g.Assert(len(_projects)).Equal(2) - }) - }) + assert.NoError(t, err) + assert.Len(t, _projects, 2) + }) - // Test repository method - g.Describe("Repo", func() { - g.It("Should return valid repo", func() { - _repo, err := client.Repo(ctx, &user, "0", "diaspora", "diaspora-client") - assert.NoError(t, err) - assert.Equal(t, "diaspora-client", _repo.Name) - assert.Equal(t, "diaspora", _repo.Owner) - assert.True(t, _repo.IsSCMPrivate) - }) + // Test repository method + t.Run("Should return valid repo", func(t *testing.T) { + _repo, err := client.Repo(ctx, &user, "0", "diaspora", "diaspora-client") + assert.NoError(t, err) + assert.Equal(t, "diaspora-client", _repo.Name) + assert.Equal(t, "diaspora", _repo.Owner) + assert.True(t, _repo.IsSCMPrivate) + }) - g.It("Should return error, when repo not exist", func() { - _, err := client.Repo(ctx, &user, "0", "not-existed", "not-existed") - assert.Error(t, err) - }) + t.Run("Should return error, when repo not exist", func(t *testing.T) { + _, err := client.Repo(ctx, &user, "0", "not-existed", "not-existed") + assert.Error(t, err) + }) - g.It("Should return repo with push access, when user inherits membership from namespace", func() { - _repo, err := client.Repo(ctx, &user, "6", "brightbox", "puppet") - assert.NoError(t, err) - assert.True(t, _repo.Perm.Push) - }) - }) + t.Run("Should return repo with push access, when user inherits membership from namespace", func(t *testing.T) { + _repo, err := client.Repo(ctx, &user, "6", "brightbox", "puppet") + assert.NoError(t, err) + assert.True(t, _repo.Perm.Push) + }) - // Test activate method - g.Describe("Activate", func() { - g.It("Should be success", func() { - err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token") - assert.NoError(t, err) - }) + // Test activate method + t.Run("Activate, success", func(t *testing.T) { + err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token") + assert.NoError(t, err) + }) - g.It("Should be failed, when token not given", func() { - err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook") + t.Run("Activate, failed no token", func(t *testing.T) { + err := client.Activate(ctx, &user, &repo, "http://example.com/api/hook") - g.Assert(err).IsNotNil() - }) - }) + assert.Error(t, err) + }) - // Test deactivate method - g.Describe("Deactivate", func() { - g.It("Should be success", func() { - err := client.Deactivate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token") + // Test deactivate method + t.Run("Deactivate", func(t *testing.T) { + err := client.Deactivate(ctx, &user, &repo, "http://example.com/api/hook?access_token=token") + assert.NoError(t, err) + }) - g.Assert(err).IsNil() - }) - }) + // Test hook method + t.Run("parse push hook", func(t *testing.T) { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.HookPush), + ) + req.Header = testdata.ServiceHookHeaders - // Test hook method - g.Describe("Hook", func() { - g.Describe("Push hook", func() { - g.It("Should parse actual push hook", func() { - req, _ := http.NewRequest( - testdata.ServiceHookMethod, - testdata.ServiceHookURL.String(), - bytes.NewReader(testdata.HookPush), - ) - req.Header = testdata.ServiceHookHeaders + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.NoError(t, err) + if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { + assert.Equal(t, pipeline.Event, model.EventPush) + assert.Equal(t, "test", hookRepo.Owner) + assert.Equal(t, "woodpecker", hookRepo.Name) + assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar) + assert.Equal(t, "develop", hookRepo.Branch) + assert.Equal(t, "refs/heads/main", pipeline.Ref) + assert.Equal(t, []string{"cmd/cli/main.go"}, pipeline.ChangedFiles) + assert.Equal(t, model.EventPush, pipeline.Event) + } + }) - hookRepo, pipeline, err := client.Hook(ctx, req) - assert.NoError(t, err) - if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { - assert.Equal(t, pipeline.Event, model.EventPush) - assert.Equal(t, "test", hookRepo.Owner) - assert.Equal(t, "woodpecker", hookRepo.Name) - assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar) - assert.Equal(t, "develop", hookRepo.Branch) - assert.Equal(t, "refs/heads/main", pipeline.Ref) - assert.Equal(t, []string{"cmd/cli/main.go"}, pipeline.ChangedFiles) - assert.Equal(t, model.EventPush, pipeline.Event) - } - }) - }) + t.Run("tag push hook", func(t *testing.T) { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.HookTag), + ) + req.Header = testdata.ServiceHookHeaders - g.Describe("Tag push hook", func() { - g.It("Should parse tag push hook", func() { - req, _ := http.NewRequest( - testdata.ServiceHookMethod, - testdata.ServiceHookURL.String(), - bytes.NewReader(testdata.HookTag), - ) - req.Header = testdata.ServiceHookHeaders + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.NoError(t, err) + if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { + assert.Equal(t, "test", hookRepo.Owner) + assert.Equal(t, "woodpecker", hookRepo.Name) + assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar) + assert.Equal(t, "develop", hookRepo.Branch) + assert.Equal(t, "refs/tags/v22", pipeline.Ref) + assert.Len(t, pipeline.ChangedFiles, 0) + assert.Equal(t, model.EventTag, pipeline.Event) + } + }) - hookRepo, pipeline, err := client.Hook(ctx, req) - assert.NoError(t, err) - if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { - assert.Equal(t, "test", hookRepo.Owner) - assert.Equal(t, "woodpecker", hookRepo.Name) - assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar) - assert.Equal(t, "develop", hookRepo.Branch) - assert.Equal(t, "refs/tags/v22", pipeline.Ref) - assert.Len(t, pipeline.ChangedFiles, 0) - assert.Equal(t, model.EventTag, pipeline.Event) - } - }) - }) + t.Run("merge request hook", func(t *testing.T) { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.HookPullRequest), + ) + req.Header = testdata.ServiceHookHeaders - g.Describe("Merge request hook", func() { - g.It("Should parse merge request hook", func() { - req, _ := http.NewRequest( - testdata.ServiceHookMethod, - testdata.ServiceHookURL.String(), - bytes.NewReader(testdata.HookPullRequest), - ) - req.Header = testdata.ServiceHookHeaders + // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.NoError(t, err) + if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { + assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar) + assert.Equal(t, "main", hookRepo.Branch) + assert.Equal(t, "anbraten", hookRepo.Owner) + assert.Equal(t, "woodpecker", hookRepo.Name) + assert.Equal(t, "Update client.go 🎉", pipeline.Title) + assert.Len(t, pipeline.ChangedFiles, 0) // see L217 + assert.Equal(t, model.EventPull, pipeline.Event) + } + }) - // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles - hookRepo, pipeline, err := client.Hook(ctx, req) - assert.NoError(t, err) - if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { - assert.Equal(t, "http://example.com/uploads/project/avatar/555/Outh-20-Logo.jpg", hookRepo.Avatar) - assert.Equal(t, "main", hookRepo.Branch) - assert.Equal(t, "anbraten", hookRepo.Owner) - assert.Equal(t, "woodpecker", hookRepo.Name) - assert.Equal(t, "Update client.go 🎉", pipeline.Title) - assert.Len(t, pipeline.ChangedFiles, 0) // see L217 - assert.Equal(t, model.EventPull, pipeline.Event) - } - }) + t.Run("ignore merge request hook without changes", func(t *testing.T) { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.HookPullRequestWithoutChanges), + ) + req.Header = testdata.ServiceHookHeaders - g.It("Should ignore merge request hook without changes", func() { - req, _ := http.NewRequest( - testdata.ServiceHookMethod, - testdata.ServiceHookURL.String(), - bytes.NewReader(testdata.HookPullRequestWithoutChanges), - ) - req.Header = testdata.ServiceHookHeaders + // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.Nil(t, hookRepo) + assert.Nil(t, pipeline) + assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) + }) - // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles - hookRepo, pipeline, err := client.Hook(ctx, req) - assert.Nil(t, hookRepo) - assert.Nil(t, pipeline) - assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) - }) + t.Run("ignore merge request approval", func(t *testing.T) { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.HookPullRequestApproved), + ) + req.Header = testdata.ServiceHookHeaders - g.It("Should ignore merge request approval", func() { - req, _ := http.NewRequest( - testdata.ServiceHookMethod, - testdata.ServiceHookURL.String(), - bytes.NewReader(testdata.HookPullRequestApproved), - ) - req.Header = testdata.ServiceHookHeaders + // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.Nil(t, hookRepo) + assert.Nil(t, pipeline) + assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) + }) - // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles - hookRepo, pipeline, err := client.Hook(ctx, req) - assert.Nil(t, hookRepo) - assert.Nil(t, pipeline) - assert.ErrorIs(t, err, &types.ErrIgnoreEvent{}) - }) + t.Run("parse merge request closed", func(t *testing.T) { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.HookPullRequestClosed), + ) + req.Header = testdata.ServiceHookHeaders - g.It("Should parse merge request hook when MR closed", func() { - req, _ := http.NewRequest( - testdata.ServiceHookMethod, - testdata.ServiceHookURL.String(), - bytes.NewReader(testdata.HookPullRequestClosed), - ) - req.Header = testdata.ServiceHookHeaders + // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.NoError(t, err) + if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { + assert.Equal(t, "main", hookRepo.Branch) + assert.Equal(t, "anbraten", hookRepo.Owner) + assert.Equal(t, "woodpecker-test", hookRepo.Name) + assert.Equal(t, "Add new file", pipeline.Title) + assert.Len(t, pipeline.ChangedFiles, 0) // see L217 + assert.Equal(t, model.EventPullClosed, pipeline.Event) + } + }) - // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles - hookRepo, pipeline, err := client.Hook(ctx, req) - assert.NoError(t, err) - if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { - assert.Equal(t, "main", hookRepo.Branch) - assert.Equal(t, "anbraten", hookRepo.Owner) - assert.Equal(t, "woodpecker-test", hookRepo.Name) - assert.Equal(t, "Add new file", pipeline.Title) - assert.Len(t, pipeline.ChangedFiles, 0) // see L217 - assert.Equal(t, model.EventPullClosed, pipeline.Event) - } - }) + t.Run("parse merge request merged", func(t *testing.T) { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.HookPullRequestMerged), + ) + req.Header = testdata.ServiceHookHeaders - g.It("Should parse merge request hook when merged", func() { - req, _ := http.NewRequest( - testdata.ServiceHookMethod, - testdata.ServiceHookURL.String(), - bytes.NewReader(testdata.HookPullRequestMerged), - ) - req.Header = testdata.ServiceHookHeaders + // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.NoError(t, err) + if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { + assert.Equal(t, "main", hookRepo.Branch) + assert.Equal(t, "anbraten", hookRepo.Owner) + assert.Equal(t, "woodpecker-test", hookRepo.Name) + assert.Equal(t, "Add new file", pipeline.Title) + assert.Len(t, pipeline.ChangedFiles, 0) // see L217 + assert.Equal(t, model.EventPullClosed, pipeline.Event) + } + }) - // TODO: insert fake store into context to retrieve user & repo, this will activate fetching of ChangedFiles - hookRepo, pipeline, err := client.Hook(ctx, req) - assert.NoError(t, err) - if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { - assert.Equal(t, "main", hookRepo.Branch) - assert.Equal(t, "anbraten", hookRepo.Owner) - assert.Equal(t, "woodpecker-test", hookRepo.Name) - assert.Equal(t, "Add new file", pipeline.Title) - assert.Len(t, pipeline.ChangedFiles, 0) // see L217 - assert.Equal(t, model.EventPullClosed, pipeline.Event) - } - }) + t.Run("release hook", func(t *testing.T) { + req, _ := http.NewRequest( + testdata.ServiceHookMethod, + testdata.ServiceHookURL.String(), + bytes.NewReader(testdata.WebhookReleaseBody), + ) + req.Header = testdata.ReleaseHookHeaders - g.It("Should parse release request hook", func() { - req, _ := http.NewRequest( - testdata.ServiceHookMethod, - testdata.ServiceHookURL.String(), - bytes.NewReader(testdata.WebhookReleaseBody), - ) - req.Header = testdata.ReleaseHookHeaders - - hookRepo, pipeline, err := client.Hook(ctx, req) - assert.NoError(t, err) - if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { - assert.Equal(t, "refs/tags/0.0.2", pipeline.Ref) - assert.Equal(t, "ci", hookRepo.Name) - assert.Equal(t, "created release Awesome version 0.0.2", pipeline.Message) - assert.Equal(t, model.EventRelease, pipeline.Event) - } - }) - }) - }) + hookRepo, pipeline, err := client.Hook(ctx, req) + assert.NoError(t, err) + if assert.NotNil(t, hookRepo) && assert.NotNil(t, pipeline) { + assert.Equal(t, "refs/tags/0.0.2", pipeline.Ref) + assert.Equal(t, "ci", hookRepo.Name) + assert.Equal(t, "created release Awesome version 0.0.2", pipeline.Message) + assert.Equal(t, model.EventRelease, pipeline.Event) + } }) } diff --git a/server/grpc/rpc_test.go b/server/grpc/rpc_test.go index 7b071cf1b..798c39e35 100644 --- a/server/grpc/rpc_test.go +++ b/server/grpc/rpc_test.go @@ -19,7 +19,6 @@ import ( "testing" "time" - "github.com/franela/goblin" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "google.golang.org/grpc/metadata" @@ -30,92 +29,87 @@ import ( ) func TestRegisterAgent(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("When existing agent Name is empty", func() { - g.It("Should update Name with hostname from metadata", func() { - store := mocks_store.NewStore(t) - storeAgent := new(model.Agent) - storeAgent.ID = 1337 - updatedAgent := model.Agent{ - ID: 1337, - Created: 0, - Updated: 0, - Name: "hostname", - OwnerID: 0, - Token: "", - LastContact: 0, - Platform: "platform", - Backend: "backend", - Capacity: 2, - Version: "version", - NoSchedule: false, - } + t.Run("When existing agent Name is empty it should update Name with hostname from metadata", func(t *testing.T) { + store := mocks_store.NewStore(t) + storeAgent := new(model.Agent) + storeAgent.ID = 1337 + updatedAgent := model.Agent{ + ID: 1337, + Created: 0, + Updated: 0, + Name: "hostname", + OwnerID: 0, + Token: "", + LastContact: 0, + Platform: "platform", + Backend: "backend", + Capacity: 2, + Version: "version", + NoSchedule: false, + } - store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil) - store.On("AgentUpdate", &updatedAgent).Once().Return(nil) - grpc := RPC{ - store: store, - } - ctx := metadata.NewIncomingContext( - context.Background(), - metadata.Pairs("hostname", "hostname", "agent_id", "1337"), - ) - agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{ - Version: "version", - Platform: "platform", - Backend: "backend", - Capacity: 2, - }) - if !assert.NoError(t, err) { - return - } - - assert.EqualValues(t, 1337, agentID) + store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil) + store.On("AgentUpdate", &updatedAgent).Once().Return(nil) + grpc := RPC{ + store: store, + } + ctx := metadata.NewIncomingContext( + context.Background(), + metadata.Pairs("hostname", "hostname", "agent_id", "1337"), + ) + agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{ + Version: "version", + Platform: "platform", + Backend: "backend", + Capacity: 2, }) + if !assert.NoError(t, err) { + return + } + + assert.EqualValues(t, 1337, agentID) }) - g.Describe("When existing agent hostname is present", func() { - g.It("Should not update the hostname", func() { - store := mocks_store.NewStore(t) - storeAgent := new(model.Agent) - storeAgent.ID = 1337 - storeAgent.Name = "originalHostname" - updatedAgent := model.Agent{ - ID: 1337, - Created: 0, - Updated: 0, - Name: "originalHostname", - OwnerID: 0, - Token: "", - LastContact: 0, - Platform: "platform", - Backend: "backend", - Capacity: 2, - Version: "version", - NoSchedule: false, - } + t.Run("When existing agent hostname is present it should not update the hostname", func(t *testing.T) { + store := mocks_store.NewStore(t) + storeAgent := new(model.Agent) + storeAgent.ID = 1337 + storeAgent.Name = "originalHostname" + updatedAgent := model.Agent{ + ID: 1337, + Created: 0, + Updated: 0, + Name: "originalHostname", + OwnerID: 0, + Token: "", + LastContact: 0, + Platform: "platform", + Backend: "backend", + Capacity: 2, + Version: "version", + NoSchedule: false, + } - store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil) - store.On("AgentUpdate", &updatedAgent).Once().Return(nil) - grpc := RPC{ - store: store, - } - ctx := metadata.NewIncomingContext( - context.Background(), - metadata.Pairs("hostname", "newHostname", "agent_id", "1337"), - ) - agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{ - Version: "version", - Platform: "platform", - Backend: "backend", - Capacity: 2, - }) - if !assert.NoError(t, err) { - return - } - - assert.EqualValues(t, 1337, agentID) + store.On("AgentFind", int64(1337)).Once().Return(storeAgent, nil) + store.On("AgentUpdate", &updatedAgent).Once().Return(nil) + grpc := RPC{ + store: store, + } + ctx := metadata.NewIncomingContext( + context.Background(), + metadata.Pairs("hostname", "newHostname", "agent_id", "1337"), + ) + agentID, err := grpc.RegisterAgent(ctx, rpc.AgentInfo{ + Version: "version", + Platform: "platform", + Backend: "backend", + Capacity: 2, }) + if !assert.NoError(t, err) { + return + } + + assert.EqualValues(t, 1337, agentID) }) } diff --git a/server/model/secret_test.go b/server/model/secret_test.go index 915b432b0..d1195f16b 100644 --- a/server/model/secret_test.go +++ b/server/model/secret_test.go @@ -17,90 +17,90 @@ package model import ( "testing" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" ) func TestSecretValidate(t *testing.T) { - g := goblin.Goblin(t) - g.Describe("Secret", func() { - g.It("should pass validation", func() { - secret := Secret{ + tests := []struct { + s Secret + err bool + }{ + { + s: Secret{ Name: "secretname", Value: "secretvalue", Events: []WebhookEvent{EventPush}, Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, - } - err := secret.Validate() - g.Assert(err).IsNil() - }) - g.Describe("should fail validation", func() { - g.It("when no name", func() { - secret := Secret{ - Value: "secretvalue", - Events: []WebhookEvent{EventPush}, - Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, - } - err := secret.Validate() - g.Assert(err).IsNotNil() - }) - g.It("when no value", func() { - secret := Secret{ - Name: "secretname", - Events: []WebhookEvent{EventPush}, - Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, - } - err := secret.Validate() - g.Assert(err).IsNotNil() - }) - g.It("when no events", func() { - secret := Secret{ - Name: "secretname", - Value: "secretvalue", - Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, - } - err := secret.Validate() - g.Assert(err).IsNotNil() - }) - g.It("wrong image: no value", func() { - secret := Secret{ - Name: "secretname", - Value: "secretvalue", - Events: []WebhookEvent{EventPush}, - Images: []string{"wrong image:no"}, - } - err := secret.Validate() - g.Assert(err).IsNotNil() - }) - g.It("wrong image: no hostname", func() { - secret := Secret{ - Name: "secretname", - Value: "secretvalue", - Events: []WebhookEvent{EventPush}, - Images: []string{"/library/mysql:latest", ":8443/mysql:latest", ":8443/library/mysql:latest", "/library/mysql", ":8443/mysql", ":8443/library/mysql"}, - } - err := secret.Validate() - g.Assert(err).IsNotNil() - }) - g.It("wrong image: no port number", func() { - secret := Secret{ - Name: "secretname", - Value: "secretvalue", - Events: []WebhookEvent{EventPush}, - Images: []string{"localregistry.test:/mysql:latest", "localregistry.test:/mysql"}, - } - err := secret.Validate() - g.Assert(err).IsNotNil() - }) - g.It("wrong image: no tag name", func() { - secret := Secret{ - Name: "secretname", - Value: "secretvalue", - Events: []WebhookEvent{EventPush}, - Images: []string{"docker.io/library/mysql:", "alpine:", "localregistry.test:8443/mysql:", "localregistry.test:8443/library/mysql:"}, - } - err := secret.Validate() - g.Assert(err).IsNotNil() - }) - }) - }) + }, + err: false, + }, + { + s: Secret{ + Value: "secretvalue", + Events: []WebhookEvent{EventPush}, + Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, + }, + err: true, + }, + { + s: Secret{ + Name: "secretname", + Events: []WebhookEvent{EventPush}, + Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, + }, + err: true, + }, + { + s: Secret{ + Name: "secretname", + Value: "secretvalue", + Images: []string{"docker.io/library/mysql:latest", "alpine:latest", "localregistry.test:8443/mysql:latest", "localregistry.test:8443/library/mysql:latest", "docker.io/library/mysql", "alpine", "localregistry.test:8443/mysql", "localregistry.test:8443/library/mysql"}, + }, + err: true, + }, + { + s: Secret{ + Name: "secretname", + Value: "secretvalue", + Events: []WebhookEvent{EventPush}, + Images: []string{"wrong image:no"}, + }, + err: true, + }, + { + s: Secret{ + Name: "secretname", + Value: "secretvalue", + Events: []WebhookEvent{EventPush}, + Images: []string{"/library/mysql:latest", ":8443/mysql:latest", ":8443/library/mysql:latest", "/library/mysql", ":8443/mysql", ":8443/library/mysql"}, + }, + err: true, + }, + { + s: Secret{ + Name: "secretname", + Value: "secretvalue", + Events: []WebhookEvent{EventPush}, + Images: []string{"localregistry.test:/mysql:latest", "localregistry.test:/mysql"}, + }, + err: true, + }, + { + s: Secret{ + Name: "secretname", + Value: "secretvalue", + Events: []WebhookEvent{EventPush}, + Images: []string{"docker.io/library/mysql:", "alpine:", "localregistry.test:8443/mysql:", "localregistry.test:8443/library/mysql:"}, + }, + err: true, + }, + } + for i, tt := range tests { + err := tt.s.Validate() + if tt.err { + assert.Errorf(t, err, "expected secret validation error on index %d", i) + } else { + assert.NoErrorf(t, err, "unexpected secret validation error on index %d", i) + } + } } diff --git a/server/services/secret/db_test.go b/server/services/secret/db_test.go index 08e1a5f16..c966a7f9b 100644 --- a/server/services/secret/db_test.go +++ b/server/services/secret/db_test.go @@ -17,7 +17,7 @@ package secret_test import ( "testing" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "go.woodpecker-ci.org/woodpecker/v3/server/model" @@ -25,12 +25,8 @@ import ( mocks_store "go.woodpecker-ci.org/woodpecker/v3/server/store/mocks" ) -func TestSecretListPipeline(t *testing.T) { - g := goblin.Goblin(t) - mockStore := mocks_store.NewStore(t) - - // global secret - globalSecret := &model.Secret{ +var ( + globalSecret = &model.Secret{ ID: 1, OrgID: 0, RepoID: 0, @@ -38,8 +34,7 @@ func TestSecretListPipeline(t *testing.T) { Value: "value-global", } - // org secret - orgSecret := &model.Secret{ + orgSecret = &model.Secret{ ID: 2, OrgID: 1, RepoID: 0, @@ -47,53 +42,48 @@ func TestSecretListPipeline(t *testing.T) { Value: "value-org", } - // repo secret - repoSecret := &model.Secret{ + repoSecret = &model.Secret{ ID: 3, OrgID: 0, RepoID: 1, Name: "secret", Value: "value-repo", } +) - g.Describe("Priority of secrets", func() { - g.It("should get the repo secret", func() { - mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{ - globalSecret, - orgSecret, - repoSecret, - }, nil) +func TestSecretListPipeline(t *testing.T) { + mockStore := mocks_store.NewStore(t) - s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{}) - g.Assert(err).IsNil() + mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{ + globalSecret, + orgSecret, + repoSecret, + }, nil) - g.Assert(len(s)).Equal(1) - g.Assert(s[0].Value).Equal("value-repo") - }) + s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{}) + assert.NoError(t, err) - g.It("should get the org secret", func() { - mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{ - globalSecret, - orgSecret, - }, nil) + assert.Len(t, s, 1) + assert.Equal(t, "value-repo", s[0].Value) - s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{}) - g.Assert(err).IsNil() + mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{ + globalSecret, + orgSecret, + }, nil) - g.Assert(len(s)).Equal(1) - g.Assert(s[0].Value).Equal("value-org") - }) + s, err = secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{}) + assert.NoError(t, err) - g.It("should get the global secret", func() { - mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{ - globalSecret, - }, nil) + assert.Len(t, s, 1) + assert.Equal(t, "value-org", s[0].Value) - s, err := secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{}) - g.Assert(err).IsNil() + mockStore.On("SecretList", mock.Anything, mock.Anything, mock.Anything).Once().Return([]*model.Secret{ + globalSecret, + }, nil) - g.Assert(len(s)).Equal(1) - g.Assert(s[0].Value).Equal("value-global") - }) - }) + s, err = secret.NewDB(mockStore).SecretListPipeline(&model.Repo{}, &model.Pipeline{}) + assert.NoError(t, err) + + assert.Len(t, s, 1) + assert.Equal(t, "value-global", s[0].Value) } diff --git a/server/store/datastore/pipeline_test.go b/server/store/datastore/pipeline_test.go index c4a81c632..fed95149b 100644 --- a/server/store/datastore/pipeline_test.go +++ b/server/store/datastore/pipeline_test.go @@ -16,11 +16,9 @@ package datastore import ( - "fmt" "testing" "time" - "github.com/franela/goblin" "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/model" @@ -38,275 +36,170 @@ func TestPipelines(t *testing.T) { store, closer := newTestStore(t, new(model.Repo), new(model.Step), new(model.Pipeline)) defer closer() - g := goblin.Goblin(t) - g.Describe("Pipelines", func() { - g.Before(func() { - _, err := store.engine.Exec("DELETE FROM repos") - g.Assert(err).IsNil() - g.Assert(store.CreateRepo(repo)).IsNil() - }) - g.After(func() { - _, err := store.engine.Exec("DELETE FROM repos") - g.Assert(err).IsNil() - }) + assert.NoError(t, store.CreateRepo(repo)) - // before each test be sure to purge the package - // table data from the database. - g.BeforeEach(func() { - _, err := store.engine.Exec("DELETE FROM pipelines") - g.Assert(err).IsNil() - _, err = store.engine.Exec("DELETE FROM steps") - g.Assert(err).IsNil() - }) + // Fail when the repo is not existing + pipeline := model.Pipeline{ + RepoID: 100, + Status: model.StatusSuccess, + } + err := store.CreatePipeline(&pipeline) + assert.Error(t, err) - g.It("Should Fail early when the repo is not existing", func() { - pipeline := model.Pipeline{ - RepoID: 100, - Status: model.StatusSuccess, - } - err := store.CreatePipeline(&pipeline) - g.Assert(err).IsNotNil() + count, err := store.GetPipelineCount() + assert.NoError(t, err) + assert.Zero(t, count) - count, err := store.GetPipelineCount() - g.Assert(err).IsNil() - g.Assert(count == 0).IsTrue() - fmt.Println("GOT COUNT", count) - }) + // add pipeline + pipeline = model.Pipeline{ + RepoID: repo.ID, + Status: model.StatusSuccess, + Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", + Branch: "some-branch", + } + err = store.CreatePipeline(&pipeline) + assert.NoError(t, err) + assert.NotZero(t, pipeline.ID) + assert.EqualValues(t, 1, pipeline.Number) + assert.Equal(t, "85f8c029b902ed9400bc600bac301a0aadb144ac", pipeline.Commit) - g.It("Should Post a Pipeline", func() { - pipeline := model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusSuccess, - Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", - } - err := store.CreatePipeline(&pipeline) - g.Assert(err).IsNil() - g.Assert(pipeline.ID != 0).IsTrue() - g.Assert(pipeline.Number).Equal(int64(1)) - g.Assert(pipeline.Commit).Equal("85f8c029b902ed9400bc600bac301a0aadb144ac") + count, err = store.GetPipelineCount() + assert.NoError(t, err) + assert.NotZero(t, count) - count, err := store.GetPipelineCount() - g.Assert(err).IsNil() - g.Assert(count > 0).IsTrue() - fmt.Println("GOT COUNT", count) - }) + GetPipeline, err := store.GetPipeline(pipeline.ID) + assert.NoError(t, err) + assert.Equal(t, pipeline.ID, GetPipeline.ID) + assert.Equal(t, pipeline.RepoID, GetPipeline.RepoID) + assert.Equal(t, pipeline.Status, GetPipeline.Status) - g.It("Should Put a Pipeline", func() { - pipeline := model.Pipeline{ - RepoID: repo.ID, - Number: 5, - Status: model.StatusSuccess, - Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", - } - err := store.CreatePipeline(&pipeline) - g.Assert(err).IsNil() - pipeline.Status = model.StatusRunning - err1 := store.UpdatePipeline(&pipeline) - GetPipeline, err2 := store.GetPipeline(pipeline.ID) - g.Assert(err1).IsNil() - g.Assert(err2).IsNil() - g.Assert(pipeline.ID).Equal(GetPipeline.ID) - g.Assert(pipeline.RepoID).Equal(GetPipeline.RepoID) - g.Assert(pipeline.Status).Equal(GetPipeline.Status) - g.Assert(pipeline.Number).Equal(GetPipeline.Number) - }) + // update pipeline + pipeline.Status = model.StatusRunning + err1 := store.UpdatePipeline(&pipeline) + GetPipeline, err2 := store.GetPipeline(pipeline.ID) + assert.NoError(t, err1) + assert.NoError(t, err2) + assert.Equal(t, pipeline.ID, GetPipeline.ID) + assert.Equal(t, pipeline.RepoID, GetPipeline.RepoID) + assert.Equal(t, pipeline.Status, GetPipeline.Status) + assert.Equal(t, pipeline.Number, GetPipeline.Number) - g.It("Should Get a Pipeline", func() { - pipeline := model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusSuccess, - } - err := store.CreatePipeline(&pipeline, []*model.Step{}...) - g.Assert(err).IsNil() - GetPipeline, err := store.GetPipeline(pipeline.ID) - g.Assert(err).IsNil() - g.Assert(pipeline.ID).Equal(GetPipeline.ID) - g.Assert(pipeline.RepoID).Equal(GetPipeline.RepoID) - g.Assert(pipeline.Status).Equal(GetPipeline.Status) - }) + pipeline2 := &model.Pipeline{ + RepoID: repo.ID, + Status: model.StatusPending, + Event: model.EventPush, + Branch: "main", + } + err2 = store.CreatePipeline(pipeline2, []*model.Step{}...) + assert.NoError(t, err2) + GetPipeline, err3 := store.GetPipelineNumber(&model.Repo{ID: 1}, pipeline2.Number) + assert.NoError(t, err3) + assert.Equal(t, pipeline2.ID, GetPipeline.ID) + assert.Equal(t, pipeline2.RepoID, GetPipeline.RepoID) + assert.Equal(t, pipeline2.Number, GetPipeline.Number) - g.It("Should Get a Pipeline by Number", func() { - pipeline1 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusPending, - } - pipeline2 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusPending, - } - err1 := store.CreatePipeline(pipeline1, []*model.Step{}...) - g.Assert(err1).IsNil() - err2 := store.CreatePipeline(pipeline2, []*model.Step{}...) - g.Assert(err2).IsNil() - GetPipeline, err3 := store.GetPipelineNumber(&model.Repo{ID: 1}, pipeline2.Number) - g.Assert(err3).IsNil() - g.Assert(pipeline2.ID).Equal(GetPipeline.ID) - g.Assert(pipeline2.RepoID).Equal(GetPipeline.RepoID) - g.Assert(pipeline2.Number).Equal(GetPipeline.Number) - }) + GetPipeline, err3 = store.GetPipelineLast(&model.Repo{ID: repo.ID}, pipeline2.Branch) + assert.NoError(t, err3) + assert.Equal(t, pipeline2.ID, GetPipeline.ID) + assert.Equal(t, pipeline2.RepoID, GetPipeline.RepoID) + assert.Equal(t, pipeline2.Number, GetPipeline.Number) + assert.Equal(t, pipeline2.Status, GetPipeline.Status) - g.It("Should Get the last Pipeline", func() { - pipeline1 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusFailure, - Branch: "main", - Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", - Event: model.EventPush, - } - pipeline2 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusSuccess, - Branch: "main", - Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa", - Event: model.EventPush, - } - err1 := store.CreatePipeline(pipeline1, []*model.Step{}...) - err2 := store.CreatePipeline(pipeline2, []*model.Step{}...) - GetPipeline, err3 := store.GetPipelineLast(&model.Repo{ID: 1}, pipeline2.Branch) - g.Assert(err1).IsNil() - g.Assert(err2).IsNil() - g.Assert(err3).IsNil() - g.Assert(pipeline2.ID).Equal(GetPipeline.ID) - g.Assert(pipeline2.RepoID).Equal(GetPipeline.RepoID) - g.Assert(pipeline2.Number).Equal(GetPipeline.Number) - g.Assert(pipeline2.Status).Equal(GetPipeline.Status) - g.Assert(pipeline2.Branch).Equal(GetPipeline.Branch) - g.Assert(pipeline2.Commit).Equal(GetPipeline.Commit) - }) + pipeline3 := &model.Pipeline{ + RepoID: repo.ID, + Status: model.StatusRunning, + Branch: "main", + Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa", + } + err1 = store.CreatePipeline(pipeline3, []*model.Step{}...) + assert.NoError(t, err1) - g.It("Should Get the last Pipeline Before Pipeline N", func() { - pipeline1 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusFailure, - Branch: "main", - Commit: "85f8c029b902ed9400bc600bac301a0aadb144ac", - } - pipeline2 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusSuccess, - Branch: "main", - Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa", - } - pipeline3 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusRunning, - Branch: "main", - Commit: "85f8c029b902ed9400bc600bac301a0aadb144aa", - } - err1 := store.CreatePipeline(pipeline1, []*model.Step{}...) - g.Assert(err1).IsNil() - err2 := store.CreatePipeline(pipeline2, []*model.Step{}...) - g.Assert(err2).IsNil() - err3 := store.CreatePipeline(pipeline3, []*model.Step{}...) - g.Assert(err3).IsNil() - GetPipeline, err4 := store.GetPipelineLastBefore(&model.Repo{ID: 1}, pipeline3.Branch, pipeline3.ID) - g.Assert(err4).IsNil() - g.Assert(pipeline2.ID).Equal(GetPipeline.ID) - g.Assert(pipeline2.RepoID).Equal(GetPipeline.RepoID) - g.Assert(pipeline2.Number).Equal(GetPipeline.Number) - g.Assert(pipeline2.Status).Equal(GetPipeline.Status) - g.Assert(pipeline2.Branch).Equal(GetPipeline.Branch) - g.Assert(pipeline2.Commit).Equal(GetPipeline.Commit) - }) + GetPipeline, err4 := store.GetPipelineLastBefore(&model.Repo{ID: 1}, pipeline3.Branch, pipeline3.ID) + assert.NoError(t, err4) + assert.Equal(t, pipeline2.ID, GetPipeline.ID) + assert.Equal(t, pipeline2.RepoID, GetPipeline.RepoID) + assert.Equal(t, pipeline2.Number, GetPipeline.Number) + assert.Equal(t, pipeline2.Status, GetPipeline.Status) + assert.Equal(t, pipeline2.Branch, GetPipeline.Branch) + assert.Equal(t, pipeline2.Commit, GetPipeline.Commit) +} - g.It("Should get recent pipelines", func() { - pipeline1 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusFailure, - Event: model.EventCron, - Ref: "refs/heads/some-branch", - Branch: "some-branch", - } - pipeline2 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusSuccess, - Event: model.EventPull, - Ref: "refs/pull/32", - Branch: "main", - } - err := store.CreatePipeline(pipeline1, []*model.Step{}...) - g.Assert(err).IsNil() - err = store.CreatePipeline(pipeline2, []*model.Step{}...) - g.Assert(err).IsNil() - pipelines, err := store.GetPipelineList(&model.Repo{ID: 1}, &model.ListOptions{Page: 1, PerPage: 50}, nil) - g.Assert(err).IsNil() - g.Assert(len(pipelines)).Equal(2) - g.Assert(pipelines[0].ID).Equal(pipeline2.ID) - g.Assert(pipelines[0].RepoID).Equal(pipeline2.RepoID) - g.Assert(pipelines[0].Status).Equal(pipeline2.Status) +func TestPipelineListFilter(t *testing.T) { + repo := &model.Repo{ + UserID: 1, + FullName: "bradrydzewski/test", + Owner: "bradrydzewski", + Name: "test", + } - pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ - Branch: "main", - }) - g.Assert(err).IsNil() - g.Assert(len(pipelines)).Equal(1) - g.Assert(pipelines[0].ID).Equal(pipeline2.ID) + store, closer := newTestStore(t, new(model.Repo), new(model.Step), new(model.Pipeline)) + defer closer() - pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ - Events: []model.WebhookEvent{model.EventCron}, - }) - g.Assert(err).IsNil() - g.Assert(len(pipelines)).Equal(1) - g.Assert(pipelines[0].ID).Equal(pipeline1.ID) + assert.NoError(t, store.CreateRepo(repo)) - pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ - Events: []model.WebhookEvent{model.EventCron, model.EventPull}, - RefContains: "32", - }) - g.Assert(err).IsNil() - g.Assert(len(pipelines)).Equal(1) - g.Assert(pipelines[0].ID).Equal(pipeline2.ID) - }) + pipeline1 := &model.Pipeline{ + RepoID: repo.ID, + Status: model.StatusFailure, + Event: model.EventCron, + Ref: "refs/heads/some-branch", + Branch: "some-branch", + } + pipeline2 := &model.Pipeline{ + RepoID: repo.ID, + Status: model.StatusSuccess, + Event: model.EventPull, + Ref: "refs/pull/32", + Branch: "main", + } + err := store.CreatePipeline(pipeline1, []*model.Step{}...) + assert.NoError(t, err) + time.Sleep(1 * time.Second) + before := time.Now().Unix() + err = store.CreatePipeline(pipeline2, []*model.Step{}...) + assert.NoError(t, err) - g.It("Should get filtered pipelines", func() { - pipeline1 := &model.Pipeline{ - RepoID: repo.ID, - } - pipeline2 := &model.Pipeline{ - RepoID: repo.ID, - } - err1 := store.CreatePipeline(pipeline1, []*model.Step{}...) - g.Assert(err1).IsNil() - time.Sleep(1 * time.Second) - before := time.Now().Unix() - err2 := store.CreatePipeline(pipeline2, []*model.Step{}...) - g.Assert(err2).IsNil() - pipelines, err3 := store.GetPipelineList(&model.Repo{ID: 1}, &model.ListOptions{Page: 1, PerPage: 50}, &model.PipelineFilter{Before: before}) - g.Assert(err3).IsNil() - g.Assert(len(pipelines)).Equal(1) - g.Assert(pipelines[0].ID).Equal(pipeline1.ID) - g.Assert(pipelines[0].RepoID).Equal(pipeline1.RepoID) - }) + pipelines, err := store.GetPipelineList(&model.Repo{ID: 1}, &model.ListOptions{Page: 1, PerPage: 50}, nil) + assert.NoError(t, err) + assert.Len(t, (pipelines), 2) + assert.Equal(t, pipeline2.ID, pipelines[0].ID) + assert.Equal(t, pipeline2.RepoID, pipelines[0].RepoID) + assert.Equal(t, pipeline2.Status, pipelines[0].Status) - g.It("Should get pipelines filtered by status", func() { - pipeline1 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusSuccess, - } - pipeline2 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusFailure, - } - pipeline3 := &model.Pipeline{ - RepoID: repo.ID, - Status: model.StatusRunning, - } - err1 := store.CreatePipeline(pipeline1, []*model.Step{}...) - g.Assert(err1).IsNil() - err2 := store.CreatePipeline(pipeline2, []*model.Step{}...) - g.Assert(err2).IsNil() - err3 := store.CreatePipeline(pipeline3, []*model.Step{}...) - g.Assert(err3).IsNil() - - pipelines, err := store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ - Status: model.StatusSuccess, - }) - g.Assert(err).IsNil() - g.Assert(len(pipelines)).Equal(1) - g.Assert(pipelines[0].ID).Equal(pipeline1.ID) - g.Assert(pipelines[0].Status).Equal(model.StatusSuccess) - }) + pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ + Branch: "main", }) + assert.NoError(t, err) + assert.Len(t, pipelines, 1) + assert.Equal(t, pipeline2.ID, pipelines[0].ID) + + pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ + Events: []model.WebhookEvent{model.EventCron}, + }) + assert.NoError(t, err) + assert.Len(t, pipelines, 1) + assert.Equal(t, pipeline1.ID, pipelines[0].ID) + + pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ + Events: []model.WebhookEvent{model.EventCron, model.EventPull}, + RefContains: "32", + }) + assert.NoError(t, err) + assert.Len(t, (pipelines), 1) + assert.Equal(t, pipeline2.ID, pipelines[0].ID) + + pipelines, err3 := store.GetPipelineList(&model.Repo{ID: 1}, &model.ListOptions{Page: 1, PerPage: 50}, &model.PipelineFilter{Before: before}) + assert.NoError(t, err3) + assert.Len(t, pipelines, 1) + assert.Equal(t, pipeline1.ID, pipelines[0].ID) + assert.Equal(t, pipeline1.RepoID, pipelines[0].RepoID) + + pipelines, err = store.GetPipelineList(&model.Repo{ID: 1}, nil, &model.PipelineFilter{ + Status: model.StatusSuccess, + }) + assert.NoError(t, err) + assert.Len(t, pipelines, 1) + assert.Equal(t, pipeline2.ID, pipelines[0].ID) + assert.Equal(t, model.StatusSuccess, pipelines[0].Status) } func TestPipelineIncrement(t *testing.T) { diff --git a/server/store/datastore/repo_test.go b/server/store/datastore/repo_test.go index 90b5dfac4..97ac3723f 100644 --- a/server/store/datastore/repo_test.go +++ b/server/store/datastore/repo_test.go @@ -18,146 +18,106 @@ package datastore import ( "testing" - "github.com/franela/goblin" "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/model" ) -func TestRepos(t *testing.T) { - store, closer := newTestStore(t, new(model.Repo), new(model.User), new(model.Pipeline)) +func TestCreateRepo(t *testing.T) { + store, closer := newTestStore(t, new(model.Repo)) defer closer() - g := goblin.Goblin(t) - g.Describe("Repo", func() { - // before each test be sure to purge the package - // table data from the database. - g.BeforeEach(func() { - _, err := store.engine.Exec("DELETE FROM pipelines") - g.Assert(err).IsNil() - _, err = store.engine.Exec("DELETE FROM repos") - g.Assert(err).IsNil() - _, err = store.engine.Exec("DELETE FROM users") - g.Assert(err).IsNil() - }) + repo := model.Repo{ + UserID: 1, + FullName: "bradrydzewski/test", + Owner: "bradrydzewski", + Name: "test", + } + err := store.CreateRepo(&repo) + assert.NoError(t, err) + assert.NotZero(t, repo.ID) - g.It("Should Set a Repo", func() { - repo := model.Repo{ - UserID: 1, - FullName: "bradrydzewski/test", - Owner: "bradrydzewski", - Name: "test", - } - err1 := store.CreateRepo(&repo) - err2 := store.UpdateRepo(&repo) - getRepo, err3 := store.GetRepo(repo.ID) + err2 := store.UpdateRepo(&repo) + getRepo, err3 := store.GetRepo(repo.ID) - g.Assert(err1).IsNil() - g.Assert(err2).IsNil() - g.Assert(err3).IsNil() - g.Assert(repo.ID).Equal(getRepo.ID) - }) + assert.NoError(t, err2) + assert.NoError(t, err3) + assert.Equal(t, repo.ID, getRepo.ID) - g.It("Should Add a Repo", func() { - repo := model.Repo{ - UserID: 1, - FullName: "bradrydzewski/test", - Owner: "bradrydzewski", - Name: "test", - } - err := store.CreateRepo(&repo) - g.Assert(err).IsNil() - g.Assert(repo.ID != 0).IsTrue() - }) + // test that repo has name/owner/fullname + assert.Error(t, store.CreateRepo(&model.Repo{ + UserID: 1, + FullName: "bradrydzewski/", + Owner: "bradrydzewski", + Name: "", + })) + assert.Error(t, store.CreateRepo(&model.Repo{ + UserID: 1, + FullName: "/test", + Owner: "", + Name: "test", + })) + assert.Error(t, store.CreateRepo(&model.Repo{ + UserID: 1, + FullName: "", + Owner: "bradrydzewski", + Name: "test", + })) - g.It("Should fail if repo has no name / owner / fullname", func() { - g.Assert(store.CreateRepo(&model.Repo{ - UserID: 1, - FullName: "bradrydzewski/", - Owner: "bradrydzewski", - Name: "", - })).IsNotNil() - g.Assert(store.CreateRepo(&model.Repo{ - UserID: 1, - FullName: "/test", - Owner: "", - Name: "test", - })).IsNotNil() - g.Assert(store.CreateRepo(&model.Repo{ - UserID: 1, - FullName: "", - Owner: "bradrydzewski", - Name: "test", - })).IsNotNil() - }) + // test unique name + repo2 := model.Repo{ + UserID: 2, + FullName: "bradrydzewski/test", + Owner: "bradrydzewski", + Name: "test", + } + err2 = store.CreateRepo(&repo2) + assert.Error(t, err2) +} - g.It("Should Get a Repo by ID", func() { - repo := model.Repo{ - UserID: 1, - FullName: "bradrydzewski/test", - Owner: "bradrydzewski", - Name: "test", - } - g.Assert(store.CreateRepo(&repo)).IsNil() - getrepo, err := store.GetRepo(repo.ID) - g.Assert(err).IsNil() - g.Assert(repo.ID).Equal(getrepo.ID) - g.Assert(repo.UserID).Equal(getrepo.UserID) - g.Assert(repo.Owner).Equal(getrepo.Owner) - g.Assert(repo.Name).Equal(getrepo.Name) - }) +func TestGetRepo(t *testing.T) { + store, closer := newTestStore(t, new(model.Repo)) + defer closer() + repo := model.Repo{ + UserID: 1, + FullName: "bradrydzewski/test", + Owner: "bradrydzewski", + Name: "test", + } + assert.NoError(t, store.CreateRepo(&repo)) + getrepo, err := store.GetRepo(repo.ID) + assert.NoError(t, err) + assert.Equal(t, repo.ID, getrepo.ID) + assert.Equal(t, repo.UserID, getrepo.UserID) + assert.Equal(t, repo.Owner, getrepo.Owner) + assert.Equal(t, repo.Name, getrepo.Name) +} - g.It("Should Get a Repo by Name", func() { - repo := model.Repo{ - UserID: 1, - FullName: "bradrydzewski/test", - Owner: "bradrydzewski", - Name: "test", - } - g.Assert(store.CreateRepo(&repo)).IsNil() - getrepo, err := store.GetRepoName(repo.FullName) - g.Assert(err).IsNil() - g.Assert(repo.ID).Equal(getrepo.ID) - g.Assert(repo.UserID).Equal(getrepo.UserID) - g.Assert(repo.Owner).Equal(getrepo.Owner) - g.Assert(repo.Name).Equal(getrepo.Name) - }) +func TestGetRepoName(t *testing.T) { + store, closer := newTestStore(t, new(model.Repo)) + defer closer() + repo := model.Repo{ + UserID: 1, + FullName: "bradrydzewski/TEST", + Owner: "bradrydzewski", + Name: "TEST", + } - g.It("Should Get a Repo by Name (case-insensitive)", func() { - repo := model.Repo{ - UserID: 1, - FullName: "bradrydzewski/TEST", - Owner: "bradrydzewski", - Name: "TEST", - } - g.Assert(store.CreateRepo(&repo)).IsNil() - getrepo, err := store.GetRepoName("Bradrydzewski/test") - g.Assert(err).IsNil() - g.Assert(repo.ID).Equal(getrepo.ID) - g.Assert(repo.UserID).Equal(getrepo.UserID) - g.Assert(repo.Owner).Equal(getrepo.Owner) - g.Assert(repo.Name).Equal(getrepo.Name) - }) + assert.NoError(t, store.CreateRepo(&repo)) + getrepo, err := store.GetRepoName(repo.FullName) + assert.NoError(t, err) + assert.Equal(t, repo.ID, getrepo.ID) + assert.Equal(t, repo.UserID, getrepo.UserID) + assert.Equal(t, repo.Owner, getrepo.Owner) + assert.Equal(t, repo.Name, getrepo.Name) - g.It("Should Enforce Unique Repo Name", func() { - repo1 := model.Repo{ - UserID: 1, - FullName: "bradrydzewski/test", - Owner: "bradrydzewski", - Name: "test", - } - repo2 := model.Repo{ - UserID: 2, - FullName: "bradrydzewski/test", - Owner: "bradrydzewski", - Name: "test", - } - err1 := store.CreateRepo(&repo1) - err2 := store.CreateRepo(&repo2) - g.Assert(err1).IsNil() - g.Assert(err2 == nil).IsFalse() - }) - }) + // case-insensitive + getrepo, err = store.GetRepoName("Bradrydzewski/test") + assert.NoError(t, err) + assert.Equal(t, repo.ID, getrepo.ID) + assert.Equal(t, repo.UserID, getrepo.UserID) + assert.Equal(t, repo.Owner, getrepo.Owner) + assert.Equal(t, repo.Name, getrepo.Name) } func TestRepoList(t *testing.T) { diff --git a/server/store/datastore/users_test.go b/server/store/datastore/users_test.go index a26ebecca..0189e9f49 100644 --- a/server/store/datastore/users_test.go +++ b/server/store/datastore/users_test.go @@ -18,238 +18,79 @@ package datastore import ( "testing" - "github.com/franela/goblin" + "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/server/model" ) func TestUsers(t *testing.T) { - store, closer := newTestStore(t, new(model.User), new(model.Repo), new(model.Pipeline), new(model.Step), new(model.Perm), new(model.Org), new(model.Secret)) + store, closer := newTestStore(t, new(model.User), new(model.Org), new(model.Secret), new(model.Repo), new(model.Perm)) defer closer() - g := goblin.Goblin(t) - g.Describe("User", func() { - // before each test be sure to purge the package - // table data from the database. - g.BeforeEach(func() { - _, err := store.engine.Exec("DELETE FROM users") - g.Assert(err).IsNil() - _, err = store.engine.Exec("DELETE FROM repos") - g.Assert(err).IsNil() - _, err = store.engine.Exec("DELETE FROM pipelines") - g.Assert(err).IsNil() - _, err = store.engine.Exec("DELETE FROM steps") - g.Assert(err).IsNil() - _, err = store.engine.Exec("DELETE FROM orgs") - g.Assert(err).IsNil() - }) + count, err := store.GetUserCount() + assert.NoError(t, err) + assert.Zero(t, count) - g.It("Should Update a User", func() { - user := model.User{ - Login: "joe", - Email: "foo@bar.com", - AccessToken: "e42080dddf012c718e476da161d21ad5", - } - err1 := store.CreateUser(&user) - err2 := store.UpdateUser(&user) - getUser, err3 := store.GetUser(user.ID) - g.Assert(err1).IsNil() - g.Assert(err2).IsNil() - g.Assert(err3).IsNil() - g.Assert(user.ID).Equal(getUser.ID) - }) + user := model.User{ + Login: "joe", + AccessToken: "f0b461ca586c27872b43a0685cbc2847", + RefreshToken: "976f22a5eef7caacb7e678d6c52f49b1", + Email: "foo@bar.com", + Avatar: "b9015b0857e16ac4d94a0ffd9a0b79c8", + } + err = store.CreateUser(&user) + assert.NoError(t, err) + assert.NotZero(t, user.ID) - g.It("Should Add a new User", func() { - user := model.User{ - Login: "joe", - Email: "foo@bar.com", - AccessToken: "e42080dddf012c718e476da161d21ad5", - } - err := store.CreateUser(&user) - g.Assert(err).IsNil() - g.Assert(user.ID != 0).IsTrue() - }) + err2 := store.UpdateUser(&user) + assert.NoError(t, err2) - g.It("Should Get a User", func() { - user := &model.User{ - Login: "joe", - AccessToken: "f0b461ca586c27872b43a0685cbc2847", - RefreshToken: "976f22a5eef7caacb7e678d6c52f49b1", - Email: "foo@bar.com", - Avatar: "b9015b0857e16ac4d94a0ffd9a0b79c8", - } + getUser, err := store.GetUser(user.ID) + assert.NoError(t, err) + assert.Equal(t, user.ID, getUser.ID) + assert.Equal(t, user.Login, getUser.Login) + assert.Equal(t, user.AccessToken, getUser.AccessToken) + assert.Equal(t, user.RefreshToken, getUser.RefreshToken) + assert.Equal(t, user.Email, getUser.Email) + assert.Equal(t, user.Avatar, getUser.Avatar) - g.Assert(store.CreateUser(user)).IsNil() - getUser, err := store.GetUser(user.ID) - g.Assert(err).IsNil() - g.Assert(user.ID).Equal(getUser.ID) - g.Assert(user.Login).Equal(getUser.Login) - g.Assert(user.AccessToken).Equal(getUser.AccessToken) - g.Assert(user.RefreshToken).Equal(getUser.RefreshToken) - g.Assert(user.Email).Equal(getUser.Email) - g.Assert(user.Avatar).Equal(getUser.Avatar) - }) + getUser, err = store.GetUserLogin(user.Login) + assert.NoError(t, err) + assert.Equal(t, user.ID, getUser.ID) + assert.Equal(t, user.Login, getUser.Login) - g.It("Should Get a User By Login", func() { - user := &model.User{ - Login: "joe", - Email: "foo@bar.com", - AccessToken: "e42080dddf012c718e476da161d21ad5", - } - g.Assert(store.CreateUser(user)) - getUser, err := store.GetUserLogin(user.Login) - g.Assert(err).IsNil() - g.Assert(user.ID).Equal(getUser.ID) - g.Assert(user.Login).Equal(getUser.Login) - }) + // check unique login + user2 := model.User{ + Login: "joe", + Email: "foo@bar.com", + AccessToken: "ab20g0ddaf012c744e136da16aa21ad9", + } + err2 = store.CreateUser(&user2) + assert.Error(t, err2) - g.It("Should Enforce Unique User Login", func() { - user1 := model.User{ - Login: "joe", - Email: "foo@bar.com", - AccessToken: "e42080dddf012c718e476da161d21ad5", - } - user2 := model.User{ - Login: "joe", - Email: "foo@bar.com", - AccessToken: "ab20g0ddaf012c744e136da16aa21ad9", - } - err1 := store.CreateUser(&user1) - err2 := store.CreateUser(&user2) - g.Assert(err1).IsNil() - g.Assert(err2 == nil).IsFalse() - }) + user2 = model.User{ + Login: "jane", + Email: "foo@bar.com", + AccessToken: "ab20g0ddaf012c744e136da16aa21ad9", + Hash: "A", + } + assert.NoError(t, store.CreateUser(&user2)) + users, err := store.GetUserList(&model.ListOptions{Page: 1, PerPage: 50}) + assert.NoError(t, err) + assert.Len(t, users, 2) + // "jane" user is first due to alphabetic sorting + assert.Equal(t, user2.Login, users[0].Login) + assert.Equal(t, user2.Email, users[0].Email) + assert.Equal(t, user2.AccessToken, users[0].AccessToken) - g.It("Should Get a User List", func() { - user1 := model.User{ - Login: "jane", - Email: "foo@bar.com", - AccessToken: "ab20g0ddaf012c744e136da16aa21ad9", - Hash: "A", - } - user2 := model.User{ - Login: "joe", - Email: "foo@bar.com", - AccessToken: "e42080dddf012c718e476da161d21ad5", - } - g.Assert(store.CreateUser(&user1)).IsNil() - g.Assert(store.CreateUser(&user2)).IsNil() - users, err := store.GetUserList(&model.ListOptions{Page: 1, PerPage: 50}) - g.Assert(err).IsNil() - g.Assert(len(users)).Equal(2) - g.Assert(users[0].Login).Equal(user1.Login) - g.Assert(users[0].Email).Equal(user1.Email) - g.Assert(users[0].AccessToken).Equal(user1.AccessToken) - }) + count, err = store.GetUserCount() + assert.NoError(t, err) + assert.EqualValues(t, 2, count) - g.It("Should Get a User Count", func() { - user1 := model.User{ - Login: "jane", - Email: "foo@bar.com", - AccessToken: "ab20g0ddaf012c744e136da16aa21ad9", - Hash: "A", - } - user2 := model.User{ - Login: "joe", - Email: "foo@bar.com", - AccessToken: "e42080dddf012c718e476da161d21ad5", - Hash: "B", - } - g.Assert(store.CreateUser(&user1)).IsNil() - g.Assert(store.CreateUser(&user2)).IsNil() - count, err := store.GetUserCount() - g.Assert(err).IsNil() - g.Assert(count).Equal(int64(2)) - }) - - g.It("Should Get a User Count Zero", func() { - count, err := store.GetUserCount() - g.Assert(err).IsNil() - g.Assert(count).Equal(int64(0)) - }) - - g.It("Should Del a User", func() { - user := &model.User{ - Login: "joe", - Email: "foo@bar.com", - AccessToken: "e42080dddf012c718e476da161d21ad5", - } - g.Assert(store.CreateUser(user)).IsNil() - user, err1 := store.GetUser(user.ID) - g.Assert(err1).IsNil() - err2 := store.DeleteUser(user) - g.Assert(err2).IsNil() - _, err3 := store.GetUser(user.ID) - g.Assert(err3).IsNotNil() - }) - - g.It("Should get the Pipeline feed for a User", func() { - user := &model.User{ - Login: "joe", - Email: "foo@bar.com", - AccessToken: "e42080dddf012c718e476da161d21ad5", - } - g.Assert(store.CreateUser(user)).IsNil() - - repo1 := &model.Repo{ - Owner: "bradrydzewski", - Name: "test", - FullName: "bradrydzewski/test", - IsActive: true, - ForgeRemoteID: "1", - } - repo2 := &model.Repo{ - Owner: "test", - Name: "test", - FullName: "test/test", - IsActive: true, - ForgeRemoteID: "2", - } - repo3 := &model.Repo{ - Owner: "octocat", - Name: "hello-world", - FullName: "octocat/hello-world", - IsActive: true, - ForgeRemoteID: "3", - } - g.Assert(store.CreateRepo(repo1)).IsNil() - g.Assert(store.CreateRepo(repo2)).IsNil() - g.Assert(store.CreateRepo(repo3)).IsNil() - - for _, perm := range []*model.Perm{ - {UserID: user.ID, Repo: repo1, Push: true, Admin: false}, - {UserID: user.ID, Repo: repo2, Push: false, Admin: true}, - } { - g.Assert(store.PermUpsert(perm)).IsNil() - } - - pipeline1 := &model.Pipeline{ - RepoID: repo1.ID, - Status: model.StatusFailure, - } - pipeline2 := &model.Pipeline{ - RepoID: repo1.ID, - Status: model.StatusSuccess, - } - pipeline3 := &model.Pipeline{ - RepoID: repo2.ID, - Status: model.StatusSuccess, - } - pipeline4 := &model.Pipeline{ - RepoID: repo3.ID, - Status: model.StatusSuccess, - } - g.Assert(store.CreatePipeline(pipeline1)).IsNil() - g.Assert(store.CreatePipeline(pipeline2)).IsNil() - g.Assert(store.CreatePipeline(pipeline3)).IsNil() - g.Assert(store.CreatePipeline(pipeline4)).IsNil() - - pipelines, err := store.UserFeed(user) - g.Assert(err).IsNil() - g.Assert(len(pipelines)).Equal(3) - g.Assert(pipelines[0].RepoID).Equal(repo2.ID) - g.Assert(pipelines[1].RepoID).Equal(repo1.ID) - g.Assert(pipelines[2].RepoID).Equal(repo1.ID) - }) - }) + getUser, err1 := store.GetUser(user.ID) + assert.NoError(t, err1) + err2 = store.DeleteUser(getUser) + assert.NoError(t, err2) + _, err3 := store.GetUser(getUser.ID) + assert.Error(t, err3) } diff --git a/shared/token/token_test.go b/shared/token/token_test.go index 5c321e4d9..0c1f3b973 100644 --- a/shared/token/token_test.go +++ b/shared/token/token_test.go @@ -3,60 +3,51 @@ package token_test import ( "testing" - "github.com/franela/goblin" - "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" "github.com/stretchr/testify/assert" "go.woodpecker-ci.org/woodpecker/v3/shared/token" ) -func TestToken(t *testing.T) { - gin.SetMode(gin.TestMode) +const jwtSecret = "secret-to-sign-the-token" - g := goblin.Goblin(t) - g.Describe("Token", func() { - jwtSecret := "secret-to-sign-the-token" +func TestTokenValid(t *testing.T) { + _token := token.New(token.UserToken) + _token.Set("user-id", "1") + signedToken, err := _token.Sign(jwtSecret) + assert.NoError(t, err) - g.It("should parse a valid token", func() { - _token := token.New(token.UserToken) - _token.Set("user-id", "1") - signedToken, err := _token.Sign(jwtSecret) - assert.NoError(g, err) - - parsed, err := token.Parse([]token.Type{token.UserToken}, signedToken, func(_ *token.Token) (string, error) { - return jwtSecret, nil - }) - - assert.NoError(g, err) - assert.NotNil(g, parsed) - assert.Equal(g, "1", parsed.Get("user-id")) - }) - - g.It("should fail to parse a token with a wrong type", func() { - _token := token.New(token.UserToken) - _token.Set("user-id", "1") - signedToken, err := _token.Sign(jwtSecret) - assert.NoError(g, err) - - _, err = token.Parse([]token.Type{token.AgentToken}, signedToken, func(_ *token.Token) (string, error) { - return jwtSecret, nil - }) - - assert.ErrorIs(g, err, jwt.ErrInvalidType) - }) - - g.It("should fail to parse a token with a wrong secret", func() { - _token := token.New(token.UserToken) - _token.Set("user-id", "1") - signedToken, err := _token.Sign(jwtSecret) - assert.NoError(g, err) - - _, err = token.Parse([]token.Type{token.UserToken}, signedToken, func(_ *token.Token) (string, error) { - return "this-is-a-wrong-secret", nil - }) - - assert.ErrorIs(g, err, jwt.ErrSignatureInvalid) - }) + parsed, err := token.Parse([]token.Type{token.UserToken}, signedToken, func(_ *token.Token) (string, error) { + return jwtSecret, nil }) + + assert.NoError(t, err) + assert.NotNil(t, parsed) + assert.Equal(t, "1", parsed.Get("user-id")) +} + +func TestTokenWrongType(t *testing.T) { + _token := token.New(token.UserToken) + _token.Set("user-id", "1") + signedToken, err := _token.Sign(jwtSecret) + assert.NoError(t, err) + + _, err = token.Parse([]token.Type{token.AgentToken}, signedToken, func(_ *token.Token) (string, error) { + return jwtSecret, nil + }) + + assert.ErrorIs(t, err, jwt.ErrInvalidType) +} + +func TestTokenWrongSecret(t *testing.T) { + _token := token.New(token.UserToken) + _token.Set("user-id", "1") + signedToken, err := _token.Sign(jwtSecret) + assert.NoError(t, err) + + _, err = token.Parse([]token.Type{token.UserToken}, signedToken, func(_ *token.Token) (string, error) { + return "this-is-a-wrong-secret", nil + }) + + assert.ErrorIs(t, err, jwt.ErrSignatureInvalid) }