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
39 changes: 39 additions & 0 deletions frontend/e2e/search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,42 @@ test.describe('Semantic Search', () => {
})

})

test.describe('Plot Sidebar', () => {
test('plot sidebar does not duplicate visible labels', async ({ page }) => {
// Mock the API calls so we don't need real ChromaDB data
await page.route('**/api/collections', async route => {
await route.fulfill({ json: [{ name: 'fashionimageUrl', count: 100 }] })
})
await page.route('**/api/collections/fashionimageUrl', async route => {
await route.fulfill({
json: { name: 'fashionimageUrl', count: 100, metadata_fields: ['productDisplayName', 'imageUrl'] }
})
})

// Navigate with collection param
await page.goto('/plot?collection=fashionimageUrl')

// Wait for the collection dropdown to be populated with options
await expect(
page.locator('select option:not([value=""])').first()
).toBeAttached({ timeout: 10_000 })

const sidebar = page.getByTestId('plot-sidebar')

await expect(sidebar.getByRole('button', { name: 'Collection', exact: true })).toBeVisible({ timeout: 5_000 })

const displayFieldsBtn = sidebar.getByRole('button', { name: 'Display Fields', exact: true })
const imageFieldBtn = sidebar.getByRole('button', { name: 'Image Field', exact: true })

await displayFieldsBtn.click()
await imageFieldBtn.click()

await expect(sidebar.locator('label').filter({ hasText: /^Collection$/ })).toHaveCount(0)
await expect(sidebar.locator('label').filter({ hasText: /^Display Fields$/ })).toHaveCount(0)
await expect(sidebar.locator('label').filter({ hasText: /^Image Field$/ })).toHaveCount(0)

await expect(sidebar.getByRole('combobox', { name: 'Collection' })).toBeVisible()
await expect(sidebar.getByRole('combobox', { name: 'Image Field' })).toBeVisible()
})
})
11 changes: 4 additions & 7 deletions frontend/src/components/plot/PlotControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ export default function PlotControls({ onCompute, isComputing }: PlotControlsPro
{/* Collection Selection */}
<CollapsibleSection title="Collection" defaultOpen={true}>
<div className="space-y-1.5">
<label className="block text-xs font-medium text-gray-600">Collection</label>
<select
aria-label="Collection"
className="w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm"
value={selectedCollection}
onChange={(e) => {
Expand Down Expand Up @@ -174,9 +174,6 @@ export default function PlotControls({ onCompute, isComputing }: PlotControlsPro
{/* Reduction Algorithm */}
<CollapsibleSection title="Reduction Algorithm" defaultOpen={false}>
<div className="space-y-1.5">
<label className="block text-xs font-medium text-gray-600">
Reduction Algorithm
</label>
<div className="flex space-x-2">
{(['tsne', 'umap', 'pca'] as const).map((algo) => (
<label key={algo} className="flex items-center text-xs cursor-pointer">
Expand Down Expand Up @@ -285,7 +282,6 @@ export default function PlotControls({ onCompute, isComputing }: PlotControlsPro
{/* Text Display Fields */}
<CollapsibleSection title="Display Fields" defaultOpen={false}>
<div className="space-y-1.5">
<label className="block text-xs font-medium text-gray-600">Display Fields</label>
<div className="max-h-32 overflow-y-auto border rounded p-2 space-y-1">
{collectionDetails.metadata_fields.map((field) => (
<div key={field} className="flex items-center">
Expand All @@ -308,8 +304,8 @@ export default function PlotControls({ onCompute, isComputing }: PlotControlsPro
{/* Image Field */}
<CollapsibleSection title="Image Field" defaultOpen={false}>
<div className="space-y-1.5">
<label className="block text-xs font-medium text-gray-600">Image Field</label>
<select
aria-label="Image Field"
className="w-full border border-gray-300 rounded-md px-2 py-1.5 text-sm"
value={imageField}
onChange={(e) => setImageField(e.target.value)}
Expand All @@ -331,12 +327,13 @@ export default function PlotControls({ onCompute, isComputing }: PlotControlsPro
<input
type="checkbox"
id="gpt-enabled"
aria-label="GPT Cluster Naming"
checked={gptEnabled}
onChange={(e) => setGptEnabled(e.target.checked)}
className="mr-2"
/>
<label htmlFor="gpt-enabled" className="text-xs font-medium text-gray-600 cursor-pointer">
GPT Cluster Naming
Enable
</label>
</div>

Expand Down
Loading