Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion cypress/src/e2e/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,13 @@ const APIS = [
{ pattern: '**/api-tokens*', alias: 'getApiTokens' },
{ pattern: '**/repository*', alias: 'getRepositories', chat: true },
{ pattern: '**/collection*', alias: 'getCollections' },
{ pattern: '**/bedrock-agents/approvals*', alias: 'getBedrockApprovals' },
{ pattern: '**/bedrock-agents/discovery*', alias: 'getBedrockDiscovery' },
{ pattern: '**/bedrock-agents/invoke*', alias: 'invokeBedrockAgent' },
{ pattern: '**/bedrock-agents*', alias: 'getBedrockAgents' },
{ pattern: '**/mcp-server*', alias: 'getMcpServers' },
{ pattern: '**/mcp*', alias: 'getMcp' },
{ pattern: '**/mcp-management*', alias: 'getMcpServers' },
{ pattern: '**/mcp-management*', alias: 'getHostedMcpManagement' },
{ pattern: '**/mcp-workbench*', alias: 'getMcpWorkbench' },
{ pattern: '**/prompt-templates*', alias: 'getPromptTemplates' },
{ pattern: '**/user-preferences*', alias: 'getUserPreferences' },
Expand Down
44 changes: 44 additions & 0 deletions cypress/src/shared/specs/admin.shared.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ import {
navigateToAdminPage,
expandAdminMenu,
collapseAdminMenu,
navigateViaLibraries,
} from '../../support/adminHelpers';
import { waitForContentToLoad, verifyCloudscapeTableHasData } from '../../support/dataHelpers';

export function runAdminTests (options: {
expectMinItems?: boolean;
Expand Down Expand Up @@ -116,4 +118,46 @@ export function runAdminTests (options: {
cy.get('li[data-testid="weather.py"]').should('be.visible');
}
});

it('Bedrock Agent Catalog page loads; Add to catalog opens scan modal', () => {
const minRows = expectMinItems ? 1 : 0;
navigateToAdminPage('Bedrock Agent Catalog');
cy.url().should('include', '/bedrock-agent-management');
waitForContentToLoad();
cy.wait('@getBedrockApprovals', { timeout: 30000 });
cy.contains('h2', 'LISA catalog').should('be.visible');
if (verifyFixtureData) {
cy.contains('Smoke Test Agent').should('be.visible');
}
verifyCloudscapeTableHasData(minRows);

cy.contains('button', 'Add to catalog').click();
cy.wait('@getBedrockDiscovery', { timeout: 30000 });
if (verifyFixtureData) {
cy.contains('Add agent to catalog').should('be.visible');
cy.contains('Discovered Only Agent').should('be.visible');
}
});

it('Agentic Connections shows MCP and Bedrock tabs; agent details page loads', () => {
navigateViaLibraries('Agentic Connections');
cy.url().should('include', '/mcp-connections');
waitForContentToLoad();

// Chat prefetches MCP servers and user preferences after login, so those APIs may not fire again here.
cy.contains('[role="tab"]', 'MCP servers').should('be.visible');
cy.contains('MCP connections').should('be.visible');

cy.contains('[role="tab"]', 'Bedrock agents').should('be.visible').click();
cy.wait('@getBedrockAgents', { timeout: 30000 });

cy.contains('Amazon Bedrock agents').should('be.visible');
if (verifyFixtureData) {
cy.contains('Smoke Test Agent').should('be.visible').click();
cy.url().should('match', /bedrock\//);
cy.contains('h1', 'Smoke Test Agent').should('be.visible');
cy.contains('Agent tools').should('be.visible');
cy.contains('bedrock_smoke_tool').should('be.visible');
}
});
}
1 change: 1 addition & 0 deletions cypress/src/shared/specs/rag-admin.shared.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export function runRagAdminTests (options: {
'#/api-token-management',
'#/mcp-management',
'#/mcp-workbench',
'#/bedrock-agent-management',
];

adminOnlyPaths.forEach((path) => {
Expand Down
3 changes: 2 additions & 1 deletion cypress/src/shared/specs/user.shared.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export function runUserTests (options: {
'#/repository-management',
'#/api-token-management',
'#/mcp-management',
'#/mcp-workbench'
'#/mcp-workbench',
'#/bedrock-agent-management',
];

adminPaths.forEach((path) => {
Expand Down
10 changes: 10 additions & 0 deletions cypress/src/smoke/fixtures/bedrock-agent-approvals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"approvals": [
{
"agentId": "br-agent-1",
"agentAliasId": "TSTALIASID",
"agentName": "Smoke Test Agent",
"groups": []
}
]
}
19 changes: 19 additions & 0 deletions cypress/src/smoke/fixtures/bedrock-agents-discovery.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"agents": [
{
"agentId": "br-agent-discovered",
"agentName": "Discovered Only Agent",
"agentStatus": "PREPARED",
"suggestedAliasId": "DISCALIAS",
"aliases": [
{
"agentAliasId": "DISCALIAS",
"agentAliasStatus": "PREPARED"
}
],
"invokeReady": true,
"actionTools": []
}
],
"totalAgents": 1
}
36 changes: 36 additions & 0 deletions cypress/src/smoke/fixtures/bedrock-agents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"agents": [
{
"agentId": "br-agent-1",
"agentName": "Smoke Test Agent",
"agentStatus": "PREPARED",
"description": "Cypress smoke fixture agent",
"suggestedAliasId": "TSTALIASID",
"aliases": [
{
"agentAliasId": "TSTALIASID",
"agentAliasName": "test-alias",
"agentAliasStatus": "PREPARED"
}
],
"invokeReady": true,
"inAccount": true,
"catalogGroups": [],
"actionTools": [
{
"openAiToolName": "bedrock_smoke_tool",
"functionName": "get_smoke",
"actionGroupId": "ag-smoke",
"actionGroupName": "SmokeActions",
"description": "Smoke test tool",
"parameterSchema": {
"type": "object",
"properties": {},
"required": []
}
}
]
}
],
"totalAgents": 1
}
1 change: 1 addition & 0 deletions cypress/src/smoke/fixtures/configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"showRagLibrary": true,
"showPromptTemplateLibrary": true,
"mcpConnections": true,
"bedrockAgents": true,
"awsSessions": false,
"showMcpWorkbench": true,
"projectOrganization": true
Expand Down
13 changes: 13 additions & 0 deletions cypress/src/smoke/fixtures/user-preferences.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"user": "test-admin",
"preferences": {
"mcp": {
"overrideAllApprovals": false,
"enabledServers": []
},
"bedrockAgents": {
"enabledAgents": [],
"overrideAllBedrockApprovals": false
}
}
}
21 changes: 20 additions & 1 deletion cypress/src/smoke/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ const API_STUBS = [
{ endpoint: 'configuration', alias: 'getConfiguration' },
{ endpoint: 'health', alias: 'getHealth' },
{ endpoint: 'api-tokens', alias: 'getApiTokens' },
{ endpoint: 'mcp', alias: 'getMcp' },
{ endpoint: 'mcp-server', alias: 'getMcpServers' },
{ endpoint: 'mcp', alias: 'getMcp' },
{ endpoint: 'mcp-workbench', alias: 'getMcpWorkbench' },
{ endpoint: 'collections', alias: 'getCollections' },
];
Expand Down Expand Up @@ -202,6 +202,25 @@ function setupApiStubs (env: Record<string, unknown>) {
cy.intercept('GET', `**${apiBase}/${endpoint}*`, { fixture: `${endpoint}.json` }).as(alias);
});

const apiRoot = String(apiBase).replace(/\/+$/, '');
const escRoot = apiRoot.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// Match full request URL (origin + path)
cy.intercept('GET', new RegExp(`.+${escRoot}/bedrock-agents/approvals`), { fixture: 'bedrock-agent-approvals.json' }).as(
'getBedrockApprovals'
);
cy.intercept('GET', new RegExp(`.+${escRoot}/bedrock-agents/discovery`), { fixture: 'bedrock-agents-discovery.json' }).as(
'getBedrockDiscovery'
);
cy.intercept('GET', new RegExp(`.+${escRoot}/bedrock-agents(?:/)?(?:\\?.*)?$`), { fixture: 'bedrock-agents.json' }).as(
'getBedrockAgents'
);
cy.intercept('GET', new RegExp(`.+${escRoot}/user-preferences(?:\\?.*)?$`), { fixture: 'user-preferences.json' }).as(
'getUserPreferences'
);
cy.intercept('PUT', new RegExp(`.+${escRoot}/user-preferences`), (req) => {
req.reply({ statusCode: 200, body: req.body });
}).as('putUserPreferences');

// Setup stateful project stubs
setupProjectStubs(apiBase);

Expand Down
22 changes: 19 additions & 3 deletions cypress/src/support/adminHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ const MENU_ITEM_SELECTOR = '[role="menuitem"]';

// Core menu items that are always present for admin users
const EXPECTED_MENU_ITEMS = [
'Configuration',
'Model Management',
'RAG Management',
'API Token Management',
'Bedrock Agent Catalog',
'Configuration',
'MCP Management',
'MCP Workbench',
'Model Management',
'RAG Management',
];

/**
Expand All @@ -54,6 +55,20 @@ export function getLibraryButton (): Cypress.Chainable {
// Use aria-label which is reliable in Cloudscape TopNavigation
return cy.get('header button[aria-label="Libraries"]');
}

const LIBRARIES_MENU_SELECTOR = '[role="menu"][aria-label="Libraries"]';

/**
* Open the Libraries dropdown and click a menu item (e.g. Agentic Connections).
*/
export function navigateViaLibraries (menuItemName: string) {
getLibraryButton().should('be.visible').click().should('have.attr', 'aria-expanded', 'true');
cy.get(LIBRARIES_MENU_SELECTOR)
.should('be.visible')
.contains(MENU_ITEM_SELECTOR, menuItemName)
.filter(':visible')
.click();
}
/**
* Expand the admin menu and verify all items are present
*/
Expand Down Expand Up @@ -108,6 +123,7 @@ export function expandRagAdminMenu () {
// Cloudscape may render multiple menu elements (collapsed/expanded views).
// Filter to visible only to avoid asserting on hidden duplicates.
const ADMIN_ONLY_ITEMS = [
'Bedrock Agent Catalog',
'Configuration',
'Model Management',
'API Token Management',
Expand Down
4 changes: 4 additions & 0 deletions lambda/chat_assistant_stacks/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class ChatAssistantStackModel(BaseModel):
collectionIds: list[str] = Field(default_factory=list)
mcpServerIds: list[str] = Field(default_factory=list)
mcpToolIds: list[str] = Field(default_factory=list)
bedrockAgentIds: list[str] = Field(
default_factory=list,
description="Bedrock agent IDs allowed when using this stack; users must still opt in under Agent connections.",
)
personaPromptId: str | None = None
directivePromptIds: list[str] = Field(default_factory=list)
allowedGroups: list[str] = Field(default_factory=list)
Expand Down
Loading
Loading