| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- import { screen, waitFor } from '@testing-library/react'
- import userEvent from '@testing-library/user-event'
- import dayjs from 'dayjs'
- import customParseFormat from 'dayjs/plugin/customParseFormat'
- import relativeTime from 'dayjs/plugin/relativeTime'
- import timezone from 'dayjs/plugin/timezone'
- import utc from 'dayjs/plugin/utc'
- import { expect, test, vi } from 'vitest'
- import { LogTable } from '@/components/interfaces/Settings/Logs/LogTable'
- import { customRender as render } from '@/tests/lib/custom-render'
- dayjs.extend(customParseFormat)
- dayjs.extend(utc)
- dayjs.extend(timezone)
- dayjs.extend(relativeTime)
- vi.mock('next/router', () => import('next-router-mock'))
- vi.mock('react-data-grid', () => ({
- default: ({ columns, rows, renderers, role, headerRowHeight }: any) => (
- <div role={role ?? 'table'}>
- {headerRowHeight !== 0 && (
- <div role="row">
- {columns.map((col: any, colIdx: number) => (
- <div key={colIdx} role="columnheader">
- {col.renderHeaderCell ? col.renderHeaderCell({}) : col.name}
- </div>
- ))}
- </div>
- )}
- {rows.map((row: any, rowIdx: number) => (
- <div key={rowIdx} role="row">
- {columns.map((col: any, colIdx: number) => (
- <div key={colIdx} role="cell">
- {col.renderCell?.({ row, rowIdx, isCellSelected: false })}
- </div>
- ))}
- </div>
- ))}
- {rows.length === 0 && renderers?.noRowsFallback}
- </div>
- ),
- Row: ({ row, ...props }: any) => <div role="row" {...props} />,
- }))
- const fakeMicroTimestamp = dayjs().unix() * 1000
- const LOG_DATA = {
- id: 'some-uuid',
- timestamp: 1621323232312,
- event_message: 'event message',
- metadata: {
- my_key: 'something_value',
- },
- }
- test('can display log data', async () => {
- render(
- <>
- <LogTable projectRef="default" data={[LOG_DATA]} />
- </>
- )
- await screen.findAllByText(LOG_DATA.timestamp)
- })
- test('Shows total results', async () => {
- render(<LogTable projectRef="default" data={[LOG_DATA]} />)
- await screen.getByText(/results \(1\)/i)
- })
- test('can run if no queryType provided', async () => {
- const mockRun = vi.fn()
- render(
- <LogTable
- projectRef="projectRef"
- data={[
- {
- id: 'some-uuid',
- timestamp: 1621323232312,
- event_message: 'some event happened',
- metadata: {
- my_key: 'something_value',
- },
- },
- ]}
- onRun={mockRun}
- />
- )
- const run = await screen.findByText('Run')
- await userEvent.click(run)
- // expect(mockRun).toBeCalled()
- })
- test('can run if no queryType provided', async () => {
- const mockRun = vi.fn()
- render(
- <LogTable
- data={[
- {
- id: 'some-uuid',
- timestamp: 1621323232312,
- event_message: 'some event happened',
- metadata: {
- my_key: 'something_value',
- },
- },
- ]}
- projectRef="abcd"
- onRun={mockRun}
- />
- )
- const run = await screen.findByText('Run')
- await userEvent.click(run)
- // expect(mockRun).toBeCalled()
- })
- test('dedupes log lines with exact id', async () => {
- // chronological mode requires 4 columns
- render(
- <LogTable
- projectRef="projectRef"
- data={[
- {
- id: 'some-uuid',
- timestamp: 1621323232312,
- event_message: 'some event happened',
- metadata: {},
- },
- {
- id: 'some-uuid',
- timestamp: 1621323232312,
- event_message: 'some event happened',
- metadata: {},
- },
- ]}
- />
- )
- // should only have one element, this line will fail if there are >1 element
- await screen.findByText('timestamp')
- })
- test('can display standard preview table columns', async () => {
- render(
- <LogTable
- projectRef="ref"
- queryType="auth"
- data={[{ id: '12345', event_message: 'some event message', timestamp: fakeMicroTimestamp }]}
- />
- )
- await waitFor(() => screen.getByText(/some event message/))
- await expect(screen.findByText(/12345/)).rejects.toThrow()
- await expect(screen.findByText(fakeMicroTimestamp)).rejects.toThrow()
- })
- test("closes the selection if the selected row's data changes", async () => {
- const { rerender } = render(
- <LogTable
- projectRef="ref"
- queryType="auth"
- data={[{ id: '1', event_message: 'some event message', timestamp: fakeMicroTimestamp }]}
- />
- )
- const text = await screen.findByText(/some event message/)
- await userEvent.click(text)
- rerender(
- <LogTable
- projectRef="ref"
- queryType="auth"
- data={[{ id: '2', event_message: 'some other message', timestamp: fakeMicroTimestamp }]}
- />
- )
- await expect(screen.findByText(/some event message/)).rejects.toThrow()
- await screen.findByText(/some other message/)
- })
- enum QueryType {
- Functions = 'functions',
- Api = 'api',
- Auth = 'auth',
- }
- test.each([
- {
- queryType: QueryType.Functions,
- data: [
- {
- event_message: 'This is a error log\n',
- event_type: 'log',
- function_id: '001b0b08-331c-403e-810c-a2004b03a019',
- level: 'error',
- timestamp: 1659545029083869,
- id: '3475cf6f-2929-4296-ab44-ce2c17069937',
- },
- ],
- includes: [/ERROR/],
- excludes: ['undefined', 'null'],
- },
- {
- queryType: QueryType.Functions,
- data: [
- {
- event_message: 'This is a uncaughtExceptop\n',
- event_type: 'uncaughtException',
- function_id: '001b0b08-331c-403e-810c-a2004b03a019',
- timestamp: 1659545029083869,
- id: '4475cf6f-2929-4296-ab44-ce2c17069937',
- level: undefined,
- },
- ],
- includes: [/uncaughtException/],
- excludes: [/ERROR/],
- },
- {
- queryType: QueryType.Api,
- data: [
- {
- event_message: 'This is a uncaughtException\n',
- path: 'this-is-some-path',
- method: 'POST',
- status_code: 500,
- timestamp: 1659545029083869,
- id: '4475cf6f-2929-4296-ab44-ce2c17069937',
- },
- ],
- includes: [/POST/, 'this-is-some-path'],
- excludes: [],
- },
- {
- queryType: QueryType.Auth,
- data: [
- {
- event_message: JSON.stringify({ msg: 'some message', path: '/auth-path', level: 'info' }),
- msg: 'some message',
- path: '/auth-path',
- level: 'info',
- timestamp: 1659545029083869,
- id: '4475cf6f-2929-4296-ab44-ce2c17069937',
- },
- ],
- includes: [/auth\-path/, /some message/, /INFO/],
- excludes: [/\{/, /\}/],
- },
- ])('table col renderer for $queryType', async ({ queryType, data, includes, excludes }) => {
- render(<LogTable projectRef="ref" queryType={queryType} data={data} />)
- await Promise.all([
- ...includes.map((text) => screen.findByText(text)),
- ...excludes.map((text) => expect(screen.findByText(text)).rejects.toThrow()),
- ])
- })
- test('error message handling', async () => {
- // Render LogTable with error as a string
- render(<LogTable projectRef="ref" error={'some error message'} />)
- expect(screen.getByText(`some error message`)).toBeTruthy()
- // Rerender LogTable with error as null
- render(<LogTable projectRef="ref" error={null} />)
- // Add any additional assertions if LogTable behaves differently when error is null
- })
- test('no results message handling', async () => {
- render(<LogTable projectRef="ref" data={[]} />)
- await screen.findByText(/No results/)
- await screen.findByText(/Try another search/)
- })
- test('custom error message: Resources exceeded during query execution', async () => {
- const errorFromLogflare = {
- error: {
- code: 400,
- errors: [
- {
- domain: 'global',
- message:
- 'Resources exceeded during query execution: The query could not be executed in the allotted memory. Peak usage: 122% of limit.\nTop memory consumer(s):\n ORDER BY operations: 99%\n other/unattributed: 1%\n',
- reason: 'resourcesExceeded',
- },
- ],
- message:
- 'Resources exceeded during query execution: The query could not be executed in the allotted memory. Peak usage: 122% of limit.\nTop memory consumer(s):\n ORDER BY operations: 99%\n other/unattributed: 1%\n',
- status: 'INVALID_ARGUMENT',
- },
- }
- // logs explorer, custom query
- const { rerender } = render(<LogTable projectRef="ref" error={errorFromLogflare} />)
- // prompt user to reduce selected tables
- await screen.findByText(/This query requires too much memory to be executed/)
- await screen.findByText(
- /Avoid selecting entire objects and instead select specific keys using dot notation/
- )
- // previewer, prompt to reduce time range
- rerender(<LogTable projectRef="ref" queryType="api" error={errorFromLogflare} />)
- await screen.findByText(/This query requires too much memory to be executed/)
- await screen.findByText(/Avoid querying across a large datetime range/)
- await screen.findByText(/Please contact support if this error persists/)
- })
|