diff --git a/studio/pages/project/[ref]/settings/logs/[type].tsx b/studio/pages/project/[ref]/settings/logs/[type].tsx index 01bb5e9856f..5a7782c56b6 100644 --- a/studio/pages/project/[ref]/settings/logs/[type].tsx +++ b/studio/pages/project/[ref]/settings/logs/[type].tsx @@ -9,8 +9,9 @@ import { get } from "lib/common/fetch" import LogTable, { LogData } from 'components/ui/Logs/LogTable' import useSWR from 'swr' import { API_URL } from 'lib/constants' -import { Typography, Input, Button } from '@supabase/ui' +import { Typography, Button } from '@supabase/ui' import debounce from 'lodash/debounce' +import CodeEditor from 'components/ui/CodeEditor' interface CountData { count: number @@ -24,6 +25,7 @@ export const LogPage = () => { const title = LOG_TYPE_LABEL_MAPPING[type as string] const [search, setSearch] = useState("") const [queryParams, setQueryParams] = useState("") + const [where, setWhere] = useState("") const [latestRefresh, setLatestRefresh] = useState(new Date().toISOString()) // handle log fetching @@ -35,20 +37,21 @@ export const LogPage = () => { revalidateOnFocus: false, }) const debouncedSearch = debounce(setSearch, 500) + const debouncedWhere = debounce(setWhere, 500) useEffect(() => { const params = { - search_query: search, - path: `/${type}` + search_query: search || "", + path: `/${type}`, + where: where || "" } const qs = new URLSearchParams(params).toString() setQueryParams(qs) - }, [search]) + }, [search, where]) const countKey = `${API_URL}/projects/${ref}/logs?${queryParams}&count=true&period_start=${latestRefresh}` const { data: countData, - mutate: mutateCount } = useSWR<{ data: [CountData] | [], error?: any }>(countKey, get, { refreshInterval: 5000 }) @@ -62,6 +65,13 @@ export const LogPage = () => { return ( + setWhere(v || "")} + onInputRun={handleRefresh} + /> {error && (Could not fetch data)} {newCount && newCount > 0 && } diff --git a/studio/tests/pages/projects/logs.test.js b/studio/tests/pages/projects/logs.test.js index 7a3a633c48a..a76a9226c2b 100644 --- a/studio/tests/pages/projects/logs.test.js +++ b/studio/tests/pages/projects/logs.test.js @@ -18,9 +18,22 @@ jest.mock('next/router') import { useRouter } from 'next/router' useRouter.mockReturnValue({ query: { ref: "123", type: "auth" } }) +// mock monaco editor +jest.mock("@monaco-editor/react") +import Editor, { useMonaco } from "@monaco-editor/react" +Editor = jest.fn() +Editor.mockImplementation((props) => { + return ( + + ) +}) +useMonaco.mockImplementation(v => v) + import { LogPage } from 'pages/project/[ref]/settings/logs/[type]' import { render, fireEvent, waitFor, screen } from '@testing-library/react' -import { SWRConfig } from 'swr' import userEvent from '@testing-library/user-event' beforeEach(() => { @@ -121,5 +134,32 @@ test("poll count for new messages", async () => { userEvent.click(screen.getByText(/Load new logs/)) await waitFor(() => screen.queryByText(/Load new logs/) === null) + await waitFor(() => screen.getByText(/happened/)) +}) + + +test("where clause will trigger a log refresh", async () => { + get.mockImplementation((url) => { + + if (url.includes("where") && url.includes("something")) { + return { + data: [{ + id: "some-uuid", + timestamp: 1621323232312, + event_message: "some event happened", + metadata: {} + }] + } + } + return { data: [] } + }) + const { container } = render() + const editor = container.querySelector('.monaco-editor'); + userEvent.type(editor, "metadata.field = something") + await waitFor(() => { + expect(get).toHaveBeenCalledWith(expect.stringContaining("where")) + expect(get).toHaveBeenCalledWith(expect.stringContaining("metadata.field")) + }, { timeout: 1000 }) + await waitFor(() => screen.getByText(/happened/)) }) \ No newline at end of file