@@ -540,6 +540,7 @@ func TestAccessReviewCampaign_DeleteRemovesFromListAndNode(t *testing.T) {
|
||||
|
||||
err = owner.Execute(listQuery, map[string]any{"id": orgID}, &listResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, edge := range listResult.Node.AccessReviewCampaigns.Edges {
|
||||
assert.NotEqual(t, campaignID, edge.Node.ID, "deleted campaign must not appear in the connection")
|
||||
}
|
||||
@@ -557,6 +558,7 @@ func TestAccessReviewCampaign_DeleteRemovesFromListAndNode(t *testing.T) {
|
||||
`
|
||||
|
||||
_, err = owner.Do(nodeQuery, map[string]any{"id": campaignID})
|
||||
|
||||
var gqlErrors testutil.GraphQLErrors
|
||||
require.ErrorAs(t, err, &gqlErrors)
|
||||
require.Len(t, gqlErrors, 1)
|
||||
@@ -1114,11 +1116,13 @@ func TestAccessReviewCampaign_FullLifecycle(t *testing.T) {
|
||||
}
|
||||
|
||||
var campaignResult campaignQueryResult
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
err := owner.Execute(nodeQuery, map[string]any{"id": campaignID}, &campaignResult)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return campaignResult.Node.Status == "PENDING_ACTIONS"
|
||||
}, 60*time.Second, 1*time.Second, "campaign should transition to PENDING_ACTIONS")
|
||||
|
||||
@@ -1239,6 +1243,7 @@ func TestAccessReviewCampaign_CloseRequiresAllDecisions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
err := owner.Execute(startQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"accessReviewCampaignId": campaignID,
|
||||
@@ -1264,6 +1269,7 @@ func TestAccessReviewCampaign_CloseRequiresAllDecisions(t *testing.T) {
|
||||
if err := owner.Execute(nodeQuery, map[string]any{"id": campaignID}, &r); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return r.Node.Status == "PENDING_ACTIONS"
|
||||
}, 60*time.Second, 1*time.Second)
|
||||
|
||||
|
||||
@@ -240,6 +240,7 @@ func TestAsset_PublishAssetList(t *testing.T) {
|
||||
|
||||
ver1Major := result1.PublishAssetList.DocumentVersionEdge.Node.Major
|
||||
ver2Major := result2.PublishAssetList.DocumentVersionEdge.Node.Major
|
||||
|
||||
assert.Equal(t, 1, ver1Major)
|
||||
assert.Equal(t, 2, ver2Major)
|
||||
},
|
||||
|
||||
@@ -125,6 +125,7 @@ func TestAsset_Update(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
assetID := createResult.CreateAsset.AssetEdge.Node.ID
|
||||
|
||||
const query = `
|
||||
@@ -205,6 +206,7 @@ func TestAsset_Delete(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
assetID := createResult.CreateAsset.AssetEdge.Node.ID
|
||||
|
||||
const query = `
|
||||
|
||||
@@ -80,17 +80,21 @@ func TestAuditLog_List(t *testing.T) {
|
||||
|
||||
// Find the thirdParty create entry.
|
||||
found := false
|
||||
|
||||
for _, edge := range result.Node.AuditLogEntries.Edges {
|
||||
if edge.Node.Action == "core:thirdParty:create" {
|
||||
found = true
|
||||
|
||||
assert.Equal(t, "USER", edge.Node.ActorType)
|
||||
assert.Equal(t, "ThirdParty", edge.Node.ResourceType)
|
||||
assert.NotEmpty(t, edge.Node.ActorID)
|
||||
assert.NotEmpty(t, edge.Node.ResourceID)
|
||||
assert.NotEmpty(t, edge.Node.CreatedAt)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert.True(t, found, "expected to find core:thirdParty:create audit log entry")
|
||||
}
|
||||
|
||||
@@ -143,6 +147,7 @@ func TestAuditLog_Filter(t *testing.T) {
|
||||
}, &result)
|
||||
require.NoError(t, err)
|
||||
assert.GreaterOrEqual(t, result.Node.AuditLogEntries.TotalCount, 1)
|
||||
|
||||
for _, edge := range result.Node.AuditLogEntries.Edges {
|
||||
assert.Equal(t, "core:thirdParty:create", edge.Node.Action)
|
||||
}
|
||||
@@ -171,6 +176,7 @@ func TestAuditLog_Filter(t *testing.T) {
|
||||
}, &result)
|
||||
require.NoError(t, err)
|
||||
assert.GreaterOrEqual(t, result.Node.AuditLogEntries.TotalCount, 1)
|
||||
|
||||
for _, edge := range result.Node.AuditLogEntries.Edges {
|
||||
assert.Equal(t, "ThirdParty", edge.Node.ResourceType)
|
||||
}
|
||||
|
||||
@@ -250,9 +250,11 @@ func TestAudit_Create_Validation(t *testing.T) {
|
||||
if !tt.skipOrganization {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
|
||||
if !tt.skipFramework {
|
||||
input["frameworkId"] = frameworkID
|
||||
}
|
||||
|
||||
maps.Copy(input, tt.input)
|
||||
|
||||
_, err := owner.Do(query, map[string]any{"input": input})
|
||||
@@ -376,6 +378,7 @@ func TestAudit_Update(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
audit := result.UpdateAudit.Audit
|
||||
|
||||
switch tt.assertField {
|
||||
case "name":
|
||||
assert.Equal(t, tt.assertValue, audit.Name)
|
||||
@@ -1188,6 +1191,7 @@ func TestAudit_Pagination(t *testing.T) {
|
||||
assert.GreaterOrEqual(t, result.Node.Audits.TotalCount, 5)
|
||||
|
||||
testutil.AssertHasMorePages(t, result.Node.Audits.PageInfo)
|
||||
|
||||
queryAfter := `
|
||||
query($id: ID!, $after: CursorKey) {
|
||||
node(id: $id) {
|
||||
@@ -1372,7 +1376,6 @@ func TestAudit_TenantIsolation(t *testing.T) {
|
||||
err := org2Owner.Execute(query, map[string]any{
|
||||
"id": org1Owner.GetOrganizationID().String(),
|
||||
}, &result)
|
||||
|
||||
if err == nil {
|
||||
for _, edge := range result.Node.Audits.Edges {
|
||||
assert.NotEqual(t, auditID, edge.Node.ID, "Should not see audit from another org")
|
||||
@@ -1434,6 +1437,7 @@ func TestAudit_Ordering(t *testing.T) {
|
||||
for i, edge := range result.Node.Audits.Edges {
|
||||
times[i] = edge.Node.CreatedAt
|
||||
}
|
||||
|
||||
testutil.AssertTimesOrderedDescending(t, times, "createdAt")
|
||||
})
|
||||
}
|
||||
@@ -1539,6 +1543,7 @@ func TestAudit_UploadReport(t *testing.T) {
|
||||
Content: pdfContent1,
|
||||
}, &result1)
|
||||
require.NoError(t, err)
|
||||
|
||||
firstReportID := result1.UploadAuditReport.Audit.Report.ID
|
||||
|
||||
// Upload second report (should replace)
|
||||
|
||||
@@ -75,6 +75,7 @@ func TestConnectorProviderInfos(t *testing.T) {
|
||||
assert.NotEmpty(t, infos)
|
||||
|
||||
providerNames := make(map[string]bool)
|
||||
|
||||
for _, info := range infos {
|
||||
assert.NotEmpty(t, info.Provider)
|
||||
assert.NotEmpty(t, info.DisplayName)
|
||||
|
||||
@@ -118,7 +118,6 @@ func TestControl_Update(t *testing.T) {
|
||||
assert.Equal(t, controlID, result.UpdateControl.Control.ID)
|
||||
assert.Equal(t, "Updated Control Name", result.UpdateControl.Control.Name)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestControl_Delete(t *testing.T) {
|
||||
@@ -243,6 +242,7 @@ func TestControl_RequiredFields(t *testing.T) {
|
||||
},
|
||||
}, &frameworkResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
frameworkID := frameworkResult.CreateFramework.FrameworkEdge.Node.ID
|
||||
|
||||
createControlQuery := `
|
||||
@@ -389,6 +389,7 @@ func TestControl_OmittableDescription(t *testing.T) {
|
||||
},
|
||||
}, &frameworkResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
frameworkID := frameworkResult.CreateFramework.FrameworkEdge.Node.ID
|
||||
|
||||
// Create control with description
|
||||
@@ -427,6 +428,7 @@ func TestControl_OmittableDescription(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
controlID := createResult.CreateControl.ControlEdge.Node.ID
|
||||
|
||||
t.Run("Update with null description should clear it", func(t *testing.T) {
|
||||
@@ -573,6 +575,7 @@ func TestControl_MaturityLevel(t *testing.T) {
|
||||
|
||||
t.Run("create with INITIAL maturityLevel", func(t *testing.T) {
|
||||
var res createResult
|
||||
|
||||
err := owner.Execute(createControlQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"frameworkId": frameworkID,
|
||||
@@ -589,6 +592,7 @@ func TestControl_MaturityLevel(t *testing.T) {
|
||||
|
||||
t.Run("create with maturityLevel persists value", func(t *testing.T) {
|
||||
var res createResult
|
||||
|
||||
err := owner.Execute(createControlQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"frameworkId": frameworkID,
|
||||
@@ -605,6 +609,7 @@ func TestControl_MaturityLevel(t *testing.T) {
|
||||
|
||||
t.Run("update lifecycle: set, change, omit", func(t *testing.T) {
|
||||
var created createResult
|
||||
|
||||
err := owner.Execute(createControlQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"frameworkId": frameworkID,
|
||||
@@ -616,10 +621,12 @@ func TestControl_MaturityLevel(t *testing.T) {
|
||||
},
|
||||
}, &created)
|
||||
require.NoError(t, err)
|
||||
|
||||
controlID := created.CreateControl.ControlEdge.Node.ID
|
||||
|
||||
// set
|
||||
var setRes updateResult
|
||||
|
||||
err = owner.Execute(updateControlQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": controlID,
|
||||
@@ -631,6 +638,7 @@ func TestControl_MaturityLevel(t *testing.T) {
|
||||
|
||||
// change
|
||||
var changeRes updateResult
|
||||
|
||||
err = owner.Execute(updateControlQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": controlID,
|
||||
@@ -642,6 +650,7 @@ func TestControl_MaturityLevel(t *testing.T) {
|
||||
|
||||
// omit field on next update -> stays unchanged
|
||||
var omitRes updateResult
|
||||
|
||||
err = owner.Execute(updateControlQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": controlID,
|
||||
@@ -654,6 +663,7 @@ func TestControl_MaturityLevel(t *testing.T) {
|
||||
|
||||
t.Run("invalid maturityLevel is rejected", func(t *testing.T) {
|
||||
var res createResult
|
||||
|
||||
err := owner.Execute(createControlQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"frameworkId": frameworkID,
|
||||
@@ -702,6 +712,7 @@ func TestControl_SubResolvers(t *testing.T) {
|
||||
},
|
||||
}, &frameworkResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
frameworkID := frameworkResult.CreateFramework.FrameworkEdge.Node.ID
|
||||
|
||||
// Create control
|
||||
@@ -738,6 +749,7 @@ func TestControl_SubResolvers(t *testing.T) {
|
||||
},
|
||||
}, &controlResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
controlID := controlResult.CreateControl.ControlEdge.Node.ID
|
||||
|
||||
// Create a measure and link it
|
||||
@@ -771,6 +783,7 @@ func TestControl_SubResolvers(t *testing.T) {
|
||||
},
|
||||
}, &measureResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
measureID := measureResult.CreateMeasure.MeasureEdge.Node.ID
|
||||
|
||||
// Create mapping
|
||||
|
||||
@@ -84,6 +84,7 @@ func TestCookieBanner_Create(t *testing.T) {
|
||||
}, &result)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
node := result.CreateCookieBanner.CookieBannerEdge.Node
|
||||
assert.NotEmpty(t, node.ID)
|
||||
assert.Equal(t, name, node.Name)
|
||||
@@ -135,6 +136,7 @@ func TestCookieBanner_Create(t *testing.T) {
|
||||
}, &result)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
node := result.CreateCookieBanner.CookieBannerEdge.Node
|
||||
assert.NotEmpty(t, node.ID)
|
||||
require.NotNil(t, node.PrivacyPolicyUrl)
|
||||
@@ -189,6 +191,7 @@ func TestCookieBanner_Create(t *testing.T) {
|
||||
for _, e := range result.Node.ConsentCategories.Edges {
|
||||
kinds[e.Node.Kind] = true
|
||||
}
|
||||
|
||||
assert.True(t, kinds["NECESSARY"], "should have a NECESSARY category")
|
||||
})
|
||||
|
||||
@@ -262,6 +265,7 @@ func TestCookieBanner_Update(t *testing.T) {
|
||||
`
|
||||
|
||||
newName := factory.SafeName("Updated")
|
||||
|
||||
var result struct {
|
||||
UpdateCookieBanner struct {
|
||||
CookieBanner struct {
|
||||
@@ -410,6 +414,7 @@ func TestCookieBanner_ActivateDeactivate(t *testing.T) {
|
||||
} `json:"cookieBanner"`
|
||||
} `json:"deactivateCookieBanner"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: DeactivateCookieBannerInput!) {
|
||||
deactivateCookieBanner(input: $input) {
|
||||
@@ -751,8 +756,10 @@ func TestCookieBanner_UpsertTranslation(t *testing.T) {
|
||||
} `json:"cookieBannerTranslation"`
|
||||
} `json:"upsertCookieBannerTranslation"`
|
||||
}
|
||||
|
||||
err := owner.Execute(query, input, &result1)
|
||||
require.NoError(t, err)
|
||||
|
||||
firstID := result1.UpsertCookieBannerTranslation.CookieBannerTranslation.ID
|
||||
|
||||
input["input"].(map[string]any)["translations"] = `{"title":"Ajustes de cookies"}`
|
||||
@@ -765,6 +772,7 @@ func TestCookieBanner_UpsertTranslation(t *testing.T) {
|
||||
} `json:"cookieBannerTranslation"`
|
||||
} `json:"upsertCookieBannerTranslation"`
|
||||
}
|
||||
|
||||
err = owner.Execute(query, input, &result2)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, firstID, result2.UpsertCookieBannerTranslation.CookieBannerTranslation.ID)
|
||||
|
||||
@@ -166,6 +166,7 @@ func TestCookieBannerVersioning_NoOpUpdates(t *testing.T) {
|
||||
`
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"cookieBannerId": bannerID,
|
||||
@@ -238,6 +239,7 @@ func TestCookieBannerVersioning_NoOpUpdates(t *testing.T) {
|
||||
`
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"cookieCategoryId": categoryID,
|
||||
@@ -273,6 +275,7 @@ func TestCookieBannerVersioning_NoOpUpdates(t *testing.T) {
|
||||
`
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"cookieCategoryId": categoryID,
|
||||
@@ -308,6 +311,7 @@ func TestCookieBannerVersioning_NoOpUpdates(t *testing.T) {
|
||||
`
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"cookieCategoryId": categoryID,
|
||||
@@ -342,6 +346,7 @@ func TestCookieBannerVersioning_NoOpUpdates(t *testing.T) {
|
||||
`
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"trackerPatternId": patternID,
|
||||
@@ -424,6 +429,7 @@ func TestCookieBannerVersioning_ExcludedPattern(t *testing.T) {
|
||||
`
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{"trackerPatternId": patternID},
|
||||
}, &result)
|
||||
@@ -456,6 +462,7 @@ func TestCookieBannerVersioning_ExcludedPattern(t *testing.T) {
|
||||
`
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"trackerPatternId": patternID,
|
||||
@@ -531,6 +538,7 @@ func reportDetectedCookies(t *testing.T, c *testutil.Client, bannerID string, na
|
||||
Name string `json:"name"`
|
||||
Source string `json:"source"`
|
||||
}
|
||||
|
||||
cookies := make([]entry, len(names))
|
||||
for i, n := range names {
|
||||
cookies[i] = entry{Name: n, Source: "script"}
|
||||
@@ -542,7 +550,9 @@ func reportDetectedCookies(t *testing.T, c *testutil.Client, bannerID string, na
|
||||
endpoint := fmt.Sprintf("%s/api/cookie-banner/v1/%s/report", c.BaseURL(), bannerID)
|
||||
resp, err := c.HTTPClient().Post(endpoint, "application/json", bytes.NewReader(body))
|
||||
require.NoError(t, err)
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
require.Equal(t, http.StatusNoContent, resp.StatusCode,
|
||||
"report endpoint should return 204")
|
||||
}
|
||||
@@ -584,7 +594,9 @@ func TestCookieBannerVersioning_RealChangesStillBumpVersion(t *testing.T) {
|
||||
updateCookieBanner(input: $input) { cookieBanner { id } }
|
||||
}
|
||||
`
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"cookieBannerId": bannerID,
|
||||
@@ -617,7 +629,9 @@ func TestCookieBannerVersioning_RealChangesStillBumpVersion(t *testing.T) {
|
||||
updateTrackerPattern(input: $input) { trackerPattern { id } }
|
||||
}
|
||||
`
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"trackerPatternId": patternID,
|
||||
|
||||
@@ -89,6 +89,7 @@ func TestCookieCategory_Create(t *testing.T) {
|
||||
}, &result)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
node := result.CreateCookieCategory.CookieCategoryEdge.Node
|
||||
assert.NotEmpty(t, node.ID)
|
||||
assert.Equal(t, "Marketing", node.Name)
|
||||
@@ -343,12 +344,14 @@ func TestCookieCategory_Delete(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var necessaryCategoryID string
|
||||
|
||||
for _, e := range listResult.Node.ConsentCategories.Edges {
|
||||
if e.Node.Kind == "NECESSARY" {
|
||||
necessaryCategoryID = e.Node.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
require.NotEmpty(t, necessaryCategoryID, "should find a NECESSARY category")
|
||||
|
||||
_, err = owner.Do(`
|
||||
|
||||
@@ -242,6 +242,7 @@ func TestDatum_PublishDataList(t *testing.T) {
|
||||
|
||||
ver1Major := result1.PublishDataList.DocumentVersionEdge.Node.Major
|
||||
ver2Major := result2.PublishDataList.DocumentVersionEdge.Node.Major
|
||||
|
||||
assert.Equal(t, 1, ver1Major)
|
||||
assert.Equal(t, 2, ver2Major)
|
||||
},
|
||||
|
||||
@@ -249,9 +249,11 @@ func TestDatum_Create_Validation(t *testing.T) {
|
||||
if !tt.skipOrganization {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
|
||||
if !tt.skipOwner {
|
||||
input["ownerId"] = profileID
|
||||
}
|
||||
|
||||
maps.Copy(input, tt.input)
|
||||
|
||||
_, err := owner.Do(query, map[string]any{"input": input})
|
||||
@@ -348,6 +350,7 @@ func TestDatum_Update(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
datum := result.UpdateDatum.Datum
|
||||
|
||||
switch tt.assertField {
|
||||
case "name":
|
||||
assert.Equal(t, tt.assertValue, datum.Name)
|
||||
@@ -1159,6 +1162,7 @@ func TestDatum_Pagination(t *testing.T) {
|
||||
assert.GreaterOrEqual(t, result.Node.Data.TotalCount, 5)
|
||||
|
||||
testutil.AssertHasMorePages(t, result.Node.Data.PageInfo)
|
||||
|
||||
queryAfter := `
|
||||
query($id: ID!, $after: CursorKey) {
|
||||
node(id: $id) {
|
||||
@@ -1343,7 +1347,6 @@ func TestDatum_TenantIsolation(t *testing.T) {
|
||||
err := org2Owner.Execute(query, map[string]any{
|
||||
"id": org1Owner.GetOrganizationID().String(),
|
||||
}, &result)
|
||||
|
||||
if err == nil {
|
||||
for _, edge := range result.Node.Data.Edges {
|
||||
assert.NotEqual(t, datumID, edge.Node.ID, "Should not see datum from another org")
|
||||
@@ -1404,6 +1407,7 @@ func TestDatum_Ordering(t *testing.T) {
|
||||
for i, edge := range result.Node.Data.Edges {
|
||||
times[i] = edge.Node.CreatedAt
|
||||
}
|
||||
|
||||
testutil.AssertTimesOrderedDescending(t, times, "createdAt")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -276,6 +276,7 @@ func TestDocument_Create_Validation(t *testing.T) {
|
||||
if !tt.skipOrganization {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
|
||||
maps.Copy(input, tt.input)
|
||||
|
||||
_, err := owner.Do(query, map[string]any{"input": input})
|
||||
@@ -1111,6 +1112,7 @@ func TestDocument_Pagination(t *testing.T) {
|
||||
assert.GreaterOrEqual(t, result.Node.Documents.TotalCount, 5)
|
||||
|
||||
testutil.AssertHasMorePages(t, result.Node.Documents.PageInfo)
|
||||
|
||||
queryAfter := `
|
||||
query($id: ID!, $after: CursorKey) {
|
||||
node(id: $id) {
|
||||
@@ -1288,7 +1290,6 @@ func TestDocument_TenantIsolation(t *testing.T) {
|
||||
err := org2Owner.Execute(query, map[string]any{
|
||||
"id": org1Owner.GetOrganizationID().String(),
|
||||
}, &result)
|
||||
|
||||
if err == nil {
|
||||
for _, edge := range result.Node.Documents.Edges {
|
||||
assert.NotEqual(t, documentID, edge.Node.ID, "Should not see document from another org")
|
||||
@@ -1348,6 +1349,7 @@ func TestDocument_Ordering(t *testing.T) {
|
||||
for i, edge := range result.Node.Documents.Edges {
|
||||
times[i] = edge.Node.CreatedAt
|
||||
}
|
||||
|
||||
testutil.AssertTimesOrderedDescending(t, times, "createdAt")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ func createTestDocument(t *testing.T, owner *testutil.Client) (docID string, doc
|
||||
if len(result.CreateDocument.DocumentEdge.Node.Versions.Edges) > 0 {
|
||||
docVersionID = result.CreateDocument.DocumentEdge.Node.Versions.Edges[0].Node.ID
|
||||
}
|
||||
|
||||
return docID, docVersionID
|
||||
}
|
||||
|
||||
@@ -502,6 +503,7 @@ func TestDocumentVersion_BulkPublish(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 2, len(result.BulkPublishDocuments.DocumentVersions))
|
||||
|
||||
for _, dv := range result.BulkPublishDocuments.DocumentVersions {
|
||||
assert.Equal(t, "PUBLISHED", dv.Status)
|
||||
}
|
||||
@@ -720,6 +722,7 @@ func TestDocumentVersion_BulkRequestSignatures(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 2, len(result.BulkRequestSignatures.DocumentVersionSignatureEdges))
|
||||
|
||||
for _, edge := range result.BulkRequestSignatures.DocumentVersionSignatureEdges {
|
||||
assert.Equal(t, "REQUESTED", edge.Node.State)
|
||||
}
|
||||
@@ -1028,6 +1031,7 @@ func TestDocumentVersion_VoidApproval(t *testing.T) {
|
||||
require.NotEmpty(t, quorumResult.Node.Versions.Edges[0].Node.ApprovalQuorums.Edges)
|
||||
decisions := quorumResult.Node.Versions.Edges[0].Node.ApprovalQuorums.Edges[0].Node.Decisions.Edges
|
||||
require.NotEmpty(t, decisions)
|
||||
|
||||
for _, d := range decisions {
|
||||
assert.Equal(t, "VOIDED", d.Node.State, "decisions should be VOIDED after voiding")
|
||||
}
|
||||
@@ -1382,6 +1386,7 @@ func TestDocumentVersion_DeleteDraft(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var updateResult struct {
|
||||
UpdateDocument struct {
|
||||
Document struct {
|
||||
@@ -1393,6 +1398,7 @@ func TestDocumentVersion_DeleteDraft(t *testing.T) {
|
||||
} `json:"documentVersion"`
|
||||
} `json:"updateDocument"`
|
||||
}
|
||||
|
||||
err := owner.Execute(updateQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": docID,
|
||||
@@ -1411,6 +1417,7 @@ func TestDocumentVersion_DeleteDraft(t *testing.T) {
|
||||
} `json:"document"`
|
||||
} `json:"deleteDocumentDraft"`
|
||||
}
|
||||
|
||||
err = owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{"documentId": docID},
|
||||
}, &result)
|
||||
@@ -1427,6 +1434,7 @@ func TestDocumentVersion_DeleteDraft(t *testing.T) {
|
||||
docID, _ := createTestDocument(t, owner)
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{"documentId": docID},
|
||||
}, &result)
|
||||
@@ -1443,6 +1451,7 @@ func TestDocumentVersion_DeleteDraft(t *testing.T) {
|
||||
approveTestDocument(t, owner, docID)
|
||||
|
||||
var result struct{}
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{"documentId": docID},
|
||||
}, &result)
|
||||
@@ -1469,6 +1478,7 @@ func TestDocumentVersion_DeleteDraft(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var updateResult struct {
|
||||
UpdateDocument struct {
|
||||
Document struct {
|
||||
@@ -1479,6 +1489,7 @@ func TestDocumentVersion_DeleteDraft(t *testing.T) {
|
||||
} `json:"documentVersion"`
|
||||
} `json:"updateDocument"`
|
||||
}
|
||||
|
||||
err := owner.Execute(updateQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": docID,
|
||||
@@ -1488,6 +1499,7 @@ func TestDocumentVersion_DeleteDraft(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var result struct{}
|
||||
|
||||
err = viewer.Execute(query, map[string]any{
|
||||
"input": map[string]any{"documentId": docID},
|
||||
}, &result)
|
||||
|
||||
@@ -505,12 +505,14 @@ func TestEmployeeDocument_FilterModeIsolation(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var found bool
|
||||
|
||||
for _, edge := range result.Viewer.SignableDocuments.Edges {
|
||||
if edge.Node.ID == docID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert.True(t, found, "signer should see document in signableDocuments list")
|
||||
})
|
||||
|
||||
@@ -613,12 +615,14 @@ func TestEmployeeDocument_ApproverFilterModeIsolation(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var found bool
|
||||
|
||||
for _, edge := range result.Viewer.ApprovableDocuments.Edges {
|
||||
if edge.Node.ID == docID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert.True(t, found, "approver should see document in approvableDocuments list")
|
||||
})
|
||||
|
||||
|
||||
@@ -237,6 +237,7 @@ func TestFinding_PublishFindingList(t *testing.T) {
|
||||
|
||||
ver1Major := result1.PublishFindingList.DocumentVersionEdge.Node.Major
|
||||
ver2Major := result2.PublishFindingList.DocumentVersionEdge.Node.Major
|
||||
|
||||
assert.Equal(t, 1, ver1Major)
|
||||
assert.Equal(t, 2, ver2Major)
|
||||
},
|
||||
|
||||
@@ -186,6 +186,7 @@ func TestFinding_Update(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
findingID := createResult.CreateFinding.FindingEdge.Node.ID
|
||||
|
||||
query := `
|
||||
@@ -274,6 +275,7 @@ func TestFinding_Delete(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
findingID := createResult.CreateFinding.FindingEdge.Node.ID
|
||||
|
||||
query := `
|
||||
@@ -510,6 +512,7 @@ func TestFinding_CreateAuditMapping(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
findingID := createResult.CreateFinding.FindingEdge.Node.ID
|
||||
|
||||
// Link finding to audit
|
||||
@@ -635,6 +638,7 @@ func TestFinding_DeleteAuditMapping(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
findingID := createResult.CreateFinding.FindingEdge.Node.ID
|
||||
|
||||
// Link finding to audit
|
||||
@@ -753,6 +757,7 @@ func TestFinding_StatusAndPriorityValues(t *testing.T) {
|
||||
"status values",
|
||||
func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
riskID := factory.CreateRisk(owner)
|
||||
statuses := []string{"OPEN", "IN_PROGRESS", "CLOSED", "RISK_ACCEPTED", "MITIGATED", "FALSE_POSITIVE"}
|
||||
|
||||
@@ -761,6 +766,7 @@ func TestFinding_StatusAndPriorityValues(t *testing.T) {
|
||||
status,
|
||||
func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var result struct {
|
||||
CreateFinding struct {
|
||||
FindingEdge struct {
|
||||
@@ -799,6 +805,7 @@ func TestFinding_StatusAndPriorityValues(t *testing.T) {
|
||||
"priority values",
|
||||
func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
priorities := []string{"LOW", "MEDIUM", "HIGH"}
|
||||
|
||||
for _, priority := range priorities {
|
||||
@@ -806,6 +813,7 @@ func TestFinding_StatusAndPriorityValues(t *testing.T) {
|
||||
priority,
|
||||
func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var result struct {
|
||||
CreateFinding struct {
|
||||
FindingEdge struct {
|
||||
|
||||
@@ -215,6 +215,7 @@ func TestFramework_Create_Validation(t *testing.T) {
|
||||
if !tt.skipOrganization {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
|
||||
maps.Copy(input, tt.input)
|
||||
|
||||
_, err := owner.Do(query, map[string]any{"input": input})
|
||||
@@ -301,6 +302,7 @@ func TestFramework_Update(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
framework := result.UpdateFramework.Framework
|
||||
|
||||
switch tt.assertField {
|
||||
case "name":
|
||||
assert.Equal(t, tt.assertValue, framework.Name)
|
||||
@@ -637,6 +639,7 @@ func TestFramework_Timestamps(t *testing.T) {
|
||||
|
||||
t.Run("updatedAt changes on update", func(t *testing.T) {
|
||||
t.Skip("Skipped: server may not update timestamp immediately or has caching")
|
||||
|
||||
frameworkID := factory.NewFramework(owner).WithName("Timestamp Update Test").Create()
|
||||
|
||||
getQuery := `
|
||||
@@ -1216,6 +1219,7 @@ func TestFramework_SubResolvers_WithData(t *testing.T) {
|
||||
for i, edge := range result.Node.Controls.Edges {
|
||||
controlIDs[i] = edge.Node.ID
|
||||
}
|
||||
|
||||
assert.Contains(t, controlIDs, control1ID)
|
||||
assert.Contains(t, controlIDs, control2ID)
|
||||
})
|
||||
@@ -1281,6 +1285,7 @@ func TestFramework_Pagination(t *testing.T) {
|
||||
assert.GreaterOrEqual(t, result.Node.Frameworks.TotalCount, 5)
|
||||
|
||||
testutil.AssertHasMorePages(t, result.Node.Frameworks.PageInfo)
|
||||
|
||||
queryAfter := `
|
||||
query($id: ID!, $after: CursorKey) {
|
||||
node(id: $id) {
|
||||
@@ -1464,7 +1469,6 @@ func TestFramework_TenantIsolation(t *testing.T) {
|
||||
err := org2Owner.Execute(query, map[string]any{
|
||||
"id": org1Owner.GetOrganizationID().String(),
|
||||
}, &result)
|
||||
|
||||
if err == nil {
|
||||
for _, edge := range result.Node.Frameworks.Edges {
|
||||
assert.NotEqual(t, frameworkID, edge.Node.ID, "Should not see framework from another org")
|
||||
@@ -1524,6 +1528,7 @@ func TestFramework_Ordering(t *testing.T) {
|
||||
for i, edge := range result.Node.Frameworks.Edges {
|
||||
times[i] = edge.Node.CreatedAt
|
||||
}
|
||||
|
||||
testutil.AssertTimesOrderedDescending(t, times, "createdAt")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -23,7 +23,9 @@ import (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testutil.Setup()
|
||||
|
||||
code := m.Run()
|
||||
|
||||
testutil.Teardown()
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ func TestControlMeasureMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"frameworkEdge"`
|
||||
} `json:"createFramework"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateFrameworkInput!) {
|
||||
createFramework(input: $input) {
|
||||
@@ -54,6 +55,7 @@ func TestControlMeasureMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createFrameworkResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
frameworkID := createFrameworkResult.CreateFramework.FrameworkEdge.Node.ID
|
||||
|
||||
// Create a control
|
||||
@@ -66,6 +68,7 @@ func TestControlMeasureMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"controlEdge"`
|
||||
} `json:"createControl"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateControlInput!) {
|
||||
createControl(input: $input) {
|
||||
@@ -87,6 +90,7 @@ func TestControlMeasureMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createControlResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
controlID := createControlResult.CreateControl.ControlEdge.Node.ID
|
||||
|
||||
// Create a measure
|
||||
@@ -99,6 +103,7 @@ func TestControlMeasureMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"measureEdge"`
|
||||
} `json:"createMeasure"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateMeasureInput!) {
|
||||
createMeasure(input: $input) {
|
||||
@@ -117,6 +122,7 @@ func TestControlMeasureMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createMeasureResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
measureID := createMeasureResult.CreateMeasure.MeasureEdge.Node.ID
|
||||
|
||||
t.Run("create mapping", func(t *testing.T) {
|
||||
@@ -134,6 +140,7 @@ func TestControlMeasureMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"measureEdge"`
|
||||
} `json:"createControlMeasureMapping"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateControlMeasureMappingInput!) {
|
||||
createControlMeasureMapping(input: $input) {
|
||||
@@ -192,6 +199,7 @@ func TestRiskMeasureMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"riskEdge"`
|
||||
} `json:"createRisk"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateRiskInput!) {
|
||||
createRisk(input: $input) {
|
||||
@@ -213,6 +221,7 @@ func TestRiskMeasureMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createRiskResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
riskID := createRiskResult.CreateRisk.RiskEdge.Node.ID
|
||||
|
||||
// Create a measure
|
||||
@@ -225,6 +234,7 @@ func TestRiskMeasureMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"measureEdge"`
|
||||
} `json:"createMeasure"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateMeasureInput!) {
|
||||
createMeasure(input: $input) {
|
||||
@@ -243,6 +253,7 @@ func TestRiskMeasureMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createMeasureResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
measureID := createMeasureResult.CreateMeasure.MeasureEdge.Node.ID
|
||||
|
||||
t.Run("create mapping", func(t *testing.T) {
|
||||
@@ -260,6 +271,7 @@ func TestRiskMeasureMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"measureEdge"`
|
||||
} `json:"createRiskMeasureMapping"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateRiskMeasureMappingInput!) {
|
||||
createRiskMeasureMapping(input: $input) {
|
||||
@@ -318,6 +330,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"frameworkEdge"`
|
||||
} `json:"createFramework"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateFrameworkInput!) {
|
||||
createFramework(input: $input) {
|
||||
@@ -335,6 +348,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createFrameworkResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
frameworkID := createFrameworkResult.CreateFramework.FrameworkEdge.Node.ID
|
||||
|
||||
var createControlResult struct {
|
||||
@@ -346,6 +360,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"controlEdge"`
|
||||
} `json:"createControl"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateControlInput!) {
|
||||
createControl(input: $input) {
|
||||
@@ -367,6 +382,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createControlResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
controlID := createControlResult.CreateControl.ControlEdge.Node.ID
|
||||
|
||||
// Create a document
|
||||
@@ -379,6 +395,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"documentEdge"`
|
||||
} `json:"createDocument"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateDocumentInput!) {
|
||||
createDocument(input: $input) {
|
||||
@@ -399,6 +416,7 @@ func TestControlDocumentMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createDocumentResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
documentID := createDocumentResult.CreateDocument.DocumentEdge.Node.ID
|
||||
|
||||
t.Run("create mapping", func(t *testing.T) {
|
||||
@@ -458,6 +476,7 @@ func TestControlAuditMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"frameworkEdge"`
|
||||
} `json:"createFramework"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateFrameworkInput!) {
|
||||
createFramework(input: $input) {
|
||||
@@ -475,6 +494,7 @@ func TestControlAuditMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createFrameworkResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
frameworkID := createFrameworkResult.CreateFramework.FrameworkEdge.Node.ID
|
||||
|
||||
var createControlResult struct {
|
||||
@@ -486,6 +506,7 @@ func TestControlAuditMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"controlEdge"`
|
||||
} `json:"createControl"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateControlInput!) {
|
||||
createControl(input: $input) {
|
||||
@@ -507,6 +528,7 @@ func TestControlAuditMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createControlResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
controlID := createControlResult.CreateControl.ControlEdge.Node.ID
|
||||
|
||||
// Create an audit
|
||||
@@ -519,6 +541,7 @@ func TestControlAuditMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"auditEdge"`
|
||||
} `json:"createAudit"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateAuditInput!) {
|
||||
createAudit(input: $input) {
|
||||
@@ -537,6 +560,7 @@ func TestControlAuditMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createAuditResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
auditID := createAuditResult.CreateAudit.AuditEdge.Node.ID
|
||||
|
||||
t.Run("create mapping", func(t *testing.T) {
|
||||
@@ -596,6 +620,7 @@ func TestRiskDocumentMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"riskEdge"`
|
||||
} `json:"createRisk"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateRiskInput!) {
|
||||
createRisk(input: $input) {
|
||||
@@ -617,6 +642,7 @@ func TestRiskDocumentMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createRiskResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
riskID := createRiskResult.CreateRisk.RiskEdge.Node.ID
|
||||
|
||||
// Create a document
|
||||
@@ -629,6 +655,7 @@ func TestRiskDocumentMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"documentEdge"`
|
||||
} `json:"createDocument"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateDocumentInput!) {
|
||||
createDocument(input: $input) {
|
||||
@@ -649,6 +676,7 @@ func TestRiskDocumentMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createDocumentResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
documentID := createDocumentResult.CreateDocument.DocumentEdge.Node.ID
|
||||
|
||||
t.Run("create mapping", func(t *testing.T) {
|
||||
@@ -708,6 +736,7 @@ func TestRiskObligationMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"riskEdge"`
|
||||
} `json:"createRisk"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateRiskInput!) {
|
||||
createRisk(input: $input) {
|
||||
@@ -729,10 +758,12 @@ func TestRiskObligationMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createRiskResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
riskID := createRiskResult.CreateRisk.RiskEdge.Node.ID
|
||||
|
||||
// Create an obligation
|
||||
profileID := factory.CreateUser(owner)
|
||||
|
||||
var createObligationResult struct {
|
||||
CreateObligation struct {
|
||||
ObligationEdge struct {
|
||||
@@ -742,6 +773,7 @@ func TestRiskObligationMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"obligationEdge"`
|
||||
} `json:"createObligation"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateObligationInput!) {
|
||||
createObligation(input: $input) {
|
||||
@@ -763,6 +795,7 @@ func TestRiskObligationMapping_CreateDelete(t *testing.T) {
|
||||
},
|
||||
}, &createObligationResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
obligationID := createObligationResult.CreateObligation.ObligationEdge.Node.ID
|
||||
|
||||
t.Run("create mapping", func(t *testing.T) {
|
||||
@@ -815,6 +848,7 @@ func TestMeasureDocumentMapping_CreateDelete(t *testing.T) {
|
||||
|
||||
t.Run("create mapping", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
documentID := factory.NewDocument(owner).Create()
|
||||
|
||||
var result struct {
|
||||
@@ -831,6 +865,7 @@ func TestMeasureDocumentMapping_CreateDelete(t *testing.T) {
|
||||
} `json:"documentEdge"`
|
||||
} `json:"createMeasureDocumentMapping"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateMeasureDocumentMappingInput!) {
|
||||
createMeasureDocumentMapping(input: $input) {
|
||||
@@ -859,6 +894,7 @@ func TestMeasureDocumentMapping_CreateDelete(t *testing.T) {
|
||||
|
||||
t.Run("delete mapping", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
documentID := factory.NewDocument(owner).Create()
|
||||
|
||||
// Create the mapping first
|
||||
|
||||
@@ -300,6 +300,7 @@ func TestMeasure_Create_Validation(t *testing.T) {
|
||||
if !tt.skipOrganization {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
|
||||
maps.Copy(input, tt.input)
|
||||
|
||||
_, err := owner.Do(query, map[string]any{"input": input})
|
||||
@@ -403,6 +404,7 @@ func TestMeasure_Update(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
measure := result.UpdateMeasure.Measure
|
||||
|
||||
switch tt.assertField {
|
||||
case "name":
|
||||
assert.Equal(t, tt.assertValue, measure.Name)
|
||||
@@ -1349,6 +1351,7 @@ func TestMeasure_SubResolvers_WithData(t *testing.T) {
|
||||
for i, edge := range result.Node.Tasks.Edges {
|
||||
taskIDs[i] = edge.Node.ID
|
||||
}
|
||||
|
||||
assert.Contains(t, taskIDs, task1ID)
|
||||
assert.Contains(t, taskIDs, task2ID)
|
||||
})
|
||||
@@ -1543,6 +1546,7 @@ func TestMeasure_Pagination(t *testing.T) {
|
||||
|
||||
// Get next page using cursor
|
||||
testutil.AssertHasMorePages(t, result.Node.Measures.PageInfo)
|
||||
|
||||
queryAfter := `
|
||||
query($id: ID!, $after: CursorKey) {
|
||||
node(id: $id) {
|
||||
@@ -1698,12 +1702,14 @@ func TestMeasure_Filtering(t *testing.T) {
|
||||
|
||||
// Should contain our implemented measure
|
||||
found := false
|
||||
|
||||
for _, edge := range result.Node.Measures.Edges {
|
||||
if edge.Node.ID == measure1ID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert.True(t, found, "Expected to find implemented measure in filtered results")
|
||||
})
|
||||
|
||||
@@ -1749,6 +1755,7 @@ func TestMeasure_Filtering(t *testing.T) {
|
||||
for i, edge := range result.Node.Measures.Edges {
|
||||
foundIDs[i] = edge.Node.ID
|
||||
}
|
||||
|
||||
assert.Contains(t, foundIDs, measure1ID)
|
||||
assert.Contains(t, foundIDs, measure2ID)
|
||||
})
|
||||
@@ -1804,17 +1811,20 @@ func TestMeasure_FilterByCategory(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.GreaterOrEqual(t, result.Node.Measures.TotalCount, 1)
|
||||
|
||||
for _, edge := range result.Node.Measures.Edges {
|
||||
assert.Equal(t, "POLICY", edge.Node.Category)
|
||||
}
|
||||
|
||||
found := false
|
||||
|
||||
for _, edge := range result.Node.Measures.Edges {
|
||||
if edge.Node.ID == policyID {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert.True(t, found, "Expected to find POLICY measure in filtered results")
|
||||
})
|
||||
|
||||
@@ -2127,6 +2137,7 @@ func TestMeasure_Ordering(t *testing.T) {
|
||||
for i, edge := range result.Node.Measures.Edges {
|
||||
names[i] = edge.Node.Name
|
||||
}
|
||||
|
||||
testutil.AssertOrderedAscending(t, names, "name")
|
||||
})
|
||||
|
||||
@@ -2175,6 +2186,7 @@ func TestMeasure_Ordering(t *testing.T) {
|
||||
for i, edge := range result.Node.Measures.Edges {
|
||||
names[i] = edge.Node.Name
|
||||
}
|
||||
|
||||
testutil.AssertOrderedDescending(t, names, "name")
|
||||
})
|
||||
|
||||
@@ -2223,6 +2235,7 @@ func TestMeasure_Ordering(t *testing.T) {
|
||||
for i, edge := range result.Node.Measures.Edges {
|
||||
times[i] = edge.Node.CreatedAt
|
||||
}
|
||||
|
||||
testutil.AssertTimesOrderedDescending(t, times, "createdAt")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -314,6 +314,7 @@ func TestOAuth2_AuthorizationCodeFlow(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -365,6 +366,7 @@ func TestOAuth2_AuthorizationCodeFlow(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -1564,6 +1566,7 @@ func TestOAuth2_Security(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -1617,6 +1620,7 @@ func TestOAuth2_Security(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var redirectLoc string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -1696,6 +1700,7 @@ func TestOAuth2_Security(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -1822,6 +1827,7 @@ func TestOAuth2_Security(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
_, challenge2 := testutil.GeneratePKCE()
|
||||
|
||||
params.Set("state", "consent-second")
|
||||
params.Set("code_challenge", challenge2)
|
||||
|
||||
@@ -1862,6 +1868,7 @@ func TestOAuth2_Security(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -2003,12 +2010,14 @@ func TestOAuth2_Security(t *testing.T) {
|
||||
require.NotNil(t, jwks)
|
||||
|
||||
var matchingKey map[string]any
|
||||
|
||||
for _, k := range jwks.Keys {
|
||||
if kid, ok := k["kid"].(string); ok && kid == header.Kid {
|
||||
matchingKey = k
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
require.NotNil(t, matchingKey, "JWKS must contain key matching kid=%s", header.Kid)
|
||||
|
||||
// Reconstruct the RSA public key from JWK.
|
||||
@@ -2157,6 +2166,7 @@ func TestOAuth2_Security(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -2222,6 +2232,7 @@ func TestOAuth2_ClientSecretPost(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -2309,6 +2320,7 @@ func TestOAuth2_PublicClientAuthCodeFlow(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -2486,6 +2498,7 @@ func TestOAuth2_IDTokenClaims(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -2585,6 +2598,7 @@ func TestOAuth2_CacheHeaders(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -2825,6 +2839,7 @@ func TestOAuth2_Expiry(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -3010,6 +3025,7 @@ func TestOAuth2_OfflineAccessScope(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -3065,6 +3081,7 @@ func TestOAuth2_OfflineAccessScope(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
@@ -3470,6 +3487,7 @@ func TestOAuth2_AuthorizationCodeReplayRevokesTokens(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if testutil.IsConsentRedirect(authResp) {
|
||||
consentID, err := testutil.ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -237,6 +237,7 @@ func TestObligation_PublishObligationList(t *testing.T) {
|
||||
|
||||
ver1Major := result1.PublishObligationList.DocumentVersionEdge.Node.Major
|
||||
ver2Major := result2.PublishObligationList.DocumentVersionEdge.Node.Major
|
||||
|
||||
assert.Equal(t, 1, ver1Major)
|
||||
assert.Equal(t, 2, ver2Major)
|
||||
},
|
||||
|
||||
@@ -192,6 +192,7 @@ func TestProcessingActivity_Create_Validation(t *testing.T) {
|
||||
if !tt.skipOrganization {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
|
||||
maps.Copy(input, tt.input)
|
||||
|
||||
_, err := owner.Do(query, map[string]any{"input": input})
|
||||
@@ -290,6 +291,7 @@ func TestProcessingActivity_Update(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
pa := result.UpdateProcessingActivity.ProcessingActivity
|
||||
|
||||
switch tt.assertField {
|
||||
case "name":
|
||||
assert.Equal(t, tt.assertValue, pa.Name)
|
||||
@@ -954,6 +956,7 @@ func TestProcessingActivity_Pagination(t *testing.T) {
|
||||
assert.GreaterOrEqual(t, result.Node.ProcessingActivities.TotalCount, 5)
|
||||
|
||||
testutil.AssertHasMorePages(t, result.Node.ProcessingActivities.PageInfo)
|
||||
|
||||
queryAfter := `
|
||||
query($id: ID!, $after: CursorKey) {
|
||||
node(id: $id) {
|
||||
@@ -1137,7 +1140,6 @@ func TestProcessingActivity_TenantIsolation(t *testing.T) {
|
||||
err := org2Owner.Execute(query, map[string]any{
|
||||
"id": org1Owner.GetOrganizationID().String(),
|
||||
}, &result)
|
||||
|
||||
if err == nil {
|
||||
for _, edge := range result.Node.ProcessingActivities.Edges {
|
||||
assert.NotEqual(t, paID, edge.Node.ID, "Should not see processing activity from another org")
|
||||
@@ -1197,6 +1199,7 @@ func TestProcessingActivity_Ordering(t *testing.T) {
|
||||
for i, edge := range result.Node.ProcessingActivities.Edges {
|
||||
times[i] = edge.Node.CreatedAt
|
||||
}
|
||||
|
||||
testutil.AssertTimesOrderedDescending(t, times, "createdAt")
|
||||
})
|
||||
}
|
||||
@@ -1533,6 +1536,7 @@ func TestProcessingActivity_DPIA(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var createResult struct {
|
||||
CreateDataProtectionImpactAssessment struct {
|
||||
DataProtectionImpactAssessment struct {
|
||||
@@ -1540,6 +1544,7 @@ func TestProcessingActivity_DPIA(t *testing.T) {
|
||||
} `json:"dataProtectionImpactAssessment"`
|
||||
} `json:"createDataProtectionImpactAssessment"`
|
||||
}
|
||||
|
||||
err := owner.Execute(createQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"processingActivityId": paID,
|
||||
@@ -1548,6 +1553,7 @@ func TestProcessingActivity_DPIA(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
dpiaID := createResult.CreateDataProtectionImpactAssessment.DataProtectionImpactAssessment.ID
|
||||
|
||||
updateQuery := `
|
||||
@@ -1596,6 +1602,7 @@ func TestProcessingActivity_DPIA(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var createResult struct {
|
||||
CreateDataProtectionImpactAssessment struct {
|
||||
DataProtectionImpactAssessment struct {
|
||||
@@ -1603,6 +1610,7 @@ func TestProcessingActivity_DPIA(t *testing.T) {
|
||||
} `json:"dataProtectionImpactAssessment"`
|
||||
} `json:"createDataProtectionImpactAssessment"`
|
||||
}
|
||||
|
||||
err := owner.Execute(createQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"processingActivityId": paID,
|
||||
@@ -1610,6 +1618,7 @@ func TestProcessingActivity_DPIA(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
dpiaID := createResult.CreateDataProtectionImpactAssessment.DataProtectionImpactAssessment.ID
|
||||
|
||||
deleteQuery := `
|
||||
@@ -1643,6 +1652,7 @@ func TestProcessingActivity_DPIA(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var readResult struct {
|
||||
Node struct {
|
||||
DataProtectionImpactAssessment *struct {
|
||||
@@ -1650,6 +1660,7 @@ func TestProcessingActivity_DPIA(t *testing.T) {
|
||||
} `json:"dataProtectionImpactAssessment"`
|
||||
} `json:"node"`
|
||||
}
|
||||
|
||||
err = owner.Execute(readQuery, map[string]any{"id": paID}, &readResult)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, readResult.Node.DataProtectionImpactAssessment)
|
||||
@@ -1816,6 +1827,7 @@ func TestProcessingActivity_TIA(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var createResult struct {
|
||||
CreateTransferImpactAssessment struct {
|
||||
TransferImpactAssessment struct {
|
||||
@@ -1823,6 +1835,7 @@ func TestProcessingActivity_TIA(t *testing.T) {
|
||||
} `json:"transferImpactAssessment"`
|
||||
} `json:"createTransferImpactAssessment"`
|
||||
}
|
||||
|
||||
err := owner.Execute(createQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"processingActivityId": paID,
|
||||
@@ -1831,6 +1844,7 @@ func TestProcessingActivity_TIA(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
tiaID := createResult.CreateTransferImpactAssessment.TransferImpactAssessment.ID
|
||||
|
||||
updateQuery := `
|
||||
@@ -1883,6 +1897,7 @@ func TestProcessingActivity_TIA(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var createResult struct {
|
||||
CreateTransferImpactAssessment struct {
|
||||
TransferImpactAssessment struct {
|
||||
@@ -1890,6 +1905,7 @@ func TestProcessingActivity_TIA(t *testing.T) {
|
||||
} `json:"transferImpactAssessment"`
|
||||
} `json:"createTransferImpactAssessment"`
|
||||
}
|
||||
|
||||
err := owner.Execute(createQuery, map[string]any{
|
||||
"input": map[string]any{
|
||||
"processingActivityId": paID,
|
||||
@@ -1897,6 +1913,7 @@ func TestProcessingActivity_TIA(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
tiaID := createResult.CreateTransferImpactAssessment.TransferImpactAssessment.ID
|
||||
|
||||
deleteQuery := `
|
||||
@@ -1930,6 +1947,7 @@ func TestProcessingActivity_TIA(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var readResult struct {
|
||||
Node struct {
|
||||
TransferImpactAssessment *struct {
|
||||
@@ -1937,6 +1955,7 @@ func TestProcessingActivity_TIA(t *testing.T) {
|
||||
} `json:"transferImpactAssessment"`
|
||||
} `json:"node"`
|
||||
}
|
||||
|
||||
err = owner.Execute(readQuery, map[string]any{"id": paID}, &readResult)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, readResult.Node.TransferImpactAssessment)
|
||||
@@ -1957,6 +1976,7 @@ func TestProcessingActivity_DPIA_RBAC(t *testing.T) {
|
||||
} `json:"dataProtectionImpactAssessment"`
|
||||
} `json:"createDataProtectionImpactAssessment"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateDataProtectionImpactAssessmentInput!) {
|
||||
createDataProtectionImpactAssessment(input: $input) {
|
||||
@@ -1970,6 +1990,7 @@ func TestProcessingActivity_DPIA_RBAC(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err, "owner should be able to create DPIA")
|
||||
|
||||
dpiaID := createResult.CreateDataProtectionImpactAssessment.DataProtectionImpactAssessment.ID
|
||||
|
||||
_, err = owner.Do(`
|
||||
@@ -2012,6 +2033,7 @@ func TestProcessingActivity_DPIA_RBAC(t *testing.T) {
|
||||
} `json:"dataProtectionImpactAssessment"`
|
||||
} `json:"createDataProtectionImpactAssessment"`
|
||||
}
|
||||
|
||||
err := admin.Execute(`
|
||||
mutation($input: CreateDataProtectionImpactAssessmentInput!) {
|
||||
createDataProtectionImpactAssessment(input: $input) {
|
||||
@@ -2025,6 +2047,7 @@ func TestProcessingActivity_DPIA_RBAC(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err, "admin should be able to create DPIA")
|
||||
|
||||
dpiaID := createResult.CreateDataProtectionImpactAssessment.DataProtectionImpactAssessment.ID
|
||||
|
||||
_, err = admin.Do(`
|
||||
@@ -2081,6 +2104,7 @@ func TestProcessingActivity_DPIA_RBAC(t *testing.T) {
|
||||
} `json:"dataProtectionImpactAssessment"`
|
||||
} `json:"createDataProtectionImpactAssessment"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateDataProtectionImpactAssessmentInput!) {
|
||||
createDataProtectionImpactAssessment(input: $input) {
|
||||
@@ -2094,6 +2118,7 @@ func TestProcessingActivity_DPIA_RBAC(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
dpiaID := createResult.CreateDataProtectionImpactAssessment.DataProtectionImpactAssessment.ID
|
||||
|
||||
_, err = viewer.Do(`
|
||||
@@ -2139,6 +2164,7 @@ func TestProcessingActivity_TIA_RBAC(t *testing.T) {
|
||||
} `json:"transferImpactAssessment"`
|
||||
} `json:"createTransferImpactAssessment"`
|
||||
}
|
||||
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateTransferImpactAssessmentInput!) {
|
||||
createTransferImpactAssessment(input: $input) {
|
||||
@@ -2152,6 +2178,7 @@ func TestProcessingActivity_TIA_RBAC(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err, "owner should be able to create TIA")
|
||||
|
||||
tiaID := createResult.CreateTransferImpactAssessment.TransferImpactAssessment.ID
|
||||
|
||||
_, err = owner.Do(`
|
||||
@@ -2194,6 +2221,7 @@ func TestProcessingActivity_TIA_RBAC(t *testing.T) {
|
||||
} `json:"transferImpactAssessment"`
|
||||
} `json:"createTransferImpactAssessment"`
|
||||
}
|
||||
|
||||
err := admin.Execute(`
|
||||
mutation($input: CreateTransferImpactAssessmentInput!) {
|
||||
createTransferImpactAssessment(input: $input) {
|
||||
@@ -2207,6 +2235,7 @@ func TestProcessingActivity_TIA_RBAC(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err, "admin should be able to create TIA")
|
||||
|
||||
tiaID := createResult.CreateTransferImpactAssessment.TransferImpactAssessment.ID
|
||||
|
||||
_, err = admin.Do(`
|
||||
@@ -2263,6 +2292,7 @@ func TestProcessingActivity_TIA_RBAC(t *testing.T) {
|
||||
} `json:"transferImpactAssessment"`
|
||||
} `json:"createTransferImpactAssessment"`
|
||||
}
|
||||
|
||||
err = owner.Execute(`
|
||||
mutation($input: CreateTransferImpactAssessmentInput!) {
|
||||
createTransferImpactAssessment(input: $input) {
|
||||
@@ -2276,6 +2306,7 @@ func TestProcessingActivity_TIA_RBAC(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
tiaID := createResult.CreateTransferImpactAssessment.TransferImpactAssessment.ID
|
||||
|
||||
_, err = viewer.Do(`
|
||||
|
||||
@@ -120,6 +120,7 @@ func TestRightsRequest_Update(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
rrID := createResult.CreateRightsRequest.RightsRequestEdge.Node.ID
|
||||
|
||||
query := `
|
||||
@@ -208,6 +209,7 @@ func TestRightsRequest_Delete(t *testing.T) {
|
||||
},
|
||||
}, &createResult)
|
||||
require.NoError(t, err)
|
||||
|
||||
rrID := createResult.CreateRightsRequest.RightsRequestEdge.Node.ID
|
||||
|
||||
query := `
|
||||
|
||||
@@ -402,6 +402,7 @@ func TestRisk_RequiredFields(t *testing.T) {
|
||||
if !tt.skipOrganization {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
|
||||
maps.Copy(input, tt.input)
|
||||
|
||||
_, err := owner.Do(query, map[string]any{"input": input})
|
||||
|
||||
@@ -112,9 +112,11 @@ func (sc *scimClient) doRequest(method, path string, payload any) (string, int)
|
||||
sc.t.Helper()
|
||||
|
||||
var body io.Reader
|
||||
|
||||
if payload != nil {
|
||||
data, err := json.Marshal(payload)
|
||||
require.NoError(sc.t, err)
|
||||
|
||||
body = bytes.NewReader(data)
|
||||
}
|
||||
|
||||
@@ -122,12 +124,14 @@ func (sc *scimClient) doRequest(method, path string, payload any) (string, int)
|
||||
require.NoError(sc.t, err)
|
||||
|
||||
req.Header.Set("Authorization", "Bearer "+sc.token)
|
||||
|
||||
if payload != nil {
|
||||
req.Header.Set("Content-Type", "application/scim+json")
|
||||
}
|
||||
|
||||
resp, err := sc.client.Do(req)
|
||||
require.NoError(sc.t, err)
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
@@ -269,6 +273,7 @@ func TestSCIM_Unauthorized(t *testing.T) {
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
assert.Equal(t, http.StatusUnauthorized, resp.StatusCode)
|
||||
|
||||
@@ -75,12 +75,12 @@ func TestStatementOfApplicability_Create(t *testing.T) {
|
||||
)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
node := result.CreateStatementOfApplicability.StatementOfApplicabilityEdge.Node
|
||||
assert.NotEmpty(t, node.ID)
|
||||
assert.Equal(t, name, node.Name)
|
||||
},
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
func TestStatementOfApplicability_CreateDocument(t *testing.T) {
|
||||
@@ -310,6 +310,7 @@ func TestStatementOfApplicability_CreateDocument(t *testing.T) {
|
||||
|
||||
ver1Major := result1.PublishStatementOfApplicability.DocumentVersionEdge.Node.Major
|
||||
ver2Major := result2.PublishStatementOfApplicability.DocumentVersionEdge.Node.Major
|
||||
|
||||
assert.Equal(t, 1, ver1Major)
|
||||
assert.Equal(t, 2, ver2Major)
|
||||
},
|
||||
@@ -533,6 +534,7 @@ func TestStatementOfApplicability_UpdateDocumentMetadata(t *testing.T) {
|
||||
documentID, publishedVersionID := publishSOADocument(t)
|
||||
|
||||
var result updateResult
|
||||
|
||||
err := owner.Execute(
|
||||
updateQuery,
|
||||
map[string]any{
|
||||
@@ -620,6 +622,7 @@ func TestStatementOfApplicability_UpdateDocumentMetadata(t *testing.T) {
|
||||
}
|
||||
|
||||
var firstPublish publishSOAResult
|
||||
|
||||
err := owner.Execute(
|
||||
publishSOAQuery,
|
||||
map[string]any{
|
||||
@@ -631,11 +634,13 @@ func TestStatementOfApplicability_UpdateDocumentMetadata(t *testing.T) {
|
||||
&firstPublish,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
documentID := firstPublish.PublishStatementOfApplicability.DocumentEdge.Node.ID
|
||||
require.Equal(t, "STATEMENT_OF_APPLICABILITY", firstPublish.PublishStatementOfApplicability.DocumentVersionEdge.Node.DocumentType)
|
||||
require.Equal(t, "CONFIDENTIAL", firstPublish.PublishStatementOfApplicability.DocumentVersionEdge.Node.Classification)
|
||||
|
||||
var editResult updateResult
|
||||
|
||||
err = owner.Execute(
|
||||
updateQuery,
|
||||
map[string]any{
|
||||
@@ -659,6 +664,7 @@ func TestStatementOfApplicability_UpdateDocumentMetadata(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
var publishDraft struct {
|
||||
PublishDocument struct {
|
||||
DocumentVersion struct {
|
||||
@@ -672,6 +678,7 @@ func TestStatementOfApplicability_UpdateDocumentMetadata(t *testing.T) {
|
||||
} `json:"documentVersion"`
|
||||
} `json:"publishDocument"`
|
||||
}
|
||||
|
||||
err = owner.Execute(
|
||||
publishDraftQuery,
|
||||
map[string]any{
|
||||
@@ -690,6 +697,7 @@ func TestStatementOfApplicability_UpdateDocumentMetadata(t *testing.T) {
|
||||
require.Equal(t, "INTERNAL", publishDraft.PublishDocument.DocumentVersion.Classification)
|
||||
|
||||
var rePublish publishSOAResult
|
||||
|
||||
err = owner.Execute(
|
||||
publishSOAQuery,
|
||||
map[string]any{
|
||||
@@ -701,6 +709,7 @@ func TestStatementOfApplicability_UpdateDocumentMetadata(t *testing.T) {
|
||||
&rePublish,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
node := rePublish.PublishStatementOfApplicability.DocumentVersionEdge.Node
|
||||
assert.Equal(t, "Custom SOA Name", node.Title, "re-publish should preserve edited title")
|
||||
assert.Equal(t, "POLICY", node.DocumentType, "re-publish should preserve edited type")
|
||||
|
||||
@@ -296,10 +296,12 @@ func TestTask_RequiredFields(t *testing.T) {
|
||||
if !tt.skipOrganization {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
|
||||
for k, v := range tt.input {
|
||||
if v == "placeholder" {
|
||||
continue // Skip placeholder values
|
||||
}
|
||||
|
||||
input[k] = v
|
||||
}
|
||||
|
||||
|
||||
@@ -341,6 +341,7 @@ func TestThirdParty_RequiredFields(t *testing.T) {
|
||||
if !tt.skipOrganization {
|
||||
input["organizationId"] = owner.GetOrganizationID().String()
|
||||
}
|
||||
|
||||
maps.Copy(input, tt.input)
|
||||
|
||||
_, err := owner.Do(query, map[string]any{"input": input})
|
||||
@@ -1020,6 +1021,7 @@ func TestThirdParty_Assess(t *testing.T) {
|
||||
thirdPartyID := factory.NewThirdParty(owner).WithName("Unconfigured assess").Create()
|
||||
|
||||
var result resultShape
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": thirdPartyID,
|
||||
@@ -1037,6 +1039,7 @@ func TestThirdParty_Assess(t *testing.T) {
|
||||
thirdPartyID := factory.NewThirdParty(owner).WithName("Admin-assessed thirdParty").Create()
|
||||
|
||||
var result resultShape
|
||||
|
||||
err := admin.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": thirdPartyID,
|
||||
@@ -1054,6 +1057,7 @@ func TestThirdParty_Assess(t *testing.T) {
|
||||
thirdPartyID := factory.NewThirdParty(owner).WithName("Viewer attempt").Create()
|
||||
|
||||
var result resultShape
|
||||
|
||||
err := viewer.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": thirdPartyID,
|
||||
@@ -1071,6 +1075,7 @@ func TestThirdParty_Assess(t *testing.T) {
|
||||
thirdPartyID := factory.NewThirdParty(org1Owner).WithName("Org1 thirdParty").Create()
|
||||
|
||||
var result resultShape
|
||||
|
||||
err := org2Owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": thirdPartyID,
|
||||
@@ -1087,6 +1092,7 @@ func TestThirdParty_Assess(t *testing.T) {
|
||||
thirdPartyID := factory.NewThirdParty(owner).WithName("Procedure test").Create()
|
||||
|
||||
var result resultShape
|
||||
|
||||
err := owner.Execute(query, map[string]any{
|
||||
"input": map[string]any{
|
||||
"id": thirdPartyID,
|
||||
|
||||
@@ -91,6 +91,7 @@ func TestTrackerPattern_Create(t *testing.T) {
|
||||
}, &result)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
node := result.CreateTrackerPattern.TrackerPatternEdge.Node
|
||||
assert.NotEmpty(t, node.ID)
|
||||
assert.Equal(t, "_ga", node.Pattern)
|
||||
@@ -151,6 +152,7 @@ func TestTrackerPattern_Create(t *testing.T) {
|
||||
}, &result)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
node := result.CreateTrackerPattern.TrackerPatternEdge.Node
|
||||
assert.Equal(t, "_gat_*", node.Pattern)
|
||||
assert.Equal(t, "GLOB", node.MatchType)
|
||||
|
||||
@@ -85,6 +85,7 @@ func TestTrackerResource_Create(t *testing.T) {
|
||||
}, &result)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
node := result.CreateTrackerResource.TrackerResourceEdge.Node
|
||||
assert.NotEmpty(t, node.ID)
|
||||
assert.Equal(t, "SCRIPT", node.Type)
|
||||
|
||||
@@ -71,12 +71,14 @@ func TestUser_UpdateMembership(t *testing.T) {
|
||||
|
||||
// Find the admin
|
||||
var adminMembershipID string
|
||||
|
||||
for _, edge := range result.Node.Profiles.Edges {
|
||||
if edge.Node.Membership.Role == "ADMIN" {
|
||||
adminMembershipID = edge.Node.Membership.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
require.NotEmpty(t, adminMembershipID, "Should find admin member")
|
||||
|
||||
// Update the member role to VIEWER
|
||||
@@ -162,12 +164,14 @@ func TestUser_RemoveUser(t *testing.T) {
|
||||
|
||||
// Find a viewer user to remove
|
||||
var userID string
|
||||
|
||||
for _, edge := range result.Node.Profiles.Edges {
|
||||
if edge.Node.Membership.Role == "VIEWER" {
|
||||
userID = edge.Node.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert.NotEmpty(t, userID, "Should find viewer member")
|
||||
|
||||
// Remove the member
|
||||
@@ -251,12 +255,14 @@ func TestUser_RemoveOwner(t *testing.T) {
|
||||
|
||||
// Find the other owner (not the calling owner)
|
||||
var targetProfileID string
|
||||
|
||||
for _, edge := range result.Node.Profiles.Edges {
|
||||
if edge.Node.Membership.Role == "OWNER" && edge.Node.Identity.ID != owner.GetUserID().String() {
|
||||
targetProfileID = edge.Node.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
require.NotEmpty(t, targetProfileID, "Should find another owner to remove")
|
||||
|
||||
mutation := `
|
||||
|
||||
@@ -42,9 +42,11 @@ func (a Attrs) get(key string, defaultVal any) any {
|
||||
if a == nil {
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
if v, ok := a[key]; ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
@@ -52,6 +54,7 @@ func (a Attrs) getString(key string, defaultVal string) string {
|
||||
if v, ok := a.get(key, defaultVal).(string); ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
@@ -59,11 +62,13 @@ func (a Attrs) getStringPtr(key string) *string {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if v, ok := a[key]; ok {
|
||||
if s, ok := v.(string); ok {
|
||||
return &s
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -71,6 +76,7 @@ func (a Attrs) getInt(key string, defaultVal int) int {
|
||||
if a == nil {
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
if v, ok := a[key]; ok {
|
||||
switch val := v.(type) {
|
||||
case int:
|
||||
@@ -81,6 +87,7 @@ func (a Attrs) getInt(key string, defaultVal int) int {
|
||||
return int(val)
|
||||
}
|
||||
}
|
||||
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
@@ -88,11 +95,13 @@ func (a Attrs) getBool(key string, defaultVal bool) bool {
|
||||
if a == nil {
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
if v, ok := a[key]; ok {
|
||||
if b, ok := v.(bool); ok {
|
||||
return b
|
||||
}
|
||||
}
|
||||
|
||||
return defaultVal
|
||||
}
|
||||
|
||||
@@ -167,9 +176,11 @@ func CreateThirdParty(c *testutil.Client, attrs ...Attrs) string {
|
||||
if desc := a.getStringPtr("description"); desc != nil {
|
||||
input["description"] = *desc
|
||||
}
|
||||
|
||||
if url := a.getStringPtr("websiteUrl"); url != nil {
|
||||
input["websiteUrl"] = *url
|
||||
}
|
||||
|
||||
if cat := a.getStringPtr("category"); cat != nil {
|
||||
input["category"] = *cat
|
||||
}
|
||||
@@ -348,6 +359,7 @@ func CreateTask(c *testutil.Client, measureID *string, attrs ...Attrs) string {
|
||||
if measureID != nil {
|
||||
input["measureId"] = *measureID
|
||||
}
|
||||
|
||||
if desc := a.getStringPtr("description"); desc != nil {
|
||||
input["description"] = *desc
|
||||
}
|
||||
@@ -951,6 +963,7 @@ func CreateAccessSource(c *testutil.Client, organizationID string, attrs ...Attr
|
||||
if csvData := a.getStringPtr("csvData"); csvData != nil {
|
||||
input["csvData"] = *csvData
|
||||
}
|
||||
|
||||
if connectorID := a.getStringPtr("connectorId"); connectorID != nil {
|
||||
input["connectorId"] = *connectorID
|
||||
}
|
||||
@@ -1446,7 +1459,9 @@ func ReportDetectedResources(c *testutil.Client, bannerID string, count int) {
|
||||
url := fmt.Sprintf("%s/api/cookie-banner/v1/%s/report", c.BaseURL(), bannerID)
|
||||
resp, err := http.Post(url, "application/json", bytes.NewReader(body))
|
||||
require.NoError(c.T, err, "report detected resources request failed")
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
require.Equal(c.T, http.StatusNoContent, resp.StatusCode, "report detected resources unexpected status")
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ func AssertTimestampsOnUpdate(t *testing.T, createdAt, updatedAt, originalCreate
|
||||
|
||||
func AssertOptionalStringEqual(t *testing.T, expected, actual *string, fieldName string) {
|
||||
t.Helper()
|
||||
|
||||
if expected == nil {
|
||||
assert.Nil(t, actual, "%s should be nil", fieldName)
|
||||
} else {
|
||||
@@ -95,6 +96,7 @@ func AssertOrderedAscending[T cmp.Ordered](t *testing.T, values []T, fieldName s
|
||||
|
||||
func AssertOrderedDescending[T cmp.Ordered](t *testing.T, values []T, fieldName string) {
|
||||
t.Helper()
|
||||
|
||||
reversed := slices.Clone(values)
|
||||
slices.Reverse(reversed)
|
||||
assert.True(t, slices.IsSorted(reversed), "%s should be in descending order, got: %v", fieldName, values)
|
||||
@@ -102,6 +104,7 @@ func AssertOrderedDescending[T cmp.Ordered](t *testing.T, values []T, fieldName
|
||||
|
||||
func AssertTimesOrderedAscending(t *testing.T, times []time.Time, fieldName string) {
|
||||
t.Helper()
|
||||
|
||||
isSorted := slices.IsSortedFunc(times, func(a, b time.Time) int {
|
||||
return a.Compare(b)
|
||||
})
|
||||
@@ -110,6 +113,7 @@ func AssertTimesOrderedAscending(t *testing.T, times []time.Time, fieldName stri
|
||||
|
||||
func AssertTimesOrderedDescending(t *testing.T, times []time.Time, fieldName string) {
|
||||
t.Helper()
|
||||
|
||||
isSorted := slices.IsSortedFunc(times, func(a, b time.Time) int {
|
||||
return b.Compare(a)
|
||||
})
|
||||
@@ -118,9 +122,11 @@ func AssertTimesOrderedDescending(t *testing.T, times []time.Time, fieldName str
|
||||
|
||||
func AssertNodeNotAccessible(t *testing.T, err error, nodeIsNil bool, resourceType string) {
|
||||
t.Helper()
|
||||
|
||||
if err == nil {
|
||||
assert.True(t, nodeIsNil, "should not be able to access %s from another org", resourceType)
|
||||
}
|
||||
|
||||
// If there's an error, that's also acceptable (access denied)
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import (
|
||||
func generateUniqueID() string {
|
||||
randomBytes := make([]byte, 4)
|
||||
_, _ = rand.Read(randomBytes)
|
||||
|
||||
return fmt.Sprintf("%d-%s", time.Now().UnixNano(), hex.EncodeToString(randomBytes))
|
||||
}
|
||||
|
||||
@@ -139,6 +140,7 @@ func (c *Client) SetupTestUserInOrg(ownerClient *Client) {
|
||||
c.userID = identityID
|
||||
c.profileID = profileID
|
||||
ownerClient.inviteUser(profileID)
|
||||
|
||||
token := c.getActivationToken(email)
|
||||
passwordToken := c.activateUser(token)
|
||||
c.resetPassword(password, passwordToken)
|
||||
@@ -285,12 +287,14 @@ func (c *Client) updateOwnMembershipRole(role coredata.MembershipRole) {
|
||||
require.NoError(c.T, err, "cannot query organization members")
|
||||
|
||||
var membershipID string
|
||||
|
||||
for _, edge := range qResult.Node.Members.Edges {
|
||||
if edge.Node.Identity.ID == c.userID.String() {
|
||||
membershipID = edge.Node.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
require.NotEmpty(c.T, membershipID, "membership not found for user")
|
||||
|
||||
// Update the role
|
||||
@@ -422,6 +426,7 @@ func (c *Client) getActivationToken(email string) string {
|
||||
|
||||
c.T.Logf("activation token not found")
|
||||
c.T.FailNow()
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
|
||||
@@ -50,9 +50,11 @@ func (e GraphQLError) Code() string {
|
||||
if e.Extensions == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if code, ok := e.Extensions["code"].(string); ok {
|
||||
return code
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -62,9 +64,11 @@ func (e GraphQLErrors) Error() string {
|
||||
if len(e) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(e) == 1 {
|
||||
return e[0].Message
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s (and %d more errors)", e[0].Message, len(e)-1)
|
||||
}
|
||||
|
||||
@@ -83,12 +87,14 @@ func (c *Client) doWithEndpoint(endpoint string, query string, variables map[str
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
@@ -160,6 +166,7 @@ func (c *Client) ExecuteShouldFail(query string, variables map[string]any) error
|
||||
c.T.Helper()
|
||||
_, err := c.Do(query, variables)
|
||||
require.Error(c.T, err, "expected GraphQL request to fail but it succeeded")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -188,6 +195,7 @@ func (c *Client) ExecuteWithFiles(query string, variables map[string]any, files
|
||||
func (c *Client) executeMultipart(query string, variables map[string]any, files map[string]UploadFile, result any) error {
|
||||
// Create multipart writer using standard library
|
||||
var buf bytes.Buffer
|
||||
|
||||
writer := multipart.NewWriter(&buf)
|
||||
|
||||
// Build the operations JSON
|
||||
@@ -195,6 +203,7 @@ func (c *Client) executeMultipart(query string, variables map[string]any, files
|
||||
"query": query,
|
||||
"variables": variables,
|
||||
}
|
||||
|
||||
operationsJSON, err := json.Marshal(operations)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot marshal operations: %w", err)
|
||||
@@ -207,14 +216,17 @@ func (c *Client) executeMultipart(query string, variables map[string]any, files
|
||||
|
||||
// Build the map for file variables (sorted for deterministic order)
|
||||
fileMap := make(map[string][]string)
|
||||
|
||||
fileOrder := make([]string, 0, len(files))
|
||||
for path := range files {
|
||||
fileOrder = append(fileOrder, path)
|
||||
}
|
||||
|
||||
// Sort for deterministic ordering
|
||||
for i, path := range fileOrder {
|
||||
fileMap[fmt.Sprintf("%d", i)] = []string{"variables." + path}
|
||||
}
|
||||
|
||||
mapJSON, err := json.Marshal(fileMap)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot marshal map: %w", err)
|
||||
@@ -239,6 +251,7 @@ func (c *Client) executeMultipart(query string, variables map[string]any, files
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create file part %s: %w", path, err)
|
||||
}
|
||||
|
||||
if _, err := part.Write(file.Content); err != nil {
|
||||
return fmt.Errorf("cannot write file content %s: %w", path, err)
|
||||
}
|
||||
@@ -253,6 +266,7 @@ func (c *Client) executeMultipart(query string, variables map[string]any, files
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||
|
||||
// Execute request
|
||||
@@ -260,6 +274,7 @@ func (c *Client) executeMultipart(query string, variables map[string]any, files
|
||||
if err != nil {
|
||||
return fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
|
||||
@@ -45,12 +45,14 @@ func (c *Client) SearchMails(query string) (*MailpitSearchResponse, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
@@ -75,12 +77,14 @@ func (c *Client) CheckMessageLinks(messageID string) (*MailpitLinkCheckResponse,
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
resp, err := c.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
|
||||
@@ -128,6 +128,7 @@ func (mc *MCPClient) doRequest(method string, params any) (json.RawMessage, erro
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Accept", "application/json, text/event-stream")
|
||||
req.Header.Set("Authorization", "Bearer "+mc.apiToken)
|
||||
|
||||
if mc.sessionID != "" {
|
||||
req.Header.Set("Mcp-Session-Id", mc.sessionID)
|
||||
}
|
||||
@@ -136,6 +137,7 @@ func (mc *MCPClient) doRequest(method string, params any) (json.RawMessage, erro
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("request failed: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
@@ -198,6 +200,7 @@ func (mc *MCPClient) CallTool(toolName string, args map[string]any) *MCPToolResu
|
||||
require.NoError(mc.t, err, "MCP tools/call %s failed", toolName)
|
||||
|
||||
var toolResult MCPToolResult
|
||||
|
||||
err = json.Unmarshal(result, &toolResult)
|
||||
require.NoError(mc.t, err, "cannot unmarshal tool result for %s", toolName)
|
||||
|
||||
@@ -212,6 +215,7 @@ func (mc *MCPClient) CallToolExpectToolError(toolName string, args map[string]an
|
||||
require.NotEmpty(mc.t, tr.Content, "tool %s returned no content", toolName)
|
||||
|
||||
var text string
|
||||
|
||||
err := json.Unmarshal(tr.Content[0].Text, &text)
|
||||
require.NoError(mc.t, err, "cannot unmarshal error text for %s", toolName)
|
||||
|
||||
@@ -227,6 +231,7 @@ func (mc *MCPClient) CallToolInto(toolName string, args map[string]any, dest any
|
||||
// The text field in MCP content is a JSON-encoded string of the output.
|
||||
// First unmarshal the raw JSON to get the string.
|
||||
var textStr string
|
||||
|
||||
err := json.Unmarshal(tr.Content[0].Text, &textStr)
|
||||
require.NoError(mc.t, err, "cannot unmarshal text content for %s", toolName)
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ func postForm(
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot post form: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
@@ -153,6 +154,7 @@ func postJSON(
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot post json: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
@@ -181,6 +183,7 @@ func getJSON(
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot execute request: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
@@ -213,6 +216,7 @@ func postFormWithBasicAuth(
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot execute request: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
@@ -298,10 +302,12 @@ func OAuth2Authorize(
|
||||
}
|
||||
|
||||
reqURL := oauth2BaseURL(c) + "/authorize?" + params.Encode()
|
||||
|
||||
resp, err := noRedirectClient.Get(reqURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get authorize: %w", err)
|
||||
}
|
||||
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
@@ -521,6 +527,7 @@ func OAuth2TokenWithDeviceCode(
|
||||
if err := json.Unmarshal(raw.Body, &result); err != nil {
|
||||
return nil, nil, raw, fmt.Errorf("cannot decode token response: %w", err)
|
||||
}
|
||||
|
||||
return &result, nil, raw, nil
|
||||
}
|
||||
|
||||
@@ -799,6 +806,7 @@ func GeneratePKCE() (verifier, challenge string) {
|
||||
for i := range b {
|
||||
b[i] = charset[rand.IntN(len(charset))]
|
||||
}
|
||||
|
||||
verifier = string(b)
|
||||
|
||||
h := sha256.Sum256([]byte(verifier))
|
||||
@@ -814,11 +822,14 @@ func IsConsentRedirect(resp *OAuth2HTTPResponse) bool {
|
||||
if resp.StatusCode != http.StatusFound {
|
||||
return false
|
||||
}
|
||||
|
||||
loc := resp.Header.Get("Location")
|
||||
|
||||
u, err := url.Parse(loc)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return u.Query().Get("consent_id") != ""
|
||||
}
|
||||
|
||||
@@ -831,14 +842,17 @@ func ExtractConsentIDFromResponse(resp *OAuth2HTTPResponse) (string, error) {
|
||||
if loc == "" {
|
||||
return "", fmt.Errorf("no Location header in redirect response")
|
||||
}
|
||||
|
||||
u, err := url.Parse(loc)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot parse redirect url: %w", err)
|
||||
}
|
||||
|
||||
consentID := u.Query().Get("consent_id")
|
||||
if consentID == "" {
|
||||
return "", fmt.Errorf("no consent_id in redirect url: %s", loc)
|
||||
}
|
||||
|
||||
return consentID, nil
|
||||
}
|
||||
|
||||
@@ -850,12 +864,14 @@ func ExtractConsentID(body []byte) (string, error) {
|
||||
s := string(body)
|
||||
|
||||
needle := `name="consent_id" value="`
|
||||
|
||||
idx := strings.Index(s, needle)
|
||||
if idx == -1 {
|
||||
return "", fmt.Errorf("consent_id not found in page")
|
||||
}
|
||||
|
||||
start := idx + len(needle)
|
||||
|
||||
end := strings.Index(s[start:], `"`)
|
||||
if end == -1 {
|
||||
return "", fmt.Errorf("malformed consent_id value")
|
||||
@@ -890,6 +906,7 @@ func OAuth2PerformAuthorizationCodeFlow(
|
||||
require.NoError(t, err)
|
||||
|
||||
var code string
|
||||
|
||||
if IsConsentRedirect(authResp) {
|
||||
consentID, err := ExtractConsentIDFromResponse(authResp)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -32,9 +32,11 @@ func ProseMirrorTextDoc(text string) string {
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
b, err := json.Marshal(doc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ func (s *switchableWriter) Write(p []byte) (int, error) {
|
||||
s.mu.Lock()
|
||||
w := s.w
|
||||
s.mu.Unlock()
|
||||
|
||||
return w.Write(p)
|
||||
}
|
||||
|
||||
@@ -104,6 +105,7 @@ func Setup() {
|
||||
cmd.Stderr = os.Stderr
|
||||
} else {
|
||||
var buf bytes.Buffer
|
||||
|
||||
testEnv.outputBuf = &buf
|
||||
sw := &switchableWriter{w: &buf}
|
||||
testEnv.outputWriter = sw
|
||||
@@ -128,14 +130,18 @@ func Setup() {
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := waitForServer(ctx, testEnv.BaseURL+"/api/console/v1/graphql", 30*time.Second); err != nil {
|
||||
testEnv.dumpOutputOnFailure("API server failed to start", err)
|
||||
_ = testEnv.cmd.Process.Kill()
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := waitForServer(ctx, testEnv.MailpitBaseURL+"/api/v1/messages", 30*time.Second); err != nil {
|
||||
testEnv.dumpOutputOnFailure("MailPit server failed to start", err)
|
||||
_ = testEnv.cmd.Process.Kill()
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -161,11 +167,13 @@ func (e *TestEnv) dumpOutputOnFailure(context string, err error) {
|
||||
|
||||
if e.outputBuf != nil && e.outputBuf.Len() > 0 {
|
||||
output := e.outputBuf.Bytes()
|
||||
|
||||
const maxTail = 10_000
|
||||
if len(output) > maxTail {
|
||||
fmt.Fprintf(os.Stderr, "e2etest: (showing last %d bytes of output)\n", maxTail)
|
||||
output = output[len(output)-maxTail:]
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, "--- probod output start ---\n%s\n--- probod output end ---\n", output)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "e2etest: no captured output available\n")
|
||||
@@ -224,6 +232,7 @@ func GetBaseURL() string {
|
||||
if testEnv == nil {
|
||||
return "http://localhost:8080"
|
||||
}
|
||||
|
||||
return testEnv.BaseURL
|
||||
}
|
||||
|
||||
@@ -231,6 +240,7 @@ func GetMailpitBaseURL() string {
|
||||
if testEnv == nil {
|
||||
return "http://localhost:8025"
|
||||
}
|
||||
|
||||
return testEnv.MailpitBaseURL
|
||||
}
|
||||
|
||||
@@ -305,6 +315,7 @@ func generateConfig() (string, error) {
|
||||
if v, ok := env[key]; ok {
|
||||
return v
|
||||
}
|
||||
|
||||
return os.Getenv(key)
|
||||
})
|
||||
|
||||
@@ -317,6 +328,7 @@ func generateConfig() (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("create temp dir: %w", err)
|
||||
}
|
||||
|
||||
path := filepath.Join(tmpDir, "probod.yml")
|
||||
|
||||
if err := bootstrap.WriteConfig(cfg, path); err != nil {
|
||||
|
||||
@@ -23,7 +23,9 @@ import (
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testutil.Setup()
|
||||
|
||||
code := m.Run()
|
||||
|
||||
testutil.Teardown()
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ func TestMCP_ListThirdPartyContacts(t *testing.T) {
|
||||
"email": factory.SafeEmail(),
|
||||
}, &result)
|
||||
require.NotEmpty(t, result.ThirdPartyContact.ID)
|
||||
|
||||
_ = i
|
||||
}
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ func TestMCP_ListThirdPartyServices(t *testing.T) {
|
||||
"name": factory.SafeName("Service"),
|
||||
}, &result)
|
||||
require.NotEmpty(t, result.ThirdPartyService.ID)
|
||||
|
||||
_ = i
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ func TestMCP_ThirdParty_CRUD(t *testing.T) {
|
||||
Name string `json:"name"`
|
||||
} `json:"third_party"`
|
||||
}
|
||||
|
||||
name := factory.SafeName("ThirdParty")
|
||||
mc.CallToolInto("addThirdParty", map[string]any{
|
||||
"organizationId": orgID,
|
||||
|
||||
@@ -220,6 +220,7 @@ func TestMCP_ListTrustCenterReferences(t *testing.T) {
|
||||
"url": "https://example.com/" + factory.SafeName("path"),
|
||||
}, &result)
|
||||
require.NotEmpty(t, result.TrustCenterReference.ID)
|
||||
|
||||
_ = i
|
||||
}
|
||||
|
||||
@@ -395,6 +396,7 @@ func TestMCP_ListComplianceExternalURLs(t *testing.T) {
|
||||
"url": "https://example.com/" + factory.SafeName("path"),
|
||||
}, &result)
|
||||
require.NotEmpty(t, result.ComplianceExternalURL.ID)
|
||||
|
||||
_ = i
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user