mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
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:
1 parent
4295bcb845
commit
2a3a2a597e
4 files changed
+123
-8
No files matched your search
+17
-4
@@ -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()
|
||||
|
||||
Reference in new issue
Block a user