mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
fix(studio): sort replicated tables by name by default (#50696)
## Problem Replicated tables on the pipeline detail page reshuffle after a reset. API order is unstable, and the default client sort was by status, so status changes moved rows around. Fixes PIPE-1137. ## Solution Default the replicated tables table to sort by `schema` + `name` ascending. Status sorting remains available via the Status column header. ## To test 1. Open a project with a pipeline that has several replicated tables: `/project/<ref>/database/replication/<pipelineId>`. 2. Confirm the Replicated tables list is alphabetical by `schema.name`, with the Table column showing ascending sort. 3. Reset one table and confirm its row stays in place while its status updates. 4. Click the Status column header and confirm status sorting still works. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Replicated tables are now sorted alphabetically by schema and table name by default. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
47592ace0f
commit
c837116598
2 files changed
+96
-2
No files matched your search
+95
-1
@@ -1,4 +1,4 @@
|
||||
import { screen } from '@testing-library/react'
|
||||
import { screen, within } from '@testing-library/react'
|
||||
import type { components } from 'api-types'
|
||||
import { HttpResponse } from 'msw'
|
||||
import { describe, expect, test, vi } from 'vitest'
|
||||
@@ -29,6 +29,43 @@ const pipeline: PipelineResponse = {
|
||||
tenant_id: 'default',
|
||||
}
|
||||
|
||||
const mockPipelineQueries = ({
|
||||
tableStatuses = [],
|
||||
}: {
|
||||
tableStatuses?: PipelineReplicationStatusResponse['table_statuses']
|
||||
} = {}) => {
|
||||
addAPIMock({
|
||||
method: 'get',
|
||||
path: '/platform/replication/:ref/pipelines/:pipeline_id',
|
||||
response: () => HttpResponse.json<PipelineResponse>(pipeline),
|
||||
})
|
||||
addAPIMock({
|
||||
method: 'get',
|
||||
path: '/platform/replication/:ref/pipelines/:pipeline_id/status',
|
||||
response: () =>
|
||||
HttpResponse.json<PipelineStatusResponse>({
|
||||
pipeline_id: 42,
|
||||
status: { name: 'started' },
|
||||
}),
|
||||
})
|
||||
addAPIMock({
|
||||
method: 'get',
|
||||
path: '/platform/replication/:ref/pipelines/:pipeline_id/replication-status',
|
||||
response: () =>
|
||||
HttpResponse.json<PipelineReplicationStatusResponse>({
|
||||
pipeline_id: 42,
|
||||
apply_lag: {
|
||||
active: true,
|
||||
wal_status: 'reserved',
|
||||
restart_lsn_bytes: 0,
|
||||
confirmed_flush_lsn_bytes: 0,
|
||||
safe_wal_size_bytes: null,
|
||||
},
|
||||
table_statuses: tableStatuses,
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
describe('ReplicationPipelineStatus', () => {
|
||||
test('preserves the overview structure while pipeline details load', async () => {
|
||||
let resolvePipeline: (value: PipelineResponse) => void = () => {}
|
||||
@@ -92,4 +129,61 @@ describe('ReplicationPipelineStatus', () => {
|
||||
expect(await screen.findByText('No table data yet')).toBeVisible()
|
||||
expect(screen.getByRole('status')).toHaveTextContent('')
|
||||
})
|
||||
|
||||
test('defaults to sorting replicated tables by schema and name', async () => {
|
||||
// API order is reverse of schema.name, and statuses would reorder differently if status
|
||||
// were the default (error before copying before live).
|
||||
mockPipelineQueries({
|
||||
tableStatuses: [
|
||||
{
|
||||
id: 3,
|
||||
schema: 'public',
|
||||
name: 'zebra',
|
||||
table_id: 3,
|
||||
table_name: 'public.zebra',
|
||||
state: {
|
||||
name: 'error',
|
||||
reason: 'sync failed',
|
||||
retry_policy: { policy: 'manual_retry' },
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
schema: 'public',
|
||||
name: 'alpha',
|
||||
table_id: 2,
|
||||
table_name: 'public.alpha',
|
||||
state: { name: 'following_wal' },
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
schema: 'auth',
|
||||
name: 'users',
|
||||
table_id: 1,
|
||||
table_name: 'auth.users',
|
||||
state: { name: 'copying_table' },
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
customRender(
|
||||
<PipelineRequestStatusProvider>
|
||||
<ReplicationPipelineStatus />
|
||||
</PipelineRequestStatusProvider>
|
||||
)
|
||||
|
||||
expect(await screen.findByText('zebra')).toBeVisible()
|
||||
expect(screen.getByRole('columnheader', { name: 'Table' })).toHaveAttribute(
|
||||
'aria-sort',
|
||||
'ascending'
|
||||
)
|
||||
|
||||
const table = screen.getByRole('table')
|
||||
const tableNames = within(table)
|
||||
.getAllByRole('row')
|
||||
.map((row) => within(row).queryAllByRole('cell')[0]?.textContent)
|
||||
.filter((name): name is string => Boolean(name))
|
||||
|
||||
expect(tableNames).toEqual(['auth.users', 'public.alpha', 'public.zebra'])
|
||||
})
|
||||
})
|
||||
+1
-1
@@ -166,7 +166,7 @@ export const ReplicationPipelineStatus = () => {
|
||||
|
||||
const applyLagMetrics = replicationStatusData?.apply_lag
|
||||
|
||||
const [sort, setSort] = useState<TableSort>('status:asc')
|
||||
const [sort, setSort] = useState<TableSort>('table:asc')
|
||||
const [sortColumn, sortDirection] = sort.split(':') as [TableSortColumn, 'asc' | 'desc']
|
||||
|
||||
const getAriaSort = (column: TableSortColumn) => {
|
||||
|
||||
Reference in new issue
Block a user