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
64 changes: 64 additions & 0 deletions packages/app/cypress/component/chart-buttons.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { ChartButtons } from '@/components/ui/chart-buttons';

describe('ChartButtons', () => {
describe('without CSV export', () => {
beforeEach(() => {
cy.mount(
<div style={{ position: 'relative', width: 400, height: 200 }}>
<div id="test-chart">Chart content</div>
<ChartButtons chartId="test-chart" analyticsPrefix="test" />
</div>,
);
});

it('zoom reset dispatches custom event', () => {
cy.window().then((win) => {
const handler = cy.stub().as('zoomReset');
win.addEventListener('test_zoom_reset_test-chart', handler);
});
cy.get('[data-testid="zoom-reset-button"]').click();
cy.get('@zoomReset').should('have.been.calledOnce');
});
});

describe('with CSV export', () => {
it('shows dropdown with PNG and CSV options', () => {
const onExportCsv = cy.stub().as('csvExport');
cy.mount(
<div style={{ position: 'relative', width: 400, height: 200 }}>
<div id="test-chart">Chart content</div>
<ChartButtons chartId="test-chart" analyticsPrefix="test" onExportCsv={onExportCsv} />
</div>,
);
cy.get('[data-testid="export-button"]').click();
cy.get('[data-testid="export-png-button"]').should('be.visible');
cy.get('[data-testid="export-csv-button"]').should('be.visible');
});

it('clicking CSV calls onExportCsv', () => {
const onExportCsv = cy.stub().as('csvExport');
cy.mount(
<div style={{ position: 'relative', width: 400, height: 200 }}>
<div id="test-chart">Chart content</div>
<ChartButtons chartId="test-chart" analyticsPrefix="test" onExportCsv={onExportCsv} />
</div>,
);
cy.get('[data-testid="export-button"]').click();
cy.get('[data-testid="export-csv-button"]').click();
cy.get('@csvExport').should('have.been.calledOnce');
});
});

describe('hideZoomReset', () => {
it('hides zoom reset button when hideZoomReset is true', () => {
cy.mount(
<div style={{ position: 'relative', width: 400, height: 200 }}>
<div id="test-chart">Chart content</div>
<ChartButtons chartId="test-chart" analyticsPrefix="test" hideZoomReset />
</div>,
);
cy.get('[data-testid="zoom-reset-button"]').should('not.exist');
cy.get('[data-testid="export-button"]').should('be.visible');
});
});
});
96 changes: 96 additions & 0 deletions packages/app/cypress/component/chart-selectors.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { useState } from 'react';

import {
ModelSelector,
SequenceSelector,
PrecisionSelector,
} from '@/components/ui/chart-selectors';
import { TooltipProvider } from '@/components/ui/tooltip';

function ModelSelectorHarness() {
const [value, setValue] = useState('DeepSeek-R1-0528');
return (
<TooltipProvider>
<ModelSelector
value={value}
onChange={setValue}
availableModels={['DeepSeek-R1-0528', 'Llama-4-Maverick', 'Qwen3-235B']}
data-testid="model-selector"
/>
</TooltipProvider>
);
}

function SequenceSelectorHarness() {
const [value, setValue] = useState('1024_128');
return (
<TooltipProvider>
<SequenceSelector
value={value}
onChange={setValue}
availableSequences={['1024_128', '1024_8192', '8192_1024']}
data-testid="sequence-selector"
/>
</TooltipProvider>
);
}

function PrecisionSelectorHarness() {
const [value, setValue] = useState(['FP8']);
return (
<TooltipProvider>
<PrecisionSelector
value={value}
onChange={setValue}
availablePrecisions={['FP8', 'FP4', 'BF16']}
data-testid="precision-multiselect"
/>
</TooltipProvider>
);
}

describe('Chart Selectors', () => {
describe('ModelSelector', () => {
beforeEach(() => {
cy.mount(<ModelSelectorHarness />);
});

it('shows options when clicked', () => {
cy.get('[data-testid="model-selector"]').click();
cy.get('[role="option"]').should('have.length.greaterThan', 0);
});

it('selecting an option updates the displayed value', () => {
cy.get('[data-testid="model-selector"]').click();
cy.get('[role="option"]').contains('Qwen3-235B').click();
cy.get('[data-testid="model-selector"]').should('contain', 'Qwen3-235B');
});
});

describe('SequenceSelector', () => {
beforeEach(() => {
cy.mount(<SequenceSelectorHarness />);
});

it('shows options when clicked', () => {
cy.get('[data-testid="sequence-selector"]').click();
cy.get('[role="option"]').should('have.length', 3);
});

it('selecting an option updates the displayed value', () => {
cy.get('[data-testid="sequence-selector"]').click();
cy.get('[role="option"]').last().click();
cy.get('[data-testid="sequence-selector"]').should('not.contain', '1K / 128');
});
});

describe('PrecisionSelector', () => {
beforeEach(() => {
cy.mount(<PrecisionSelectorHarness />);
});

it('shows current selection', () => {
cy.get('[data-testid="precision-multiselect"]').should('contain', 'FP8');
});
});
});
81 changes: 81 additions & 0 deletions packages/app/cypress/component/date-range-picker.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { useState } from 'react';

import { DateRangePicker, DateRange } from '@/components/ui/date-range-picker';

function DateRangePickerHarness({
initialRange = { startDate: '', endDate: '' },
availableDates,
}: {
initialRange?: DateRange;
availableDates?: string[];
}) {
const [range, setRange] = useState<DateRange>(initialRange);
return (
<div data-testid="date-range-wrapper">
<DateRangePicker
dateRange={range}
onChange={setRange}
availableDates={availableDates}
placeholder="Select date range"
/>
<div data-testid="date-range-output">
{range.startDate && range.endDate ? `${range.startDate} to ${range.endDate}` : 'no range'}
</div>
</div>
);
}

describe('DateRangePicker', () => {
it('renders with placeholder text', () => {
cy.mount(<DateRangePickerHarness />);
cy.get('[data-testid="date-range-wrapper"]').should('contain', 'Select date range');
});

it('opens dialog when clicked', () => {
cy.mount(<DateRangePickerHarness />);
cy.contains('Select date range').click();
cy.get('[role="dialog"]').should('be.visible');
cy.contains('Select Date Range').should('be.visible');
});

it('apply is disabled when no dates selected', () => {
cy.mount(<DateRangePickerHarness />);
cy.contains('Select date range').click();
cy.contains('button', 'Apply').should('be.disabled');
});

it('cancel closes the dialog', () => {
cy.mount(<DateRangePickerHarness />);
cy.contains('Select date range').click();
cy.get('[role="dialog"]').should('be.visible');
cy.contains('button', 'Cancel').click();
cy.get('[role="dialog"]').should('not.exist');
});

it('displays formatted range when dates are provided', () => {
cy.mount(
<DateRangePickerHarness initialRange={{ startDate: '2026-01-15', endDate: '2026-02-20' }} />,
);
cy.get('[data-testid="date-range-wrapper"]').should('contain', 'Jan 15, 2026');
cy.get('[data-testid="date-range-wrapper"]').should('contain', 'Feb 20, 2026');
});

it('shows quick select buttons when availableDates provided', () => {
const dates = ['2025-12-01', '2025-12-15', '2026-01-01', '2026-02-01', '2026-03-01'];
cy.mount(<DateRangePickerHarness availableDates={dates} />);
cy.contains('Select date range').click();
cy.contains('button', 'Max Range').should('be.visible');
});

it('shows overlay when no available dates', () => {
cy.mount(<DateRangePickerHarness availableDates={[]} />);
cy.contains('Select date range').click();
cy.contains('No available dates').should('be.visible');
});

it('shows overlay when only 1 available date', () => {
cy.mount(<DateRangePickerHarness availableDates={['2026-01-01']} />);
cy.contains('Select date range').click();
cy.contains('Only 1 date available').should('be.visible');
});
});
8 changes: 0 additions & 8 deletions packages/app/cypress/component/footer.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ describe('Footer', () => {
);
});

it('renders the footer element', () => {
cy.get('[data-testid="footer"]').should('exist');
});

it('displays copyright notice with semianalysis.com and current year', () => {
const year = new Date().getFullYear().toString();
cy.get('[data-testid="footer-copyright"]').should('contain', 'semianalysis.com');
Expand Down Expand Up @@ -58,10 +54,6 @@ describe('Footer', () => {
.and('include', 'github.com/SemiAnalysisAI/InferenceX-app');
});

it('shows the SemiAnalysis logo', () => {
cy.get('[data-testid="footer-brand"]').find('img[alt="SemiAnalysis logo"]').should('exist');
});

it('all external links open in a new tab', () => {
cy.get('[data-testid="footer-links"]')
.find('a[target="_blank"]')
Expand Down
8 changes: 0 additions & 8 deletions packages/app/cypress/component/header.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,6 @@ describe('Header', () => {
);
});

it('renders the header element', () => {
cy.get('[data-testid="header"]').should('be.visible');
});

it('displays the InferenceX title', () => {
cy.get('[data-testid="header"]').contains('InferenceX').should('be.visible');
});
Expand Down Expand Up @@ -52,10 +48,6 @@ describe('Header', () => {
.and('include', 'github.com/SemiAnalysisAI/InferenceX');
});

it('GitHub stars button has glow animation class', () => {
cy.get('[data-testid="header-star-button"]').should('have.class', 'star-button-glow');
});

it('shows the theme toggle button', () => {
cy.get('[data-testid="theme-toggle"]').should('be.visible');
});
Expand Down
8 changes: 0 additions & 8 deletions packages/app/cypress/component/mode-toggle.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ describe('ModeToggle', () => {
);
});

it('renders the theme toggle button', () => {
cy.get('[data-testid="theme-toggle"]').should('be.visible');
});

it('has accessible aria-label', () => {
cy.get('[data-testid="theme-toggle"]').should('have.attr', 'aria-label');
});

it('clicking toggle switches to dark mode', () => {
cy.get('html').should('not.have.class', 'dark');
cy.get('[data-testid="theme-toggle"]').click();
Expand Down
29 changes: 0 additions & 29 deletions packages/app/cypress/component/social-share.cy.tsx

This file was deleted.

45 changes: 0 additions & 45 deletions packages/app/cypress/e2e/chart-export.cy.ts

This file was deleted.

Loading