Add E2E tests for local studio logs (#33592)

* add e2e tests for local studio logs

* fix auth schema test

* comment out log pages without logs

* fix tests rm react query from dom, it blocks view of definition button

* undo auth table changes
This commit is contained in:
Jordi Enric authored and GitHub committed 2025-02-14 15:06:16 +08:00
1 parent 4295bcb845
commit 2a3a2a597e
4 files changed
+123 -8

No files matched your search

@@ -16,7 +16,15 @@ import { useState, useEffect } from 'react'
const LogRowSeparator = () => <Separator className="bg-border my-1" />
const PropertyRow = ({ keyName, value }: { keyName: string; value: any }) => {
const PropertyRow = ({
keyName,
value,
dataTestId,
}: {
keyName: string
value: any
dataTestId?: string
}) => {
const isTimestamp =
keyName === 'timestamp' || keyName === 'created_at' || keyName === 'updated_at'
@@ -83,7 +91,7 @@ const PropertyRow = ({ keyName, value }: { keyName: string; value: any }) => {
return (
<DropdownMenu>
<DropdownMenuTrigger className="group w-full">
<DropdownMenuTrigger className="group w-full" data-testid={dataTestId}>
<div className="rounded-md w-full overflow-hidden">
<div
className={cn('flex py-2 w-full', {
@@ -131,10 +139,15 @@ const DefaultPreviewSelectionRenderer = ({ log }: { log: PreviewLogData }) => {
const { timestamp, event_message, metadata, id, ...rest } = log
return (
<div className={`p-2 flex flex-col`}>
<div data-testid="log-selection" className={`p-2 flex flex-col`}>
{log?.id && <PropertyRow key={'id'} keyName={'id'} value={log.id} />}
{log?.timestamp && (
<PropertyRow key={'timestamp'} keyName={'timestamp'} value={log.timestamp} />
<PropertyRow
dataTestId="log-selection-timestamp"
key={'timestamp'}
keyName={'timestamp'}
value={log.timestamp}
/>
)}
{log?.event_message && (
@@ -30,13 +30,18 @@ export default defineConfig({
trace: 'on-first-retry',
// record a video for failed tests, but only for local testing. We can't store videos on CI atm.
video: 'retain-on-failure',
launchOptions: {
env: {
NODE_ENV: 'test',
},
},
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
use: { ...devices['Desktop Chrome'], viewport: { width: 1366, height: 768 } },
},
// {
@@ -0,0 +1,81 @@
import { test, expect } from '@playwright/test'
const LOGS_PAGES = [
'API Gateway',
'Postgres',
'PostgREST',
// 'Auth', Wont have logs on first load
// 'Storage', Wont have logs on first load
//'Realtime' Wont have logs on first load
]
test.describe('Logs', async () => {
for (const logPage of LOGS_PAGES) {
test.describe(`${logPage} logs page`, () => {
test('can navigate to logs page', async ({ page }) => {
await page.goto('http://localhost:8082/project/default')
await page.locator('a', { hasText: 'Logs' }).click({ timeout: 4000 })
await expect(page.getByText('Logs & Analytics')).toBeVisible()
// Click anywhere on the screen to close the sidebar
await page.click('body')
await page
.getByRole('link', { name: logPage, exact: true })
.click()
.catch((e) => {
console.log('🔴 Error clicking', logPage, e)
throw e
})
// Wait for and verify the logs table is present
const logsTable = page.getByRole('table')
await expect(logsTable).toBeVisible()
})
test('shows logs data without errors', async ({ page }) => {
// Navigate to page first
await page.goto('http://localhost:8082/project/default')
await page.locator('a', { hasText: 'Logs' }).click({ timeout: 4000 })
await page.click('body')
await page.getByRole('link', { name: logPage, exact: true }).click()
// Wait a bit and check for errors with a longer timeout
const error = page.getByText('Error fetching logs')
await expect(error).not.toBeVisible({ timeout: 10000 })
// Check if the logs table has any rows
const gridcells = page.getByRole('gridcell')
await expect(gridcells.first()).toBeVisible()
})
test('can select and view log details', async ({ page }) => {
// Navigate to page first
await page.goto('http://localhost:8082/project/default')
await page.locator('a', { hasText: 'Logs' }).click({ timeout: 4000 })
await page.click('body')
await page.getByRole('link', { name: logPage, exact: true }).click()
const gridcells = page.getByRole('gridcell')
// Click first row and verify details
await gridcells.first().click()
const tabPanel = page.getByTestId('log-selection')
await expect(tabPanel).toBeVisible({ timeout: 2000 })
const selectionPanelTimestamp = tabPanel.getByTestId('log-selection-timestamp')
await expect(selectionPanelTimestamp).toBeVisible()
const rawTimestamp = await selectionPanelTimestamp.textContent()
const timestamp = rawTimestamp?.replace('timestamp', '')
const rowText = await gridcells.first().textContent()
expect(rowText).toContain(timestamp)
// Click second row and verify different content
await gridcells.nth(1).click()
const tabPanelText2 = await tabPanel.textContent()
expect(tabPanelText2).not.toBe(rowText)
})
})
}
})
@@ -19,7 +19,7 @@ test.describe('Table Editor page', () => {
test('should create a new table, view its definition, add new rows, sort and filter', async ({
page,
}, testInfo) => {
const tableName = `${kebabCase(testInfo.title).slice(0, 24)}-${testInfo.retry}-${Math.floor(Math.random() * 100)}`
const tableName = `${kebabCase(testInfo.title).slice(0, 24)}-${testInfo.retry}-${Math.floor(Math.random() * 10000)}`
// The page has been loaded with the table data, we can now interact with the page
await page.getByRole('button', { name: 'New table', exact: true }).click()
@@ -46,6 +46,14 @@ test.describe('Table Editor page', () => {
await page.getByRole('button', { name: 'Save' }).click()
await dismissToast(page)
// hide React Query DevTools if present
await page.evaluate(() => {
const devtools = document.querySelector('.ReactQueryDevtools')
if (devtools) {
devtools.remove()
}
})
// view its definition
await page.getByText('definition').click()
await expect(page.locator('div.view-lines')).toContainText(
@@ -69,9 +77,17 @@ test.describe('Table Editor page', () => {
await page.getByTestId('action-bar-save-row').click()
await dismissToast(page)
// Wait for both rows to be visible in the grid
await page.waitForResponse((response) =>
response.url().includes('/api/platform/pg-meta/default/query')
)
await expect(page.getByRole('grid')).toContainText('2')
await expect(page.getByRole('grid')).toContainText('100')
// Make sure we can see both rows in the grid before sorting
const rows = page.getByRole('row')
await expect(rows).toHaveCount(3) // header row + 2 data rows
// sort by the a column
await page.getByRole('button', { name: 'Sort' }).click()
await page.getByTestId('table-editor-pick-column-to-sort-button').click()
@@ -82,8 +98,8 @@ test.describe('Table Editor page', () => {
await page.locator('#spec-click-target').click()
// expect the row to be sorted by defaultValueColumn. They're inserted in the order 100, 2
await expect(page.locator('div.rdg-row:nth-child(2)')).toContainText('2')
await expect(page.locator('div.rdg-row:nth-child(3)')).toContainText('100')
await expect(rows.nth(1)).toContainText('2')
await expect(rows.nth(2)).toContainText('100')
// remove the sorting
await page.getByRole('button', { name: 'Sorted by 1 rule' }).click()
await page.getByRole('dialog').getByRole('button').nth(1).click()