Add measure-document linking
Introduce the ability to link measures to documents, following the existing pattern used by controls and risks. This includes: - Database migration for measures_documents join table - Coredata MeasureDocument struct with insert/delete operations - Document service methods for listing/counting by measure ID - Measure service CreateDocumentMapping/DeleteDocumentMapping methods - Cleanup of measure-document mappings on document archive - GraphQL mutations, inputs, payloads, and Measure.documents field - DocumentConnection.TotalCount support for measure resolver - MCP linkMeasure/unlinkMeasure updated to support documents - MCP listMeasureDocuments tool - Frontend MeasureDocumentsTab with LinkedDocumentsCard integration - Authorization actions for measure document mapping - E2e tests for measure document mapping Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -945,3 +945,93 @@ func TestRiskObligationMapping_CreateDelete(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMeasureDocumentMapping_CreateDelete(t *testing.T) {
|
||||
t.Parallel()
|
||||
owner := testutil.NewClient(t, testutil.RoleOwner)
|
||||
measureID := factory.NewMeasure(owner).Create()
|
||||
|
||||
t.Run("create mapping", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
documentID := factory.NewDocument(owner).Create()
|
||||
|
||||
var result struct {
|
||||
CreateMeasureDocumentMapping struct {
|
||||
MeasureEdge struct {
|
||||
Node struct {
|
||||
ID string `json:"id"`
|
||||
} `json:"node"`
|
||||
} `json:"measureEdge"`
|
||||
DocumentEdge struct {
|
||||
Node struct {
|
||||
ID string `json:"id"`
|
||||
} `json:"node"`
|
||||
} `json:"documentEdge"`
|
||||
} `json:"createMeasureDocumentMapping"`
|
||||
}
|
||||
err := owner.Execute(`
|
||||
mutation($input: CreateMeasureDocumentMappingInput!) {
|
||||
createMeasureDocumentMapping(input: $input) {
|
||||
measureEdge {
|
||||
node {
|
||||
id
|
||||
}
|
||||
}
|
||||
documentEdge {
|
||||
node {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`, map[string]any{
|
||||
"input": map[string]any{
|
||||
"measureId": measureID,
|
||||
"documentId": documentID,
|
||||
},
|
||||
}, &result)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, measureID, result.CreateMeasureDocumentMapping.MeasureEdge.Node.ID)
|
||||
assert.Equal(t, documentID, result.CreateMeasureDocumentMapping.DocumentEdge.Node.ID)
|
||||
})
|
||||
|
||||
t.Run("delete mapping", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
documentID := factory.NewDocument(owner).Create()
|
||||
|
||||
// Create the mapping first
|
||||
_, err := owner.Do(`
|
||||
mutation($input: CreateMeasureDocumentMappingInput!) {
|
||||
createMeasureDocumentMapping(input: $input) {
|
||||
documentEdge {
|
||||
node {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`, map[string]any{
|
||||
"input": map[string]any{
|
||||
"measureId": measureID,
|
||||
"documentId": documentID,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Delete it
|
||||
_, err = owner.Do(`
|
||||
mutation($input: DeleteMeasureDocumentMappingInput!) {
|
||||
deleteMeasureDocumentMapping(input: $input) {
|
||||
deletedMeasureId
|
||||
deletedDocumentId
|
||||
}
|
||||
}
|
||||
`, map[string]any{
|
||||
"input": map[string]any{
|
||||
"measureId": measureID,
|
||||
"documentId": documentID,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user