Verified Commit 63de4930 authored by Patrick Rice's avatar Patrick Rice 🛶 Committed by GitLab
Browse files

Merge branch 'security-scan-profiles-request-tests' into 'main'

test(security-scan-profiles): Validate GraphQL request structure

See merge request !2942
parents 7040d6ae 65e0c118
Loading
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
package gitlab

import (
	"encoding/json"
	"fmt"
	"net/http"
	"testing"
@@ -9,6 +10,16 @@ import (
	"github.com/stretchr/testify/require"
)

// testGraphQLRequestBody asserts that the request body sent to the GraphQL
// endpoint exactly matches want's query and variables.
func testGraphQLRequestBody(t *testing.T, r *http.Request, want GraphQLQuery) {
	t.Helper()

	body, err := json.Marshal(want)
	require.NoError(t, err)
	testJSONBody(t, r, string(body))
}

func TestGraphQL_Do_Success(t *testing.T) {
	t.Parallel()

+36 −28
Original line number Diff line number Diff line
@@ -40,6 +40,39 @@ type (

var _ SecurityScanProfilesServiceInterface = (*SecurityScanProfilesService)(nil)

const (
	securityScanProfileAttachMutation = `
			mutation SecurityScanProfileAttach($input: SecurityScanProfileAttachInput!) {
				securityScanProfileAttach(input: $input) {
					errors
				}
			}
		`

	securityScanProfileDetachMutation = `
			mutation SecurityScanProfileDetach($input: SecurityScanProfileDetachInput!) {
				securityScanProfileDetach(input: $input) {
					errors
				}
			}
		`

	scanProfileStatusesQuery = `
			query($fullPath: ID!) {
				project(fullPath: $fullPath) {
					scanProfileStatuses {
						status
						scanProfile {
							id
							name
							scanType
						}
					}
				}
			}
		`
)

// ScanProfile represents a security scan profile.
//
// GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#scanprofiletype
@@ -124,13 +157,7 @@ func (s *SecurityScanProfilesService) AttachSecurityScanProfile(opt *AttachSecur
	}

	mutation := GraphQLQuery{
		Query: `
			mutation SecurityScanProfileAttach($input: SecurityScanProfileAttachInput!) {
				securityScanProfileAttach(input: $input) {
					errors
				}
			}
		`,
		Query: securityScanProfileAttachMutation,
		Variables: map[string]any{
			"input": map[string]any{
				"securityScanProfileId": opt.SecurityScanProfileID,
@@ -173,13 +200,7 @@ func (s *SecurityScanProfilesService) DetachSecurityScanProfile(opt *DetachSecur
	}

	mutation := GraphQLQuery{
		Query: `
			mutation SecurityScanProfileDetach($input: SecurityScanProfileDetachInput!) {
				securityScanProfileDetach(input: $input) {
					errors
				}
			}
		`,
		Query: securityScanProfileDetachMutation,
		Variables: map[string]any{
			"input": map[string]any{
				"securityScanProfileId": opt.SecurityScanProfileID,
@@ -219,20 +240,7 @@ func (s *SecurityScanProfilesService) DetachSecurityScanProfile(opt *DetachSecur
// GitLab API docs: https://docs.gitlab.com/api/graphql/reference/#project-scanprofilestatuses
func (s *SecurityScanProfilesService) ListProjectScanProfileStatuses(projectFullPath string, options ...RequestOptionFunc) ([]ScanProfileStatus, *Response, error) {
	query := GraphQLQuery{
		Query: `
			query($fullPath: ID!) {
				project(fullPath: $fullPath) {
					scanProfileStatuses {
						status
						scanProfile {
							id
							name
							scanType
						}
					}
				}
			}
		`,
		Query: scanProfileStatusesQuery,
		Variables: map[string]any{
			"fullPath": projectFullPath,
		},
+62 −0
Original line number Diff line number Diff line
@@ -16,6 +16,16 @@ func TestSecurityScanProfiles_AttachSecurityScanProfile(t *testing.T) {

	mux.HandleFunc("/api/graphql", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		testGraphQLRequestBody(t, r, GraphQLQuery{
			Query: securityScanProfileAttachMutation,
			Variables: map[string]any{
				"input": map[string]any{
					"securityScanProfileId": SecurityScanProfileGID("dependency_scanning_post_processing"),
					"projectIds":            []string{"gid://gitlab/Project/1"},
					"groupIds":              []string{},
				},
			},
		})
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, `
			{
@@ -52,6 +62,16 @@ func TestSecurityScanProfiles_AttachSecurityScanProfile_errors(t *testing.T) {

	mux.HandleFunc("/api/graphql", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		testGraphQLRequestBody(t, r, GraphQLQuery{
			Query: securityScanProfileAttachMutation,
			Variables: map[string]any{
				"input": map[string]any{
					"securityScanProfileId": SecurityScanProfileGID("dependency_scanning_post_processing"),
					"projectIds":            []string{"gid://gitlab/Project/1"},
					"groupIds":              []string{},
				},
			},
		})
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, `
			{
@@ -81,6 +101,16 @@ func TestSecurityScanProfiles_AttachSecurityScanProfile_topLevelErrors(t *testin
	// GraphQL error with HTTP 200 and a null data payload.
	mux.HandleFunc("/api/graphql", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		testGraphQLRequestBody(t, r, GraphQLQuery{
			Query: securityScanProfileAttachMutation,
			Variables: map[string]any{
				"input": map[string]any{
					"securityScanProfileId": SecurityScanProfileGID("dependency_scanning_post_processing"),
					"projectIds":            []string{"gid://gitlab/Project/1"},
					"groupIds":              []string{},
				},
			},
		})
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, `
			{
@@ -107,6 +137,16 @@ func TestSecurityScanProfiles_DetachSecurityScanProfile(t *testing.T) {

	mux.HandleFunc("/api/graphql", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		testGraphQLRequestBody(t, r, GraphQLQuery{
			Query: securityScanProfileDetachMutation,
			Variables: map[string]any{
				"input": map[string]any{
					"securityScanProfileId": SecurityScanProfileGID("dependency_scanning_post_processing"),
					"projectIds":            []string{"gid://gitlab/Project/1"},
					"groupIds":              []string{},
				},
			},
		})
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, `
			{
@@ -143,6 +183,16 @@ func TestSecurityScanProfiles_DetachSecurityScanProfile_errors(t *testing.T) {

	mux.HandleFunc("/api/graphql", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		testGraphQLRequestBody(t, r, GraphQLQuery{
			Query: securityScanProfileDetachMutation,
			Variables: map[string]any{
				"input": map[string]any{
					"securityScanProfileId": SecurityScanProfileGID("dependency_scanning_post_processing"),
					"projectIds":            []string{"gid://gitlab/Project/1"},
					"groupIds":              []string{},
				},
			},
		})
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, `
			{
@@ -170,6 +220,12 @@ func TestSecurityScanProfiles_ListProjectScanProfileStatuses(t *testing.T) {

	mux.HandleFunc("/api/graphql", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		testGraphQLRequestBody(t, r, GraphQLQuery{
			Query: scanProfileStatusesQuery,
			Variables: map[string]any{
				"fullPath": "mygroup/myproject",
			},
		})
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, `
			{
@@ -214,6 +270,12 @@ func TestSecurityScanProfiles_ListProjectScanProfileStatuses_projectNotFound(t *

	mux.HandleFunc("/api/graphql", func(w http.ResponseWriter, r *http.Request) {
		testMethod(t, r, http.MethodPost)
		testGraphQLRequestBody(t, r, GraphQLQuery{
			Query: scanProfileStatusesQuery,
			Variables: map[string]any{
				"fullPath": "nonexistent/project",
			},
		})
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, `{"data": {"project": null}}`)
	})