mirror of
https://github.com/AmanTahiliani/box-box.git
synced 2026-08-08 04:06:18 -04:00
fix(live): give the timing tower the fold back
The tyre deg panel expanded by default during races and rendered a placeholder row per driver until enough clean laps existed to fit a degradation model. For the first third of a race that was ~525px of 'warming up' rows above the Timing Tower, pushing the tower — the thing the page exists for — off the fold entirely. The panel now opens when it has something to say rather than because the session is a race, and says 'collecting clean laps' while it waits. A reader who toggles it keeps their choice. Also: - Hoist degradationModel into a memo shared by the readiness check and the rows. It is O(laps) per driver and previously re-ran on every render at feed rate. - Order the side rail most-synthesized to most-raw, so a reader arriving mid-session gets 'what just happened' before the regulatory log. - Fade the trailing edge of the nav below 560px. It scrolls with a hidden scrollbar, so the cut-off item read as a clipping bug rather than as scrollable. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -47,9 +47,20 @@ function snapshotRows(lap: number, lastLapTime: string): LiveTimingRow[] {
|
||||
}
|
||||
|
||||
describe('TyreDegPanel', () => {
|
||||
it('shows a warming-up placeholder until enough clean laps accumulate', () => {
|
||||
it('stays collapsed while every stint is still warming up', () => {
|
||||
render(<TyreDegPanel rows={snapshotRows(3, '1:30.000')} sessionType="Race" pinned={[]} />)
|
||||
const panel = screen.getByTestId('tyredeg-panel')
|
||||
|
||||
// A panel of "warming up" placeholders carries no information and used to
|
||||
// push the Timing Tower off the fold for the first third of a race.
|
||||
expect(screen.queryAllByTestId('tyredeg-row')).toHaveLength(0)
|
||||
expect(panel).toHaveTextContent('collecting clean laps')
|
||||
})
|
||||
|
||||
it('shows a warming-up placeholder on each row once expanded', () => {
|
||||
render(<TyreDegPanel rows={snapshotRows(3, '1:30.000')} sessionType="Race" pinned={[]} />)
|
||||
fireEvent.click(screen.getByRole('button', { name: /tyre deg/i }))
|
||||
const panel = screen.getByTestId('tyredeg-panel')
|
||||
expect(panel).toHaveTextContent('VER')
|
||||
expect(panel).toHaveTextContent('M +5')
|
||||
expect(panel).toHaveTextContent('fresh')
|
||||
@@ -61,6 +72,7 @@ describe('TyreDegPanel', () => {
|
||||
makeRow('1', 1, 'VER', { NumberOfLaps: 10, LastLapTime: '1:30.000' }, { Compound: 'MEDIUM', Age: 12 }),
|
||||
]
|
||||
render(<TyreDegPanel rows={rows} sessionType="Race" pinned={[]} />)
|
||||
fireEvent.click(screen.getByRole('button', { name: /tyre deg/i }))
|
||||
expect(screen.getByText('mid-life')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
@@ -92,16 +104,44 @@ describe('TyreDegPanel', () => {
|
||||
expect(panel).not.toHaveTextContent('~P')
|
||||
})
|
||||
|
||||
it('starts expanded during a race', () => {
|
||||
render(<TyreDegPanel rows={snapshotRows(3, '1:30.000')} sessionType="Race" pinned={[]} />)
|
||||
it('opens itself during a race as soon as a stint has signal', () => {
|
||||
const { rerender } = render(
|
||||
<TyreDegPanel rows={snapshotRows(1, '1:30.000')} sessionType="Race" pinned={[]} />,
|
||||
)
|
||||
expect(screen.queryAllByTestId('tyredeg-row')).toHaveLength(0)
|
||||
|
||||
for (let lap = 2; lap <= 6; lap++) {
|
||||
const time = `1:30.${String((lap - 1) * 100).padStart(3, '0')}`
|
||||
rerender(<TyreDegPanel rows={snapshotRows(lap, time)} sessionType="Race" pinned={[]} />)
|
||||
}
|
||||
|
||||
expect(screen.getAllByTestId('tyredeg-row')).toHaveLength(2)
|
||||
})
|
||||
|
||||
it('keeps the reader\'s own collapse choice when signal arrives', () => {
|
||||
const { rerender } = render(
|
||||
<TyreDegPanel rows={snapshotRows(1, '1:30.000')} sessionType="Race" pinned={[]} />,
|
||||
)
|
||||
// Reader opens it early, then closes it again — that decision must stick
|
||||
// even once the panel would otherwise auto-open.
|
||||
const toggle = screen.getByRole('button', { name: /tyre deg/i })
|
||||
fireEvent.click(toggle)
|
||||
fireEvent.click(toggle)
|
||||
|
||||
for (let lap = 2; lap <= 6; lap++) {
|
||||
const time = `1:30.${String((lap - 1) * 100).padStart(3, '0')}`
|
||||
rerender(<TyreDegPanel rows={snapshotRows(lap, time)} sessionType="Race" pinned={[]} />)
|
||||
}
|
||||
|
||||
expect(screen.queryAllByTestId('tyredeg-row')).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('limits rows to the top ten plus pinned drivers', () => {
|
||||
const rows = Array.from({ length: 15 }, (_, index) =>
|
||||
makeRow(String(index + 1), index + 1, `D${index + 1}`),
|
||||
)
|
||||
render(<TyreDegPanel rows={rows} sessionType="Race" pinned={['14']} />)
|
||||
fireEvent.click(screen.getByRole('button', { name: /tyre deg/i }))
|
||||
expect(screen.getAllByTestId('tyredeg-row')).toHaveLength(11)
|
||||
expect(screen.getByText('D14')).toBeInTheDocument()
|
||||
expect(screen.queryByText('D12')).not.toBeInTheDocument()
|
||||
|
||||
Reference in New Issue
Block a user