diff --git a/.cursor/rules/unit-integration-testing.mdc b/.cursor/rules/unit-integration-testing.mdc new file mode 100644 index 0000000000..e3a659a7c5 --- /dev/null +++ b/.cursor/rules/unit-integration-testing.mdc @@ -0,0 +1,6 @@ +--- +description: +globs: apps/studio/**/*.test.ts,apps/studio/**/*.test.tsx +alwaysApply: false +--- +Make sure to follow the guidelines in this file to write tests: [README.md](mdc:apps/studio/tests/README.md) diff --git a/apps/studio/lib/constants/index.ts b/apps/studio/lib/constants/index.ts index 81e9970dc2..a429c02ff6 100644 --- a/apps/studio/lib/constants/index.ts +++ b/apps/studio/lib/constants/index.ts @@ -5,6 +5,7 @@ export * from './infrastructure' export const IS_PLATFORM = process.env.NEXT_PUBLIC_IS_PLATFORM === 'true' export const API_URL = (() => { + if (process.env.NODE_ENV === 'test') return 'http://localhost:3000/api' // If running in platform, use API_URL from the env var if (IS_PLATFORM) return process.env.NEXT_PUBLIC_API_URL! // If running in browser, let it add the host diff --git a/apps/studio/tests/README.md b/apps/studio/tests/README.md index e1f166fc44..28ea24fa06 100644 --- a/apps/studio/tests/README.md +++ b/apps/studio/tests/README.md @@ -1,6 +1,75 @@ # UI Testing Notes -### `` vs `` +## Rules + +- All tests should be run consistently (avoid situations whereby tests fails "sometimes") + +- Group tests in folders based on the feature they are testing. Avoid file/folder based folder names since those can change and we will forget to update the tests. + +Examples: /logs /reports /projects /database-settings /auth + +## Custom Render and Custom Render Hook + +`customRender` and `customRenderHook` are wrappers around `render` and `renderHook` that add some necessary providers like `QueryClientProvider`, `TooltipProvider` and `NuqsTestingAdapter`. + +Generally use those instead of the default `render` and `renderHook` functions. + +```ts +import { customRender, customRenderHook } from 'tests/lib/custom-render' + +customRender() +customRenderHook(() => useMyHook()) +``` + +## Mocking API Requests + +To mock API requests, we use the `msw` library. + +Global mocks can be found in `tests/lib/msw-global-api-mocks.ts`. + +To mock an endpoint you can use the `addAPIMock` function. Make sure to add the mock in the `beforeEach` hook. It won't work with `beforeAll` if you have many tests. + +```ts +beforeEach(() => { + addAPIMock({ + method: 'get', + path: '/api/my-endpoint', + response: { + data: { foo: 'bar' }, + }, + }) +}) +``` + +### API Mocking Tips: + +- Keep mocks in the same folder as the tests that use them +- Add a test to verify the mock is working + +This will make debugging and updating the mocks easier. + +```ts +test('mock is working', async () => { + const response = await fetch('/api/my-endpoint') + expect(response.json()).resolves.toEqual({ data: { foo: 'bar' } }) +}) +``` + +## Mocking Nuqs URL Parameters + +To render a component that uses Nuqs with some predefined query parameters, you can use `customRender` with the `nuqs` prop. + +```ts +customRender(, { + nuqs: { + searchParams: { + search: 'hello world', + }, + }, +}) +``` + +## `` vs `` When simulating clicks on these components, do the following: @@ -13,7 +82,3 @@ await userEvent.click('Hello world') import clickDropdown from 'tests/helpers' clickDropdown('Hello world') ``` - -### Rules - -- All tests should be run consistently (avoid situations whereby tests fails "sometimes") diff --git a/apps/studio/tests/config/msw.test.ts b/apps/studio/tests/config/msw.test.ts index 10c1224d3d..e26d06bfde 100644 --- a/apps/studio/tests/config/msw.test.ts +++ b/apps/studio/tests/config/msw.test.ts @@ -9,8 +9,10 @@ test('MSW works as expected', async () => { expect(json).toEqual({ message: 'Hello from MSW!' }) }) -test('MSW fails on missing endpoints', async () => { +test('MSW errors on missing endpoints', async () => { expect(async () => { - await fetch(`${API_URL}/endpoint-that-doesnt-exist`) - }).rejects.toThrowError() + const res = await fetch(`${API_URL}/endpoint-that-doesnt-exist`) + const json = await res.json() + expect(json).toEqual({ message: '🚫 MSW missed' }) + }) }) diff --git a/apps/studio/tests/config/router.test.tsx b/apps/studio/tests/config/router.test.tsx index 032968f7e7..de55f3f056 100644 --- a/apps/studio/tests/config/router.test.tsx +++ b/apps/studio/tests/config/router.test.tsx @@ -1,5 +1,5 @@ import { render, screen, waitFor } from '@testing-library/react' -import { routerMock } from 'tests/mocks/router' +import { routerMock } from '../lib/route-mock' import { expect, suite, test } from 'vitest' import { RouterComponent } from './router' diff --git a/apps/studio/tests/pages/projects/LogTable.test.tsx b/apps/studio/tests/features/logs/LogTable.test.tsx similarity index 91% rename from apps/studio/tests/pages/projects/LogTable.test.tsx rename to apps/studio/tests/features/logs/LogTable.test.tsx index 0794f05c1a..73a85fdf12 100644 --- a/apps/studio/tests/pages/projects/LogTable.test.tsx +++ b/apps/studio/tests/features/logs/LogTable.test.tsx @@ -1,4 +1,4 @@ -import { prettyDOM, screen, waitFor } from '@testing-library/react' +import { screen, waitFor } from '@testing-library/react' import userEvent from '@testing-library/user-event' import LogTable from 'components/interfaces/Settings/Logs/LogTable' import dayjs from 'dayjs' @@ -26,36 +26,29 @@ beforeAll(() => { const fakeMicroTimestamp = dayjs().unix() * 1000 -test.skip('can display log data', async () => { +const LOG_DATA = { + id: 'some-uuid', + timestamp: 1621323232312, + event_message: 'event message', + metadata: { + my_key: 'something_value', + }, +} + +test('can display log data', async () => { render( <> - + ) - await screen.findByText(/event message/) + await screen.findAllByText(LOG_DATA.timestamp) +}) - prettyDOM(screen.getByText(/event message/)) +test('Shows total results', async () => { + render() - const row = await screen.findByText(/event message/) - - await userEvent.click(row) - - // [Joshen] commenting out for now - seems like we need to mock more stuff - await screen.findByText(/my_key/) - await screen.findByText(/something_value/) + await screen.getByText(/results \(1\)/i) }) test('can run if no queryType provided', async () => { diff --git a/apps/studio/tests/pages/projects/Logs.Datepickers.test.tsx b/apps/studio/tests/features/logs/Logs.Datepickers.test.tsx similarity index 100% rename from apps/studio/tests/pages/projects/Logs.Datepickers.test.tsx rename to apps/studio/tests/features/logs/Logs.Datepickers.test.tsx diff --git a/apps/studio/tests/pages/projects/Logs.utils.test.ts b/apps/studio/tests/features/logs/Logs.utils.test.ts similarity index 100% rename from apps/studio/tests/pages/projects/Logs.utils.test.ts rename to apps/studio/tests/features/logs/Logs.utils.test.ts diff --git a/apps/studio/tests/pages/projects/LogsFilterPopover.test.tsx b/apps/studio/tests/features/logs/LogsFilterPopover.test.tsx similarity index 100% rename from apps/studio/tests/pages/projects/LogsFilterPopover.test.tsx rename to apps/studio/tests/features/logs/LogsFilterPopover.test.tsx diff --git a/apps/studio/tests/features/logs/LogsPreviewer.test.tsx b/apps/studio/tests/features/logs/LogsPreviewer.test.tsx new file mode 100644 index 0000000000..08d0c65557 --- /dev/null +++ b/apps/studio/tests/features/logs/LogsPreviewer.test.tsx @@ -0,0 +1,128 @@ +import { screen, waitFor } from '@testing-library/react' +import dayjs from 'dayjs' +import utc from 'dayjs/plugin/utc' +import { beforeEach, expect, test, vi } from 'vitest' +import { LogsTableName } from 'components/interfaces/Settings/Logs/Logs.constants' +import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' +import { customRender, customRenderHook } from 'tests/lib/custom-render' +import userEvent from '@testing-library/user-event' + +import useLogsPreview from 'hooks/analytics/useLogsPreview' +import { LOGS_API_MOCKS } from './logs.mocks' +import { addAPIMock } from 'tests/lib/msw' + +dayjs.extend(utc) + +vi.mock('common', async (importOriginal) => { + const actual = await importOriginal() + return { + useParams: vi.fn().mockReturnValue({}), + useIsLoggedIn: vi.fn(), + isBrowser: false, + LOCAL_STORAGE_KEYS: (actual as any).LOCAL_STORAGE_KEYS, + ...(actual as any), + } +}) + +vi.mock('lib/gotrue', async (importOriginal) => ({ + ...(await importOriginal()), + auth: { onAuthStateChange: vi.fn() }, +})) + +beforeEach(() => { + addAPIMock({ + method: 'get', + path: '/platform/projects/default/analytics/endpoints/logs.all', + response: LOGS_API_MOCKS, + }) +}) + +test('search loads with whatever is on the URL', async () => { + customRender( + , + { + nuqs: { + searchParams: { + s: 'test-search-box-value', + }, + }, + } + ) + + await waitFor(() => { + expect(screen.getByRole('textbox')).toHaveValue('test-search-box-value') + }) + + await waitFor(() => { + expect(screen.getByRole('textbox')).not.toHaveValue('WRONGVALUE!🪿') + }) +}) + +test('useLogsPreview returns data from MSW', async () => { + const { result } = customRenderHook(() => + useLogsPreview({ + projectRef: 'default', + table: LogsTableName.EDGE, + }) + ) + + await waitFor(() => { + expect(result.current.isLoading).toBe(false) + }) + + await waitFor(() => { + expect(result.current.logData.length).toBeGreaterThan(0) + }) + + expect(result.current.logData).toEqual(LOGS_API_MOCKS.result) +}) + +test('LogsPreviewer renders the expected data from the API', async () => { + customRender( + + ) + + await waitFor(() => { + expect(screen.getByRole('table')).toBeInTheDocument() + }) + + const firstLogEventMessage = LOGS_API_MOCKS.result[0].event_message + + await waitFor(() => { + expect(screen.getAllByText(firstLogEventMessage)[0]).toBeInTheDocument() + }) +}) + +test('can toggle log event chart', async () => { + customRender( + + ) + + expect(screen.getByRole('button', { name: /Chart/i })).toBeInTheDocument() + + await waitFor(() => { + expect(screen.getByTestId('logs-bar-chart')).toBeInTheDocument() + }) + + await userEvent.click(screen.getByRole('button', { name: /Chart/i })) + + await waitFor(() => { + expect(screen.queryByTestId('logs-bar-chart')).not.toBeInTheDocument() + }) +}) + +test('can click load older', async () => { + customRender( + + ) + + const loadOlder = await waitFor( + async () => await screen.findByRole('button', { name: /Load older/i }) + ) + + loadOlder.onclick = vi.fn() + + await userEvent.click(loadOlder) + + expect(loadOlder.onclick).toHaveBeenCalled() +}) diff --git a/apps/studio/tests/pages/projects/LogsQueryPanel.test.tsx b/apps/studio/tests/features/logs/LogsQueryPanel.test.tsx similarity index 100% rename from apps/studio/tests/pages/projects/LogsQueryPanel.test.tsx rename to apps/studio/tests/features/logs/LogsQueryPanel.test.tsx diff --git a/apps/studio/tests/pages/projects/logs-query.test.tsx b/apps/studio/tests/features/logs/logs-query.test.tsx similarity index 99% rename from apps/studio/tests/pages/projects/logs-query.test.tsx rename to apps/studio/tests/features/logs/logs-query.test.tsx index 2d8d87904f..7d6db95321 100644 --- a/apps/studio/tests/pages/projects/logs-query.test.tsx +++ b/apps/studio/tests/features/logs/logs-query.test.tsx @@ -4,7 +4,7 @@ import dayjs from 'dayjs' import { LogsExplorerPage } from 'pages/project/[ref]/logs/explorer/index' import { clickDropdown } from 'tests/helpers' import { customRender as render } from 'tests/lib/custom-render' -import { routerMock } from 'tests/mocks/router' +import { routerMock } from 'tests/lib/route-mock' import { beforeAll, describe, expect, test, vi } from 'vitest' const router = routerMock diff --git a/apps/studio/tests/features/logs/logs.mocks.ts b/apps/studio/tests/features/logs/logs.mocks.ts new file mode 100644 index 0000000000..d59364c2bc --- /dev/null +++ b/apps/studio/tests/features/logs/logs.mocks.ts @@ -0,0 +1,22 @@ +export const LOGS_API_MOCKS = { + result: [ + { + id: 'uuid', + event_message: 'foobar', + timestamp: 1298085933, + error_count: 1, + warning_count: 2, + ok_count: 3, + count: 2, + }, + { + id: 'uuid2', + event_message: 'foobar', + timestamp: 1298085933, + error_count: 1, + warning_count: 2, + ok_count: 3, + count: 2, + }, + ], +} diff --git a/apps/studio/tests/pages/projects/reports/api-report.test.tsx b/apps/studio/tests/features/reports/api-report.test.tsx similarity index 96% rename from apps/studio/tests/pages/projects/reports/api-report.test.tsx rename to apps/studio/tests/features/reports/api-report.test.tsx index ec2d548022..40b671833c 100644 --- a/apps/studio/tests/pages/projects/reports/api-report.test.tsx +++ b/apps/studio/tests/features/reports/api-report.test.tsx @@ -2,7 +2,7 @@ import { screen } from '@testing-library/react' import { beforeAll, test, vi } from 'vitest' import { ApiReport } from 'pages/project/[ref]/reports/api-overview' -import { render } from '../../../helpers' +import { render } from 'tests/helpers' // [Joshen] Mock data for ApiReport is in __mocks__/hooks/useApiReport // I don't think this is an ideal set up as the mock data is not clear in this file itself diff --git a/apps/studio/tests/pages/projects/reports/storage-report.test.tsx b/apps/studio/tests/features/reports/storage-report.test.tsx similarity index 96% rename from apps/studio/tests/pages/projects/reports/storage-report.test.tsx rename to apps/studio/tests/features/reports/storage-report.test.tsx index 792d8d4dc8..eeb34ddcce 100644 --- a/apps/studio/tests/pages/projects/reports/storage-report.test.tsx +++ b/apps/studio/tests/features/reports/storage-report.test.tsx @@ -2,7 +2,7 @@ import { screen } from '@testing-library/react' import { test } from 'vitest' import { StorageReport } from 'pages/project/[ref]/reports/storage' -import { render } from '../../../helpers' +import { render } from 'tests/helpers' // [Joshen] Mock data for ApiReport is in __mocks__/hooks/useStorageReport // I don't think this is an ideal set up as the mock data is not clear in this file itself diff --git a/apps/studio/tests/lib/custom-render.tsx b/apps/studio/tests/lib/custom-render.tsx index 1683d21fd4..de287fa768 100644 --- a/apps/studio/tests/lib/custom-render.tsx +++ b/apps/studio/tests/lib/custom-render.tsx @@ -1,9 +1,9 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query' -import { render, RenderOptions } from '@testing-library/react' +import { render, renderHook, RenderOptions } from '@testing-library/react' import { NuqsTestingAdapter } from 'nuqs/adapters/testing' import { TooltipProvider } from 'ui' -type AdapterProps = Parameters[0] +type AdapterProps = Partial[0]> const CustomWrapper = ({ children, @@ -14,7 +14,15 @@ const CustomWrapper = ({ queryClient?: QueryClient nuqs?: AdapterProps }) => { - const _queryClient = queryClient ?? new QueryClient() + const _queryClient = + queryClient ?? + new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }) return ( @@ -41,3 +49,15 @@ export const customRender = (component: React.ReactElement, renderOptions?: Cust ...renderOptions, }) } + +export const customRenderHook = (hook: () => any, renderOptions?: CustomRenderOpts) => { + return renderHook(hook, { + wrapper: ({ children }) => + CustomWrapper({ + children, + queryClient: renderOptions?.queryClient, + nuqs: renderOptions?.nuqs, + }), + ...renderOptions, + }) +} diff --git a/apps/studio/tests/lib/msw-global-api-mocks.ts b/apps/studio/tests/lib/msw-global-api-mocks.ts new file mode 100644 index 0000000000..9b46881f3c --- /dev/null +++ b/apps/studio/tests/lib/msw-global-api-mocks.ts @@ -0,0 +1,26 @@ +import { API_URL } from 'lib/constants' +import { HttpResponse, http } from 'msw' + +export const GlobalAPIMocks = [ + http.get(`${API_URL}/msw/test`, () => { + return HttpResponse.json({ message: 'Hello from MSW!' }) + }), + http.get(`${API_URL}/platform/projects/default/databases`, () => { + return HttpResponse.json([ + { + cloud_provider: 'AWS', + connectionString: '123', + connection_string_read_only: '123', + db_host: '123', + db_name: 'postgres', + db_port: 5432, + identifier: 'default', + inserted_at: '2025-02-16T22:24:42.115195', + region: 'us-east-1', + restUrl: 'https://default.supabase.co', + size: 't4g.nano', + status: 'ACTIVE_HEALTHY', + }, + ]) + }), +] diff --git a/apps/studio/tests/lib/msw.ts b/apps/studio/tests/lib/msw.ts new file mode 100644 index 0000000000..5d473acce0 --- /dev/null +++ b/apps/studio/tests/lib/msw.ts @@ -0,0 +1,25 @@ +import { setupServer } from 'msw/node' +import { GlobalAPIMocks } from './msw-global-api-mocks' +import { http, HttpResponse } from 'msw' +import { API_URL } from 'lib/constants' + +export const mswServer = setupServer(...GlobalAPIMocks) + +export const addAPIMock = ({ + method, + path, + response, +}: { + method: keyof typeof http + path: string + response: any +}) => { + const fullPath = `${API_URL}${path}` + console.log('[MSW] Adding mock:', method, fullPath) + + mswServer.use( + http[method](fullPath, () => { + return HttpResponse.json(response) + }) + ) +} diff --git a/apps/studio/tests/mocks/router/index.ts b/apps/studio/tests/lib/route-mock.ts similarity index 100% rename from apps/studio/tests/mocks/router/index.ts rename to apps/studio/tests/lib/route-mock.ts diff --git a/apps/studio/tests/mocks/api/index.ts b/apps/studio/tests/mocks/api/index.ts deleted file mode 100644 index 55ad01ba07..0000000000 --- a/apps/studio/tests/mocks/api/index.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { API_URL } from 'lib/constants' -import { HttpResponse, http } from 'msw' - -const PROJECT_REF = 'default' - -export const APIMock = [ - http.get(`${API_URL}/msw/test`, () => { - return HttpResponse.json({ message: 'Hello from MSW!' }) - }), - http.get(`${API_URL}/platform/projects/${PROJECT_REF}/analytics/endpoints/logs.all`, () => { - return HttpResponse.json({ - totalRequests: [ - { - count: 12, - timestamp: '2024-05-13T20:00:00.000Z', - }, - ], - errorCounts: [], - responseSpeed: [ - { - avg: 1017.0000000000001, - timestamp: '2024-05-13T20:00:00', - }, - ], - topRoutes: [ - { - count: 6, - method: 'GET', - path: '/auth/v1/user', - search: null, - status_code: 200, - }, - { - count: 4, - method: 'GET', - path: '/rest/v1/', - search: null, - status_code: 200, - }, - { - count: 2, - method: 'HEAD', - path: '/rest/v1/', - search: null, - status_code: 200, - }, - ], - topErrorRoutes: [], - topSlowRoutes: [ - { - avg: 1093.5, - count: 4, - method: 'GET', - path: '/rest/v1/', - search: null, - status_code: 200, - }, - { - avg: 1037.5, - count: 2, - method: 'HEAD', - path: '/rest/v1/', - search: null, - status_code: 200, - }, - { - avg: 959.1666666666667, - count: 6, - method: 'GET', - path: '/auth/v1/health', - search: null, - status_code: 200, - }, - ], - networkTraffic: [ - { - egress_mb: 0.000666, - ingress_mb: 0, - timestamp: '2024-05-13T20:00:00.000Z', - }, - ], - }) - }), -] diff --git a/apps/studio/tests/pages/projects/LogsPreviewer.test.tsx b/apps/studio/tests/pages/projects/LogsPreviewer.test.tsx deleted file mode 100644 index 35737b539a..0000000000 --- a/apps/studio/tests/pages/projects/LogsPreviewer.test.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { findByText, screen, waitFor } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import dayjs from 'dayjs' -import utc from 'dayjs/plugin/utc' -import { useRouter } from 'next/router' -import { expect, test, vi } from 'vitest' - -dayjs.extend(utc) - -import { LogsTableName } from 'components/interfaces/Settings/Logs/Logs.constants' -import LogsPreviewer from 'components/interfaces/Settings/Logs/LogsPreviewer' -import { render } from '../../helpers' - -// [Joshen] There's gotta be a much better way to mock these things so that it applies for ALL tests -// Since these are easily commonly used things across all pages/components that we might be testing for -vi.mock('common', async (importOriginal) => { - const actual = await importOriginal() - return { - useParams: vi.fn().mockReturnValue({}), - useIsLoggedIn: vi.fn(), - isBrowser: false, - LOCAL_STORAGE_KEYS: (actual as any).LOCAL_STORAGE_KEYS, - } -}) -vi.mock('lib/gotrue', () => ({ - auth: { onAuthStateChange: vi.fn() }, -})) - -test.skip('Search will trigger a log refresh', async () => { - render() - - await userEvent.type(screen.getByPlaceholderText(/Search events/), 'something{enter}') - - await waitFor( - () => { - // updates router query params - const router = useRouter() - expect(router.push).toHaveBeenCalledWith( - expect.objectContaining({ - pathname: expect.any(String), - query: expect.objectContaining({ - s: expect.stringContaining('something'), - }), - }) - ) - }, - { timeout: 1500 } - ) - const table = await screen.findByRole('table') - await findByText(table, /some-message/, { selector: '*' }, { timeout: 1500 }) -}) - -test.skip('poll count for new messages', async () => { - render() - await waitFor(() => screen.queryByText(/200/) === null) - // should display new logs count - await waitFor(() => screen.getByText(/999/)) - - // Refresh button only exists with the queryType param, which no longer shows the id column - await userEvent.click(screen.getByTitle('refresh')) - await waitFor(() => screen.queryByText(/999/) === null) - await screen.findByText(/200/) -}) - -test.skip('stop polling for new count on error', async () => { - render() - await waitFor(() => screen.queryByText(/some-uuid123/) === null) - // should display error - await screen.findByText(/some logflare error/) - // should not load refresh counts if no data from main query - await expect(screen.findByText(/999/)).rejects.toThrowError() -}) - -test.skip('log event chart', async () => { - render() - - await waitFor(() => screen.queryByText(/some-uuid123/) === null) -}) diff --git a/apps/studio/tests/pages/projects/PreviewFilterPanel.test.tsx b/apps/studio/tests/pages/projects/PreviewFilterPanel.test.tsx deleted file mode 100644 index 8903d110b2..0000000000 --- a/apps/studio/tests/pages/projects/PreviewFilterPanel.test.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { screen } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { expect, test, vi } from 'vitest' - -test.skip('filter input change and submit', async () => { - const mockFn = vi.fn() - // render() - expect(mockFn).not.toBeCalled() - const search = screen.getByPlaceholderText(/Search/) - await userEvent.type(search, '12345{enter}') - expect(mockFn).toBeCalled() -}) - -// test('filter input value', async () => { -// render() -// await screen.findByDisplayValue('1234') -// }) - -// test('Manual refresh', async () => { -// const mockFn = vi.fn() -// render() -// const btn = await screen.findByTitle('refresh') -// await userEvent.click(btn) -// expect(mockFn).toBeCalled() -// }) -// test('Datepicker dropdown', async () => { -// const fn = vi.fn() -// render() -// clickDropdown(await screen.findByText(/Last hour/)) -// await userEvent.click(await screen.findByText(/Last 3 hours/)) -// expect(fn).toBeCalled() -// }) - -// test('shortened count to K', async () => { -// render() -// await screen.findByText(/1\.2K/) -// }) diff --git a/apps/studio/tests/pages/projects/logs-explorer/saved.test.tsx b/apps/studio/tests/pages/projects/logs-explorer/saved.test.tsx deleted file mode 100644 index 33ce28fbc1..0000000000 --- a/apps/studio/tests/pages/projects/logs-explorer/saved.test.tsx +++ /dev/null @@ -1,8 +0,0 @@ -// mock the fetch function -import { test } from 'vitest' - -test('on load, refresh user content', async () => { - // get.mockResolvedValue({}) - // render() - // expect(get).toBeCalled() -}) diff --git a/apps/studio/tests/vitestSetup.ts b/apps/studio/tests/vitestSetup.ts index 6e4cb178f9..23c1903adf 100644 --- a/apps/studio/tests/vitestSetup.ts +++ b/apps/studio/tests/vitestSetup.ts @@ -1,14 +1,11 @@ -/// - import '@testing-library/jest-dom/vitest' -import { cleanup } from '@testing-library/react' -import { setupServer } from 'msw/node' +import { cleanup, configure } from '@testing-library/react' import { createDynamicRouteParser } from 'next-router-mock/dist/dynamic-routes' import { afterAll, afterEach, beforeAll, vi } from 'vitest' -import { APIMock } from './mocks/api' -import { routerMock } from './mocks/router' +import { routerMock } from './lib/route-mock' +import { mswServer } from './lib/msw' -export const mswServer = setupServer(...APIMock) +mswServer.listen({ onUnhandledRequest: 'error' }) Object.defineProperty(window, 'matchMedia', { writable: true, @@ -24,10 +21,17 @@ Object.defineProperty(window, 'matchMedia', { })), }) -beforeAll(() => { - console.log('🤖 Starting MSW Server') +// Uncomment this if HTML in errors are being annoying. +// +// configure({ +// getElementError: (message, container) => { +// const error = new Error(message ?? 'Element not found') +// error.name = 'ElementNotFoundError' +// return error +// }, +// }) - mswServer.listen({ onUnhandledRequest: 'error' }) +beforeAll(() => { vi.mock('next/router', () => require('next-router-mock')) vi.mock('next/navigation', async () => { const actual = await vi.importActual('next/navigation') diff --git a/packages/ui-patterns/LogsBarChart/index.tsx b/packages/ui-patterns/LogsBarChart/index.tsx index 9590ce6683..264221a75f 100644 --- a/packages/ui-patterns/LogsBarChart/index.tsx +++ b/packages/ui-patterns/LogsBarChart/index.tsx @@ -43,7 +43,7 @@ export const LogsBarChart = ({ const endDate = dayjs(data[data?.length - 1]?.['timestamp']).format(DateTimeFormat) return ( -
+