276 lines
9.9 KiB
TypeScript
276 lines
9.9 KiB
TypeScript
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)
|
|
}
|
|
})
|
|
})
|
|
})
|