Files
probo/e2e/mcp/compliance_portal_test.go
Émile Ré 0d832508c9 Replace portal title with entity name
Store a short entity name instead of the full home
heading so orgs can brand portals for sub-entities.
Restore hero i18n composition and keep the English
document title composed from the entity name.

Signed-off-by: Émile Ré <emile@probo.com>
2026-07-22 13:08:02 +02:00

518 lines
17 KiB
Go

// Copyright (c) 2025-2026 Probo Inc <hello@probo.com>.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
package mcp_test
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.probo.inc/probo/e2e/internal/factory"
"go.probo.inc/probo/e2e/internal/testutil"
)
type mcpFile struct {
DownloadURL string `json:"download_url"`
}
type compliancePortal struct {
ID string `json:"id"`
EntityName string `json:"entity_name"`
Active bool `json:"active"`
Logo *mcpFile `json:"logo,omitempty"`
}
type compliancePortalReference struct {
ID string `json:"id"`
Name string `json:"name"`
WebsiteURL *string `json:"website_url"`
Description *string `json:"description"`
}
type complianceCustomLink struct {
ID string `json:"id"`
Name string `json:"name"`
URL string `json:"url"`
}
func TestMCP_GetCompliancePortal(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
const compliancePortalQuery = `
query($organizationId: ID!) {
node(id: $organizationId) {
... on Organization {
compliancePortal {
id
}
}
}
}
`
var compliancePortalLookup struct {
Node struct {
CompliancePortal struct {
ID string `json:"id"`
} `json:"compliancePortal"`
} `json:"node"`
}
err := owner.Execute(compliancePortalQuery, map[string]any{
"organizationId": orgID,
}, &compliancePortalLookup)
require.NoError(t, err)
require.NotEmpty(t, compliancePortalLookup.Node.CompliancePortal.ID)
compliancePortalID := compliancePortalLookup.Node.CompliancePortal.ID
const uploadMutation = `
mutation UpdateCompliancePortalBrand($input: UpdateCompliancePortalBrandInput!) {
updateCompliancePortalBrand(input: $input) {
compliancePortal {
id
logo {
id
downloadUrl
}
}
}
}
`
pngContent := []byte{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x15, 0xc4,
0x89, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41,
0x54, 0x78, 0x9c, 0x63, 0x00, 0x01, 0x00, 0x00,
0x05, 0x00, 0x01, 0x0d, 0x0a, 0x2d, 0xb4, 0x00,
0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae,
0x42, 0x60, 0x82,
}
var uploadResult struct {
UpdateCompliancePortalBrand struct {
CompliancePortal struct {
ID string `json:"id"`
Logo *struct {
ID string `json:"id"`
DownloadURL string `json:"downloadUrl"`
} `json:"logo"`
} `json:"compliancePortal"`
} `json:"updateCompliancePortalBrand"`
}
err = owner.ExecuteWithFile(uploadMutation, map[string]any{
"input": map[string]any{
"compliancePortalId": compliancePortalID,
"logoFile": nil,
},
}, "input.logoFile", testutil.UploadFile{
Filename: "mcp-compliance-portal-logo.png",
ContentType: "image/png",
Content: pngContent,
}, &uploadResult)
require.NoError(t, err)
require.NotNil(t, uploadResult.UpdateCompliancePortalBrand.CompliancePortal.Logo)
var result struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &result)
assert.NotEmpty(t, result.CompliancePortal.ID)
require.NotNil(t, result.CompliancePortal.Logo)
assert.True(
t,
strings.Contains(result.CompliancePortal.Logo.DownloadURL, "/api/files/v1/public/"),
"download_url must route through the public files API, got %q",
result.CompliancePortal.Logo.DownloadURL,
)
}
func TestMCP_UpdateCompliancePortal(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// Get compliance portal ID
var getResult struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &getResult)
require.NotEmpty(t, getResult.CompliancePortal.ID)
// Update
var updateResult struct {
CompliancePortal struct {
ID string `json:"id"`
EntityName string `json:"entity_name"`
Description *string `json:"description"`
WebsiteURL *string `json:"website_url"`
Email *string `json:"email"`
HeadquarterAddress *string `json:"headquarter_address"`
} `json:"compliance_portal"`
}
mc.CallToolInto("updateCompliancePortal", map[string]any{
"compliance_portal_id": getResult.CompliancePortal.ID,
"entity_name": "Acme Security",
"description": "We keep your data safe.",
"website_url": "https://example.com",
"email": "security@example.com",
"headquarter_address": "123 Main St, San Francisco, CA 94102",
}, &updateResult)
assert.Equal(t, getResult.CompliancePortal.ID, updateResult.CompliancePortal.ID)
assert.Equal(t, "Acme Security", updateResult.CompliancePortal.EntityName)
require.NotNil(t, updateResult.CompliancePortal.Description)
assert.Equal(t, "We keep your data safe.", *updateResult.CompliancePortal.Description)
require.NotNil(t, updateResult.CompliancePortal.WebsiteURL)
assert.Equal(t, "https://example.com", *updateResult.CompliancePortal.WebsiteURL)
require.NotNil(t, updateResult.CompliancePortal.Email)
assert.Equal(t, "security@example.com", *updateResult.CompliancePortal.Email)
require.NotNil(t, updateResult.CompliancePortal.HeadquarterAddress)
assert.Equal(t, "123 Main St, San Francisco, CA 94102", *updateResult.CompliancePortal.HeadquarterAddress)
}
func TestMCP_AddCompliancePortalReference(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// Get compliance portal ID
var getResult struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &getResult)
portalID := getResult.CompliancePortal.ID
var result struct {
CompliancePortalReference compliancePortalReference `json:"compliance_portal_reference"`
}
mc.CallToolInto("addCompliancePortalReference", map[string]any{
"compliance_portal_id": portalID,
"name": "SOC 2 Report",
"website_url": "https://example.com/soc2",
}, &result)
assert.NotEmpty(t, result.CompliancePortalReference.ID)
assert.Equal(t, "SOC 2 Report", result.CompliancePortalReference.Name)
}
func TestMCP_UpdateCompliancePortalReference(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// Get compliance portal ID
var getResult struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &getResult)
portalID := getResult.CompliancePortal.ID
// Create reference
var addResult struct {
CompliancePortalReference compliancePortalReference `json:"compliance_portal_reference"`
}
mc.CallToolInto("addCompliancePortalReference", map[string]any{
"compliance_portal_id": portalID,
"name": "Original Reference",
"website_url": "https://example.com/original",
}, &addResult)
require.NotEmpty(t, addResult.CompliancePortalReference.ID)
// Update reference
var updateResult struct {
CompliancePortalReference compliancePortalReference `json:"compliance_portal_reference"`
}
mc.CallToolInto("updateCompliancePortalReference", map[string]any{
"id": addResult.CompliancePortalReference.ID,
"name": "Updated Reference",
"website_url": "https://example.com/updated",
}, &updateResult)
assert.Equal(t, addResult.CompliancePortalReference.ID, updateResult.CompliancePortalReference.ID)
assert.Equal(t, "Updated Reference", updateResult.CompliancePortalReference.Name)
}
func TestMCP_DeleteCompliancePortalReference(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// Get compliance portal ID
var getResult struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &getResult)
portalID := getResult.CompliancePortal.ID
// Create reference
var addResult struct {
CompliancePortalReference compliancePortalReference `json:"compliance_portal_reference"`
}
mc.CallToolInto("addCompliancePortalReference", map[string]any{
"compliance_portal_id": portalID,
"name": "Reference to delete",
"website_url": "https://example.com/delete",
}, &addResult)
require.NotEmpty(t, addResult.CompliancePortalReference.ID)
// Delete
var deleteResult struct {
DeletedCompliancePortalReferenceID string `json:"deleted_compliance_portal_reference_id"`
}
mc.CallToolInto("deleteCompliancePortalReference", map[string]any{
"id": addResult.CompliancePortalReference.ID,
}, &deleteResult)
assert.Equal(t, addResult.CompliancePortalReference.ID, deleteResult.DeletedCompliancePortalReferenceID)
}
func TestMCP_ListCompliancePortalReferences(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// Get compliance portal ID
var getResult struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &getResult)
portalID := getResult.CompliancePortal.ID
// Create references
for i := range 2 {
var result struct {
CompliancePortalReference compliancePortalReference `json:"compliance_portal_reference"`
}
mc.CallToolInto("addCompliancePortalReference", map[string]any{
"compliance_portal_id": portalID,
"name": factory.SafeName("Ref"),
"website_url": "https://example.com/" + factory.SafeName("path"),
}, &result)
require.NotEmpty(t, result.CompliancePortalReference.ID)
_ = i
}
// List
var listResult struct {
CompliancePortalReferences []compliancePortalReference `json:"compliance_portal_references"`
}
mc.CallToolInto("listCompliancePortalReferences", map[string]any{
"compliance_portal_id": portalID,
}, &listResult)
assert.GreaterOrEqual(t, len(listResult.CompliancePortalReferences), 2)
}
func TestMCP_ListCompliancePortalFiles(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// List files (may be empty, just verify the tool works)
var listResult struct {
CompliancePortalFiles []struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"compliance_portal_files"`
}
mc.CallToolInto("listCompliancePortalFiles", map[string]any{
"organization_id": orgID,
}, &listResult)
// Just assert the call succeeded — files require multipart upload
assert.NotNil(t, listResult.CompliancePortalFiles)
}
func TestMCP_AddComplianceCustomLink(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// Get compliance portal ID
var getResult struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &getResult)
portalID := getResult.CompliancePortal.ID
var result struct {
ComplianceCustomLink complianceCustomLink `json:"compliance_custom_link"`
}
mc.CallToolInto("addComplianceCustomLink", map[string]any{
"compliance_portal_id": portalID,
"name": "ISO 27001 Certificate",
"url": "https://example.com/iso27001",
}, &result)
assert.NotEmpty(t, result.ComplianceCustomLink.ID)
assert.Equal(t, "ISO 27001 Certificate", result.ComplianceCustomLink.Name)
}
func TestMCP_UpdateComplianceCustomLink(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// Get compliance portal ID
var getResult struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &getResult)
portalID := getResult.CompliancePortal.ID
// Create
var addResult struct {
ComplianceCustomLink complianceCustomLink `json:"compliance_custom_link"`
}
mc.CallToolInto("addComplianceCustomLink", map[string]any{
"compliance_portal_id": portalID,
"name": "Original URL",
"url": "https://example.com/original",
}, &addResult)
require.NotEmpty(t, addResult.ComplianceCustomLink.ID)
// Update
var updateResult struct {
ComplianceCustomLink complianceCustomLink `json:"compliance_custom_link"`
}
mc.CallToolInto("updateComplianceCustomLink", map[string]any{
"id": addResult.ComplianceCustomLink.ID,
"name": "Updated URL",
"url": "https://example.com/updated",
}, &updateResult)
assert.Equal(t, addResult.ComplianceCustomLink.ID, updateResult.ComplianceCustomLink.ID)
assert.Equal(t, "Updated URL", updateResult.ComplianceCustomLink.Name)
}
func TestMCP_DeleteComplianceCustomLink(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// Get compliance portal ID
var getResult struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &getResult)
portalID := getResult.CompliancePortal.ID
// Create
var addResult struct {
ComplianceCustomLink complianceCustomLink `json:"compliance_custom_link"`
}
mc.CallToolInto("addComplianceCustomLink", map[string]any{
"compliance_portal_id": portalID,
"name": "URL to delete",
"url": "https://example.com/delete",
}, &addResult)
require.NotEmpty(t, addResult.ComplianceCustomLink.ID)
// Delete
var deleteResult struct {
DeletedComplianceCustomLinkID string `json:"deleted_compliance_custom_link_id"`
}
mc.CallToolInto("deleteComplianceCustomLink", map[string]any{
"id": addResult.ComplianceCustomLink.ID,
}, &deleteResult)
assert.Equal(t, addResult.ComplianceCustomLink.ID, deleteResult.DeletedComplianceCustomLinkID)
}
func TestMCP_ListComplianceCustomLinks(t *testing.T) {
t.Parallel()
owner := testutil.NewClient(t, testutil.RoleOwner)
mc := testutil.NewMCPClient(t, owner)
orgID := owner.GetOrganizationID().String()
// Get compliance portal ID
var getResult struct {
CompliancePortal compliancePortal `json:"compliance_portal"`
}
mc.CallToolInto("getCompliancePortal", map[string]any{
"organization_id": orgID,
}, &getResult)
portalID := getResult.CompliancePortal.ID
// Create URLs
for i := range 2 {
var result struct {
ComplianceCustomLink complianceCustomLink `json:"compliance_custom_link"`
}
mc.CallToolInto("addComplianceCustomLink", map[string]any{
"compliance_portal_id": portalID,
"name": factory.SafeName("URL"),
"url": "https://example.com/" + factory.SafeName("path"),
}, &result)
require.NotEmpty(t, result.ComplianceCustomLink.ID)
_ = i
}
// List
var listResult struct {
ComplianceCustomLinks []complianceCustomLink `json:"compliance_custom_links"`
}
mc.CallToolInto("listComplianceCustomLinks", map[string]any{
"compliance_portal_id": portalID,
}, &listResult)
assert.GreaterOrEqual(t, len(listResult.ComplianceCustomLinks), 2)
}