Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions catalog/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ where verb is one of

## Changes

- [Fixed] Package page: clicking a package-name prefix filters the package list to that prefix again — regressed by the unified-search migration ([#4413](https://github.com/quiltdata/quilt/pull/4413)), which stopped reading the link's legacy `filter` param ([#5035](https://github.com/quiltdata/quilt/pull/5035))
- [Fixed] Test suite: register `afterEach(cleanup)` so `@testing-library/react` components are unmounted between tests. With `globals: false` ([#4660](https://github.com/quiltdata/quilt/pull/4660)) RTL's auto-cleanup never registered, leaving components mounted; their deferred passive effects could flush after the jsdom environment was torn down, intermittently failing the run with an unhandled "`document` global … not defined anymore" error even when every test passed ([#5026](https://github.com/quiltdata/quilt/pull/5026))
- [Fixed] Qurator chat: drop `<div>`-in-`<p>` DOM-nesting warning from the connector status helper text shown while connectors are still connecting ([#5003](https://github.com/quiltdata/quilt/pull/5003))
- [Added] Bucket Overview v2: a denser redesign gated behind the catalog `beta` features toggle (Admin Settings) — navigational header stats, inline Qurator, and a config-driven Tabulator tables section linking into Athena Queries ([#4995](https://github.com/quiltdata/quilt/pull/4995))
Expand Down
10 changes: 5 additions & 5 deletions catalog/app/constants/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,15 @@ export const bucketDir = route(
export type BucketDirArgs = Parameters<typeof bucketDir.url>

interface BucketPackageListOpts {
filter?: string
sort?: string
p?: string
// KeywordWildcard value for the search model's `name` filter (e.g. `foo/` →
// matches the `foo/*` prefix). Must stay in sync with PackagesSearchFilterIO.
name?: string
}

export const bucketPackageList = route(
'/b/:bucket/packages/',
(bucket: string, { filter, sort, p }: BucketPackageListOpts = {}) =>
`/b/${bucket}/packages/${mkSearch({ filter, sort, p })}`,
(bucket: string, { name }: BucketPackageListOpts = {}) =>
`/b/${bucket}/packages/${mkSearch({ name })}`,
)
export type BucketPackageListArgs = Parameters<typeof bucketPackageList.url>

Expand Down
56 changes: 56 additions & 0 deletions catalog/app/containers/Bucket/PackageTree/PackageLink.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as React from 'react'
import { describe, it, expect, vi } from 'vitest'
import { MemoryRouter } from 'react-router-dom'
import { render } from '@testing-library/react'

import { bucketPackageList, bucketPackageDetail } from 'constants/routes'
import * as NamedRoutes from 'utils/NamedRoutes'
import {
PackagesSearchFilterIO,
ResultType,
parseSearchParams,
} from 'containers/Search/model'

import PackageLink from './PackageLink'

// The Search model's import graph pulls in `constants/config`, which throws
// unless a catalog config is present on `window`.
vi.mock('constants/config', () => ({ default: {} }))

describe('containers/Bucket/PackageTree/PackageLink', () => {
// Regression guard (#4413): the package list reads filters by predicate key
// and ignores unrecognized params, so the prefix link must emit a param that
// round-trips through `parseSearchParams` into the `name` filter.
it('prefix link round-trips to the package list `name` filter', () => {
const { getByRole } = render(
<MemoryRouter>
<NamedRoutes.Provider routes={{ bucketPackageList, bucketPackageDetail }}>
<PackageLink bucket="my-bucket" name="team/dataset" />
</NamedRoutes.Provider>
</MemoryRouter>,
)

const href = getByRole('link', { name: 'team/' }).getAttribute('href')
expect(href).toBeTruthy()

const state = parseSearchParams(new URL(href!, 'http://localhost').search)

expect(state.resultType).toBe(ResultType.QuiltPackage)
if (state.resultType !== ResultType.QuiltPackage) throw new Error('unreachable')

expect(state.filter.predicates.name).toMatchObject({
wildcard: 'team/',
strict: false,
})

// ...and the prefix becomes a `team/*` wildcard at the GraphQL layer.
expect(PackagesSearchFilterIO.toGQL(state.filter)?.name?.wildcard).toBe('team/*')
})

// The flip side: the pre-fix `filter=` param must stay inert.
it('drops the unrecognized legacy `filter` param', () => {
const state = parseSearchParams('?filter=team/')
if (state.resultType !== ResultType.QuiltPackage) throw new Error('unreachable')
expect(state.filter.predicates.name).toBeNull()
})
})
2 changes: 1 addition & 1 deletion catalog/app/containers/Bucket/PackageTree/PackageLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function PackageLink({ bucket, name }: PackageLinkProps) {
const [prefix, suffix] = name.split('/')
return (
<span className={classes.name}>
<Link to={urls.bucketPackageList(bucket, { filter: `${prefix}/` })}>{prefix}/</Link>
<Link to={urls.bucketPackageList(bucket, { name: `${prefix}/` })}>{prefix}/</Link>
Comment thread
sir-sigurd marked this conversation as resolved.
Comment thread
sir-sigurd marked this conversation as resolved.
<Link to={urls.bucketPackageDetail(bucket, name)}>{suffix}</Link>
</span>
)
Expand Down