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
4 changes: 4 additions & 0 deletions app/components/RefetchIntervalPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ export function useIntervalPicker({ enabled, isLoading, fn, className }: Props)
<div className={cn('flex', className)}>
<button
type="button"
aria-label="Refresh data"
data-testid="refetch-interval-refresh"
className={cn(
'border-default bg-default flex w-10 items-center justify-center rounded-l-md border-t border-b border-l disabled:cursor-default',
isLoading && 'hover:bg-hover',
Expand All @@ -69,6 +71,8 @@ export function useIntervalPicker({ enabled, isLoading, fn, className }: Props)
items={intervalItems}
onChange={setIntervalPreset}
disabled={!enabled}
label="Refresh interval"
hideLabel
hideSelected
/>
</div>
Expand Down
3 changes: 2 additions & 1 deletion app/pages/SiloUtilizationPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ export default function SiloUtilizationPage() {
<Listbox
selected={filterId}
className="w-52"
aria-labelledby="filter-id-label"
label="Filter by project"
hideLabel
name="filter-id"
items={projectItems}
onChange={setFilterId}
Expand Down
3 changes: 2 additions & 1 deletion app/pages/system/UtilizationPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ const MetricsTab = () => {
<Listbox
selected={filterId}
className="w-52"
aria-labelledby="filter-id-label"
label="Filter by silo"
hideLabel
name="filter-id"
items={siloItems}
onChange={setFilterId}
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"@base-ui/react": "^1.1.0",
"@floating-ui/react": "^0.26.23",
"@headlessui/react": "^2.2.9",
"@oxide/design-system": "^6.0.4",
"@oxide/design-system": "^6.2.1",
"@react-aria/live-announcer": "^3.3.4",
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/vite": "^4.1.17",
Expand Down
47 changes: 36 additions & 11 deletions test/visual/regression.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ import { expect, test } from '../e2e/utils'
// set a fixed time to avoid diffs due to irrelevant time differences
test.beforeEach(async ({ page }) => {
await page.clock.setFixedTime(new Date('2025-10-23T12:34:56.000Z'))
// TODO: revert to default viewport once we've confirmed no visual regressions
// from the grid layout change. The tall viewport forces all content to render
// without scrolling, so fullPage screenshots are comparable between the old
// contained-scroll layout and the new document-scroll layout.
await page.setViewportSize({ width: 1280, height: 3100 })
// seed Math.random so mock data (e.g. metrics charts) is deterministic
await page.addInitScript(() => {
let seed = 0x12345678
Math.random = () => {
seed |= 0
seed = (seed + 0x6d2b79f5) | 0
let t = Math.imul(seed ^ (seed >>> 15), 1 | seed)
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
}
})
})

const fullPage = { fullPage: true }
Expand Down Expand Up @@ -53,7 +59,6 @@ const pages = [
heading: 'Silo image',
exact: true,
},
{ name: 'silo utilization', url: '/utilization', heading: 'Utilization' },
{ name: 'silo access', url: '/access', heading: 'Silo Access' },

// Project - Instances
Expand Down Expand Up @@ -136,11 +141,6 @@ const pages = [

// System - Utilization
{ name: 'system utilization', url: '/system/utilization', heading: 'Utilization' },
{
name: 'system utilization metrics tab',
url: '/system/utilization?tab=metrics',
heading: 'Utilization',
},

// System - Networking
{ name: 'system ip pools', url: '/system/networking/ip-pools', heading: 'IP Pools' },
Expand Down Expand Up @@ -231,4 +231,29 @@ test.describe('Visual Regression', { tag: '@visual' }, () => {
await page.waitForLoadState('networkidle')
await expect(page).toHaveScreenshot('command-menu.png', fullPage)
})

// Utilization pages render charts and include the refetch interval picker —
// wait for the chart, then mask the refresh button so the spinner state
// doesn't cause flaky diffs.
test('silo utilization', async ({ page }) => {
await page.goto('/utilization', { waitUntil: 'networkidle' })
await expect(page.getByRole('heading', { name: 'Utilization' })).toBeVisible()
await expect(page.locator('.recharts-curve').first()).toBeVisible()
await expect(page).toHaveScreenshot('silo-utilization.png', {
fullPage: true,
mask: [page.getByTestId('refetch-interval-refresh')],
maskColor: '#0b0e14',
})
})

test('system utilization metrics tab', async ({ page }) => {
await page.goto('/system/utilization?tab=metrics', { waitUntil: 'networkidle' })
await expect(page.getByRole('heading', { name: 'Utilization' })).toBeVisible()
await expect(page.locator('.recharts-curve').first()).toBeVisible()
await expect(page).toHaveScreenshot('system-utilization-metrics-tab.png', {
fullPage: true,
mask: [page.getByTestId('refetch-interval-refresh')],
maskColor: '#0b0e14',
})
})
})
Loading