Files
bifrost/tests/e2e/features/mcp-logs/mcp-logs.spec.ts
Beyhan Oğur 880f412e2c first commit
2026-04-26 21:52:23 +03:00

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)
}
})
})
})