Commit 66b47a62 authored by Heidi Berry's avatar Heidi Berry
Browse files

Merge branch 'add-missing-tests' into 'main'

Add missing tests for refactored functions

See merge request !2676
parents bf4fa2a7 42796839
Loading
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -37,14 +37,31 @@ mise exec -- make reviewable

### Test Patterns

- All tests use the `testing` package with `testify/assert`
- Tests are parallelized using `t.Parallel()`
- Mock HTTP handlers are used for API testing
- Test data is stored in `testdata/` directory
- Each service method should have corresponding test coverage
  - **CRITICAL** - When fixing bugs or creating new features, ensure new test scenarios are added to cover the new logic.
- When writing a test, write Gherkin comments in-line with the test to make the tests easier to read. This means adding GIVEN/WHEN/THEN comments in tests.
- All tests use the `testing` package with `testify/assert`

Do not use `reflect.DeepEqual` in tests, use testify instead. 

```go
// This is an example of the incorrect test setup
want := &MyStruct{
		MyField: "Meow Kitty"
}
if !reflect.DeepEqual(want, otherStruct) {
    t.Errorf("MyStruct returned %+v, want %+v", otherStruct, want)
}

// Instead, use this
want := &MyStruct{
		MyField: "Meow Kitty"
}
assert.Equal(t, want, otherStruct)
```

### Test Structure Example

+132 −0
Original line number Diff line number Diff line
@@ -257,3 +257,135 @@ func TestRetryFailedExternalStatusCheckForProjectMergeRequest(t *testing.T) {

	assert.NotNil(t, resp)
}

func TestSetExternalStatusCheckStatus(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a project with a merge request
	// WHEN setting the status of an external status check
	mux.HandleFunc("/api/v4/projects/1/merge_requests/2/status_check_responses", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		w.WriteHeader(http.StatusCreated)
	})

	opt := &SetExternalStatusCheckStatusOptions{
		SHA:                   Ptr("abc123"),
		ExternalStatusCheckID: Ptr(int64(5)),
		Status:                Ptr("passed"),
	}

	// THEN the status should be set successfully
	resp, err := client.ExternalStatusChecks.SetExternalStatusCheckStatus(1, 2, opt)
	assert.NoError(t, err)
	assert.NotNil(t, resp)
	assert.Equal(t, http.StatusCreated, resp.StatusCode)
}

func TestCreateExternalStatusCheck(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a project
	// WHEN creating an external status check
	mux.HandleFunc("/api/v4/projects/1/external_status_checks", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		w.WriteHeader(http.StatusCreated)
	})

	opt := &CreateExternalStatusCheckOptions{
		Name:               Ptr("Security Check"),
		ExternalURL:        Ptr("https://example.com/check"),
		ProtectedBranchIDs: &[]int64{1, 2},
	}

	// THEN the external status check should be created successfully
	resp, err := client.ExternalStatusChecks.CreateExternalStatusCheck(1, opt)
	assert.NoError(t, err)
	assert.NotNil(t, resp)
	assert.Equal(t, http.StatusCreated, resp.StatusCode)
}

func TestDeleteExternalStatusCheck(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a project with an external status check
	// WHEN deleting the external status check
	mux.HandleFunc("/api/v4/projects/1/external_status_checks/5", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodDelete)
		w.WriteHeader(http.StatusNoContent)
	})

	// THEN the external status check should be deleted successfully
	resp, err := client.ExternalStatusChecks.DeleteExternalStatusCheck(1, 5)
	assert.NoError(t, err)
	assert.NotNil(t, resp)
	assert.Equal(t, http.StatusNoContent, resp.StatusCode)
}

func TestUpdateExternalStatusCheck(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a project with an external status check
	// WHEN updating the external status check
	mux.HandleFunc("/api/v4/projects/1/external_status_checks/5", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPut)
		w.WriteHeader(http.StatusOK)
	})

	opt := &UpdateExternalStatusCheckOptions{
		Name:               Ptr("Updated Security Check"),
		ExternalURL:        Ptr("https://example.com/updated-check"),
		ProtectedBranchIDs: &[]int64{1, 2, 3},
	}

	// THEN the external status check should be updated successfully
	resp, err := client.ExternalStatusChecks.UpdateExternalStatusCheck(1, 5, opt)
	assert.NoError(t, err)
	assert.NotNil(t, resp)
	assert.Equal(t, http.StatusOK, resp.StatusCode)
}

func TestDeleteProjectExternalStatusCheck(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a project with an external status check
	// WHEN deleting the project external status check
	mux.HandleFunc("/api/v4/projects/1/external_status_checks/5", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodDelete)
		w.WriteHeader(http.StatusNoContent)
	})

	// THEN the project external status check should be deleted successfully
	resp, err := client.ExternalStatusChecks.DeleteProjectExternalStatusCheck(1, 5, &DeleteProjectExternalStatusCheckOptions{})
	assert.NoError(t, err)
	assert.NotNil(t, resp)
	assert.Equal(t, http.StatusNoContent, resp.StatusCode)
}

func TestSetProjectMergeRequestExternalStatusCheckStatus(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a project with a merge request
	// WHEN setting the status of a project merge request external status check
	mux.HandleFunc("/api/v4/projects/1/merge_requests/2/status_check_responses", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		w.WriteHeader(http.StatusCreated)
	})

	opt := &SetProjectMergeRequestExternalStatusCheckStatusOptions{
		SHA:                   Ptr("abc123"),
		ExternalStatusCheckID: Ptr(int64(5)),
		Status:                Ptr("passed"),
	}

	// THEN the status should be set successfully
	resp, err := client.ExternalStatusChecks.SetProjectMergeRequestExternalStatusCheckStatus(1, 2, opt)
	assert.NoError(t, err)
	assert.NotNil(t, resp)
	assert.Equal(t, http.StatusCreated, resp.StatusCode)
}
+74 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import (
	"net/http"
	"reflect"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestListGroupBadges(t *testing.T) {
@@ -131,3 +133,75 @@ func TestRemoveGroupBadge(t *testing.T) {
		t.Errorf("GroupsBadges.DeleteGroupBadge returned %d, want %d", got, want)
	}
}

func TestPreviewGroupBadge(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a group
	// WHEN previewing a badge with placeholder interpolation
	mux.HandleFunc("/api/v4/groups/1/badges/render",
		func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodGet)
			fmt.Fprint(w, `{
				"link_url": "https://example.com/project/%{project_path}",
				"image_url": "https://shields.io/badge/coverage-95%25-green",
				"rendered_link_url": "https://example.com/project/my-group/my-project",
				"rendered_image_url": "https://shields.io/badge/coverage-95%25-green"
			}`)
		},
	)

	opt := &GroupBadgePreviewOptions{
		LinkURL:  Ptr("https://example.com/project/%{project_path}"),
		ImageURL: Ptr("https://shields.io/badge/coverage-95%25-green"),
	}

	// THEN the badge preview should be returned with rendered URLs
	badge, _, err := client.GroupBadges.PreviewGroupBadge(1, opt)
	assert.NoError(t, err)

	want := &GroupBadge{
		LinkURL:          "https://example.com/project/%{project_path}",
		ImageURL:         "https://shields.io/badge/coverage-95%25-green",
		RenderedLinkURL:  "https://example.com/project/my-group/my-project",
		RenderedImageURL: "https://shields.io/badge/coverage-95%25-green",
	}
	assert.Equal(t, want, badge)
}

func TestPreviewGroupBadgeWithURLEncodedPath(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a group with URL-encoded path
	// WHEN previewing a badge with placeholder interpolation using URL-encoded group path
	mux.HandleFunc("/api/v4/groups/my-org%2Fmy-group/badges/render",
		func(w http.ResponseWriter, r *http.Request) {
			testMethod(t, r, http.MethodGet)
			fmt.Fprint(w, `{
				"link_url": "https://example.com/project/%{project_path}",
				"image_url": "https://shields.io/badge/build-passing-brightgreen",
				"rendered_link_url": "https://example.com/project/my-org/my-group",
				"rendered_image_url": "https://shields.io/badge/build-passing-brightgreen"
			}`)
		},
	)

	opt := &GroupBadgePreviewOptions{
		LinkURL:  Ptr("https://example.com/project/%{project_path}"),
		ImageURL: Ptr("https://shields.io/badge/build-passing-brightgreen"),
	}

	// THEN the badge preview should work with URL-encoded group path
	badge, _, err := client.GroupBadges.PreviewGroupBadge("my-org/my-group", opt)
	assert.NoError(t, err)

	want := &GroupBadge{
		LinkURL:          "https://example.com/project/%{project_path}",
		ImageURL:         "https://shields.io/badge/build-passing-brightgreen",
		RenderedLinkURL:  "https://example.com/project/my-org/my-group",
		RenderedImageURL: "https://shields.io/badge/build-passing-brightgreen",
	}
	assert.Equal(t, want, badge)
}
+65 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import (
	"net/http"
	"reflect"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestCreateGroupGroupLabel(t *testing.T) {
@@ -74,6 +76,42 @@ func TestDeleteGroupLabelByName(t *testing.T) {
	}
}

func TestDeleteGroupLabelWithOptions(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a group with a label
	// WHEN deleting the label using the Name option
	mux.HandleFunc("/api/v4/groups/1/labels", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodDelete)
		testParam(t, r, "name", "MyGroupLabel")
	})

	opt := &DeleteGroupLabelOptions{Name: Ptr("MyGroupLabel")}

	// THEN the label should be deleted successfully
	_, err := client.GroupLabels.DeleteGroupLabel("1", nil, opt)
	assert.NoError(t, err)
}

func TestDeleteGroupLabelWithOptionsAndURLEncodedPath(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a group with URL-encoded path and a label
	// WHEN deleting the label using the Name option with URL-encoded group path
	mux.HandleFunc("/api/v4/groups/my-org%2Fmy-group/labels", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodDelete)
		testParam(t, r, "name", "MyGroupLabel")
	})

	opt := &DeleteGroupLabelOptions{Name: Ptr("MyGroupLabel")}

	// THEN the label should be deleted successfully using URL-encoded group path
	_, err := client.GroupLabels.DeleteGroupLabel("my-org/my-group", nil, opt)
	assert.NoError(t, err)
}

func TestUpdateGroupLabel(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)
@@ -105,6 +143,33 @@ func TestUpdateGroupLabel(t *testing.T) {
	}
}

func TestUpdateGroupLabelWithNilID(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a group with a label
	// WHEN updating the label using the Name option
	mux.HandleFunc("/api/v4/groups/1/labels", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPut)
		fmt.Fprint(w, `{"id":1, "name": "NewLabel", "color" : "#11FF23" , "description":"This is updated label"}`)
	})

	l := &UpdateGroupLabelOptions{
		Name:        Ptr("MyGroupLabel"),
		NewName:     Ptr("NewLabel"),
		Color:       Ptr("#11FF23"),
		Description: Ptr("This is updated label"),
	}

	// THEN the label should be updated successfully
	label, resp, err := client.GroupLabels.UpdateGroupLabel("1", nil, l)
	assert.NoError(t, err)
	assert.NotNil(t, resp)

	want := &GroupLabel{ID: 1, Name: "NewLabel", Color: "#11FF23", Description: "This is updated label"}
	assert.Equal(t, want, label)
}

func TestSubscribeToGroupLabel(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)
+37 −0
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@ import (
	"net/http"
	"reflect"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestCreateLabel(t *testing.T) {
@@ -191,3 +193,38 @@ func TestGetLabel(t *testing.T) {
		t.Errorf("Labels.GetLabel returned %+v, want %+v", label, want)
	}
}

func TestDeleteLabelWithOptions(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a project with a label
	// WHEN deleting the label using the Name option
	mux.HandleFunc("/api/v4/projects/1/labels", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodDelete)
		testParam(t, r, "name", "MyLabel")
	})

	opt := &DeleteLabelOptions{Name: Ptr("MyLabel")}

	// THEN the label should be deleted successfully
	_, err := client.Labels.DeleteLabel("1", nil, opt)
	assert.NoError(t, err)
}

func TestPromoteLabel(t *testing.T) {
	t.Parallel()
	mux, client := setup(t)

	// GIVEN a project with a label
	// WHEN promoting the label to a group label
	mux.HandleFunc("/api/v4/projects/1/labels/5/promote", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPut)
		w.WriteHeader(http.StatusOK)
	})

	// THEN the label should be promoted successfully
	resp, err := client.Labels.PromoteLabel("1", 5)
	assert.NoError(t, err)
	assert.Equal(t, http.StatusOK, resp.StatusCode)
}
Loading