first commit
This commit is contained in:
275
tests/e2e/features/mcp-logs/mcp-logs.spec.ts
Normal file
275
tests/e2e/features/mcp-logs/mcp-logs.spec.ts
Normal file
@@ -0,0 +1,275 @@
|
||||
import { expect, test } from '../../core/fixtures/base.fixture'
|
||||
|
||||
test.describe('MCP Logs', () => {
|
||||
test.beforeEach(async ({ mcpLogsPage }) => {
|
||||
await mcpLogsPage.goto()
|
||||
})
|
||||
|
||||
test.describe('MCP Logs Display', () => {
|
||||
test('should display MCP logs table or getting started guide', async ({ mcpLogsPage }) => {
|
||||
// When MCP logs exist the table is visible; otherwise a "Get Started" guide is shown
|
||||
const tableExists = await mcpLogsPage.logsTable.isVisible().catch(() => false)
|
||||
const gettingStarted = await mcpLogsPage.page.getByText(/Get Started/i).isVisible().catch(() => false)
|
||||
expect(tableExists || gettingStarted).toBe(true)
|
||||
})
|
||||
|
||||
test('should display stats cards', async ({ mcpLogsPage }) => {
|
||||
// Stats cards are only visible when MCP log data exists
|
||||
const tableExists = await mcpLogsPage.logsTable.isVisible().catch(() => false)
|
||||
if (!tableExists) {
|
||||
test.skip(true, 'No MCP logs — stats cards not rendered in getting-started view')
|
||||
return
|
||||
}
|
||||
const statsVisible = await mcpLogsPage.areStatsVisible()
|
||||
expect(statsVisible).toBe(true)
|
||||
})
|
||||
|
||||
test('should display filters section', async ({ mcpLogsPage }) => {
|
||||
// Filters are only visible when MCP log data exists (not in getting-started view)
|
||||
const tableExists = await mcpLogsPage.logsTable.isVisible().catch(() => false)
|
||||
if (!tableExists) {
|
||||
test.skip(true, 'No MCP logs — filters not rendered in getting-started view')
|
||||
return
|
||||
}
|
||||
const searchVisible = await mcpLogsPage.searchInput.isVisible().catch(() => false)
|
||||
const filtersButtonVisible = await mcpLogsPage.filtersButton.isVisible().catch(() => false)
|
||||
expect(searchVisible || filtersButtonVisible).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('MCP Log Filtering', () => {
|
||||
test('should filter logs by tool name', async ({ mcpLogsPage, page }) => {
|
||||
const filtersVisible = await mcpLogsPage.filtersButton.isVisible().catch(() => false)
|
||||
if (!filtersVisible) {
|
||||
test.skip(true, 'Filters button not visible')
|
||||
return
|
||||
}
|
||||
const applied = await mcpLogsPage.filterByToolName()
|
||||
if (!applied) {
|
||||
test.skip(true, 'No tool name options in filter list')
|
||||
return
|
||||
}
|
||||
await expect
|
||||
.poll(() => page.url(), { timeout: 5000, intervals: [200, 300, 500] })
|
||||
.toMatch(/tool_names=/)
|
||||
})
|
||||
|
||||
test('should filter logs by server label', async ({ mcpLogsPage, page }) => {
|
||||
const filtersVisible = await mcpLogsPage.filtersButton.isVisible().catch(() => false)
|
||||
if (!filtersVisible) {
|
||||
test.skip(true, 'Filters button not visible')
|
||||
return
|
||||
}
|
||||
const applied = await mcpLogsPage.filterByServerLabel()
|
||||
if (!applied) {
|
||||
test.skip(true, 'No server label options in filter list')
|
||||
return
|
||||
}
|
||||
await expect
|
||||
.poll(() => page.url(), { timeout: 5000, intervals: [200, 300, 500] })
|
||||
.toMatch(/server_labels=/)
|
||||
})
|
||||
|
||||
test('should filter logs by status', async ({ mcpLogsPage, page }) => {
|
||||
const filtersVisible = await mcpLogsPage.filtersButton.isVisible().catch(() => false)
|
||||
if (!filtersVisible) {
|
||||
test.skip(true, 'Filters button not visible')
|
||||
return
|
||||
}
|
||||
|
||||
const applied = await mcpLogsPage.filterByStatus('success')
|
||||
if (!applied) {
|
||||
test.skip(true, 'No status options in filter list')
|
||||
return
|
||||
}
|
||||
|
||||
await expect
|
||||
.poll(() => page.url(), { timeout: 5000, intervals: [200, 300, 500] })
|
||||
.toMatch(/status=success/)
|
||||
})
|
||||
|
||||
test('should search logs by content', async ({ mcpLogsPage }) => {
|
||||
const searchInput = mcpLogsPage.searchInput
|
||||
const isVisible = await searchInput.isVisible().catch(() => false)
|
||||
|
||||
if (isVisible) {
|
||||
const query = `test-query-${Date.now()}`
|
||||
await mcpLogsPage.searchLogs(query)
|
||||
|
||||
// Check that search input contains the query (DOM state)
|
||||
const inputValue = await searchInput.inputValue().catch(() => '')
|
||||
expect(inputValue).toContain(query)
|
||||
}
|
||||
})
|
||||
|
||||
test('should filter by time period', async ({ mcpLogsPage }) => {
|
||||
const datePicker = mcpLogsPage.dateRangePicker
|
||||
const isVisible = await datePicker.isVisible().catch(() => false)
|
||||
|
||||
if (isVisible) {
|
||||
// Get initial date picker value
|
||||
const initialValue = await datePicker.textContent().catch(() => '')
|
||||
|
||||
await mcpLogsPage.selectTimePeriod('7d')
|
||||
|
||||
// Check that date picker value changed (DOM state)
|
||||
const newValue = await datePicker.textContent().catch(() => '')
|
||||
expect(newValue || initialValue).toBeTruthy()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('MCP Log Details', () => {
|
||||
test('should open log details sheet', async ({ mcpLogsPage }) => {
|
||||
const logCount = await mcpLogsPage.getLogCount()
|
||||
|
||||
if (logCount > 0) {
|
||||
await mcpLogsPage.viewLogDetails(0)
|
||||
|
||||
const sheetVisible = await mcpLogsPage.logDetailSheet.isVisible().catch(() => false)
|
||||
expect(sheetVisible).toBe(true)
|
||||
|
||||
await mcpLogsPage.closeLogDetails()
|
||||
}
|
||||
})
|
||||
|
||||
test('should close log details sheet', async ({ mcpLogsPage }) => {
|
||||
const logCount = await mcpLogsPage.getLogCount()
|
||||
|
||||
if (logCount > 0) {
|
||||
await mcpLogsPage.viewLogDetails(0)
|
||||
await mcpLogsPage.closeLogDetails()
|
||||
|
||||
const sheetVisible = await mcpLogsPage.logDetailSheet.isVisible().catch(() => false)
|
||||
expect(sheetVisible).toBe(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Pagination', () => {
|
||||
test('should navigate to next page', async ({ mcpLogsPage }) => {
|
||||
const paginationVisible = await mcpLogsPage.paginationControls.isVisible().catch(() => false)
|
||||
if (!paginationVisible) {
|
||||
test.skip(true, 'No MCP logs — pagination not rendered')
|
||||
return
|
||||
}
|
||||
const nextBtn = mcpLogsPage.nextPageBtn
|
||||
const isEnabled = await nextBtn.isEnabled().catch(() => false)
|
||||
|
||||
if (!isEnabled) {
|
||||
test.skip(true, 'Only one page of results; skipping pagination test')
|
||||
return
|
||||
}
|
||||
|
||||
const initialPage = mcpLogsPage.getCurrentPageNumber()
|
||||
await mcpLogsPage.goToNextPage()
|
||||
|
||||
await expect
|
||||
.poll(() => mcpLogsPage.getCurrentPageNumber(), { timeout: 5000 })
|
||||
.toBe(initialPage + 1)
|
||||
})
|
||||
|
||||
test('should navigate to previous page', async ({ mcpLogsPage }) => {
|
||||
const paginationVisible = await mcpLogsPage.paginationControls.isVisible().catch(() => false)
|
||||
if (!paginationVisible) {
|
||||
test.skip(true, 'No MCP logs — pagination not rendered')
|
||||
return
|
||||
}
|
||||
const nextBtn = mcpLogsPage.nextPageBtn
|
||||
const nextEnabled = await nextBtn.isEnabled().catch(() => false)
|
||||
|
||||
if (!nextEnabled) {
|
||||
test.skip(true, 'Only one page of results; skipping pagination test')
|
||||
return
|
||||
}
|
||||
|
||||
await mcpLogsPage.goToNextPage()
|
||||
|
||||
await expect
|
||||
.poll(() => mcpLogsPage.getCurrentPageNumber(), { timeout: 5000 })
|
||||
.toBe(2)
|
||||
|
||||
const prevBtn = mcpLogsPage.prevPageBtn
|
||||
const prevEnabled = await prevBtn.isEnabled().catch(() => false)
|
||||
|
||||
if (!prevEnabled) {
|
||||
test.skip(true, 'Only one page of results; skipping previous-page test')
|
||||
return
|
||||
}
|
||||
|
||||
await mcpLogsPage.goToPreviousPage()
|
||||
|
||||
// We were on page 2; after previous we must be on page 1 (assert concrete value to avoid race with captured page number)
|
||||
await expect
|
||||
.poll(() => mcpLogsPage.getCurrentPageNumber(), { timeout: 5000 })
|
||||
.toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Table Sorting', () => {
|
||||
test('should sort by timestamp', async ({ mcpLogsPage }) => {
|
||||
const tableExists = await mcpLogsPage.logsTable.isVisible().catch(() => false)
|
||||
if (!tableExists) {
|
||||
test.skip(true, 'No MCP logs — table not rendered')
|
||||
return
|
||||
}
|
||||
// Timestamp is the default sort column (desc), so clicking it toggles to asc
|
||||
const initialUrl = mcpLogsPage.page.url()
|
||||
|
||||
await mcpLogsPage.sortBy('timestamp')
|
||||
|
||||
// Wait for URL to actually change after sort
|
||||
await expect
|
||||
.poll(() => mcpLogsPage.page.url(), { timeout: 5000 })
|
||||
.not.toBe(initialUrl)
|
||||
})
|
||||
|
||||
test('should sort by latency', async ({ mcpLogsPage }) => {
|
||||
const tableExists = await mcpLogsPage.logsTable.isVisible().catch(() => false)
|
||||
if (!tableExists) {
|
||||
test.skip(true, 'No MCP logs — table not rendered')
|
||||
return
|
||||
}
|
||||
await mcpLogsPage.sortBy('latency')
|
||||
|
||||
// Wait for URL to update
|
||||
await mcpLogsPage.page.waitForURL(/sort_by=latency/, { timeout: 5000 })
|
||||
|
||||
// Check URL state for latency sort
|
||||
const sortState = await mcpLogsPage.getSortState('latency')
|
||||
expect(sortState).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
test.describe('Live Updates', () => {
|
||||
test('should toggle live updates', async ({ mcpLogsPage }) => {
|
||||
const tableExists = await mcpLogsPage.logsTable.isVisible().catch(() => false)
|
||||
if (!tableExists) {
|
||||
test.skip(true, 'No MCP logs — live toggle not rendered in getting-started view')
|
||||
return
|
||||
}
|
||||
const liveToggle = mcpLogsPage.liveToggle
|
||||
const isVisible = await liveToggle.isVisible().catch(() => false)
|
||||
|
||||
if (isVisible) {
|
||||
// Default is live_enabled=true (but URL may not have it since it's the default)
|
||||
// Check for live_enabled=false to determine if currently disabled
|
||||
const initialUrl = mcpLogsPage.page.url()
|
||||
const initialLiveDisabled = initialUrl.includes('live_enabled=false')
|
||||
|
||||
await mcpLogsPage.toggleLiveUpdates()
|
||||
|
||||
// Wait for URL to reflect live_enabled toggle
|
||||
await mcpLogsPage.page.waitForURL(/live_enabled=/, { timeout: 5000 })
|
||||
|
||||
const newUrl = mcpLogsPage.page.url()
|
||||
const newLiveDisabled = newUrl.includes('live_enabled=false')
|
||||
|
||||
// Live enabled state should have toggled
|
||||
// If initially enabled (not disabled), after toggle it should be disabled
|
||||
// If initially disabled, after toggle it should be enabled (no live_enabled=false)
|
||||
expect(newLiveDisabled).not.toBe(initialLiveDisabled)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user