mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
## Context Saves the last visited explorer tab via `useDashboardHistory`, such that landing back on `/explorer` will open the last visited page. Similar behaviour to Table Editor and SQL Editor Would also be useful when going between the SQL Editor and Explorer to bring snippets over <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Explorer now remembers and restores the last visited query, chat, or notebook tab. * Automatically returns to the Explorer home screen when a saved tab is unavailable. * Displays a loading state while the last visited tab is being restored. * **Bug Fixes** * Closing deleted chat tabs now clears their saved history. * **Tests** * Added coverage for Explorer tab restoration, loading states, and stale history cleanup. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
105 lines
4.0 KiB
TypeScript
105 lines
4.0 KiB
TypeScript
import { act, waitFor } from '@testing-library/react'
|
|
import { beforeEach, describe, expect, it } from 'vitest'
|
|
|
|
import { useDashboardHistory } from './useDashboardHistory'
|
|
import { customRenderHook } from '@/tests/lib/custom-render'
|
|
|
|
// useParams from 'common' is globally mocked to { ref: 'default' } in vitestSetup
|
|
|
|
const renderDashboardHistory = async () => {
|
|
const utils = customRenderHook(() => useDashboardHistory())
|
|
await waitFor(() => expect(utils.result.current.isHistoryLoaded).toBe(true))
|
|
return utils
|
|
}
|
|
|
|
describe('useDashboardHistory', () => {
|
|
beforeEach(() => {
|
|
localStorage.clear()
|
|
})
|
|
|
|
it('stores the last visited snippet', async () => {
|
|
const { result } = await renderDashboardHistory()
|
|
|
|
act(() => result.current.setLastVisitedSnippet('snippet-a'))
|
|
|
|
await waitFor(() => expect(result.current.history.sql).toBe('snippet-a'))
|
|
})
|
|
|
|
describe('clearSnippetsFromHistory', () => {
|
|
it('purges the last visited snippet when it is one of the deleted ids', async () => {
|
|
const { result } = await renderDashboardHistory()
|
|
|
|
act(() => result.current.setLastVisitedSnippet('snippet-a'))
|
|
await waitFor(() => expect(result.current.history.sql).toBe('snippet-a'))
|
|
|
|
act(() => result.current.clearSnippetsFromHistory(['snippet-b', 'snippet-a']))
|
|
|
|
await waitFor(() => expect(result.current.history.sql).toBeUndefined())
|
|
})
|
|
|
|
it('keeps the last visited snippet when it is not among the deleted ids', async () => {
|
|
const { result } = await renderDashboardHistory()
|
|
|
|
act(() => result.current.setLastVisitedSnippet('snippet-a'))
|
|
await waitFor(() => expect(result.current.history.sql).toBe('snippet-a'))
|
|
|
|
act(() => result.current.clearSnippetsFromHistory(['snippet-b']))
|
|
|
|
await waitFor(() => expect(result.current.history.sql).toBe('snippet-a'))
|
|
})
|
|
|
|
it('does not touch the table editor history', async () => {
|
|
const { result } = await renderDashboardHistory()
|
|
|
|
act(() => result.current.setLastVisitedTable('table-1'))
|
|
// setLastVisitedSnippet spreads the render-time history, so wait for the
|
|
// table update to propagate before setting the snippet
|
|
await waitFor(() => expect(result.current.history.editor).toBe('table-1'))
|
|
act(() => result.current.setLastVisitedSnippet('snippet-a'))
|
|
await waitFor(() => expect(result.current.history.sql).toBe('snippet-a'))
|
|
|
|
act(() => result.current.clearSnippetsFromHistory(['snippet-a']))
|
|
|
|
await waitFor(() => expect(result.current.history.sql).toBeUndefined())
|
|
expect(result.current.history.editor).toBe('table-1')
|
|
})
|
|
})
|
|
|
|
describe('setLastVisitedExplorerTab', () => {
|
|
it('stores the last visited Explorer tab', async () => {
|
|
const { result } = await renderDashboardHistory()
|
|
|
|
act(() => result.current.setLastVisitedExplorerTab({ type: 'notebook', id: 'notebook-1' }))
|
|
|
|
await waitFor(() =>
|
|
expect(result.current.history.explorer).toEqual({ type: 'notebook', id: 'notebook-1' })
|
|
)
|
|
})
|
|
|
|
it('clears the last visited Explorer tab when called with undefined', async () => {
|
|
const { result } = await renderDashboardHistory()
|
|
|
|
act(() => result.current.setLastVisitedExplorerTab({ type: 'chat', id: 'chat-1' }))
|
|
await waitFor(() => expect(result.current.history.explorer).toBeDefined())
|
|
|
|
act(() => result.current.setLastVisitedExplorerTab(undefined))
|
|
|
|
await waitFor(() => expect(result.current.history.explorer).toBeUndefined())
|
|
})
|
|
|
|
it('does not touch the SQL or table editor history', async () => {
|
|
const { result } = await renderDashboardHistory()
|
|
|
|
act(() => result.current.setLastVisitedSnippet('snippet-a'))
|
|
await waitFor(() => expect(result.current.history.sql).toBe('snippet-a'))
|
|
|
|
act(() => result.current.setLastVisitedExplorerTab({ type: 'query', id: 'query-1' }))
|
|
|
|
await waitFor(() =>
|
|
expect(result.current.history.explorer).toEqual({ type: 'query', id: 'query-1' })
|
|
)
|
|
expect(result.current.history.sql).toBe('snippet-a')
|
|
})
|
|
})
|
|
})
|