fix(status-bar): remove pet menu reserved space (#13067)

* fix(status-bar): remove pet menu reserved space

* test(status-bar): add pet segment layout validation tests

- Unit test guards against pr-[6.5rem] padding reintroduction
- E2E test measures trailing overhang instead of total width delta
  for more accurate layout validation
- Extract enableExperimentalPet helper for test clarity

---------

Co-authored-by: m4air <m4air@m4airs-Air.localdomain>
This commit is contained in:
Isaque Coelho
2026-08-23 12:21:15 -07:00
committed by GitHub
co-authored by m4air
parent e3327c2f31
commit 853afdf80e
3 changed files with 99 additions and 1 deletions
@@ -0,0 +1,15 @@
import { readFileSync } from 'node:fs'
import { join } from 'node:path'
import { describe, expect, it } from 'vitest'
describe('PetStatusSegment layout', () => {
it('does not reserve fixed right padding on the pet menu trigger', () => {
const source = readFileSync(join(__dirname, 'PetStatusSegment.tsx'), 'utf8')
// Why: the old pr-[6.5rem] reserved ~104px of empty space after the label and
// shoved neighboring status-bar segments left; unit-guard so CI catches a
// reintroduction without needing Electron Playwright.
expect(source).not.toMatch(/pr-\[\d+(?:\.\d+)?rem\]/)
expect(source).toMatch(/className="group inline-flex items-center cursor-pointer pl-1 py-0\.5"/)
})
})
@@ -116,7 +116,7 @@ function PetStatusSegmentInner(): React.JSX.Element {
<DropdownMenuTrigger asChild>
<button
type="button"
className="group inline-flex items-center cursor-pointer pl-1 pr-[6.5rem] py-0.5"
className="group inline-flex items-center cursor-pointer pl-1 py-0.5"
aria-label={translate(
'auto.components.status.bar.PetStatusSegment.aec479308a',
'Pet menu'
@@ -0,0 +1,83 @@
import type { Page, TestInfo } from '@stablyai/playwright-test'
import { expect, test } from './helpers/orca-app'
import { waitForSessionReady } from './helpers/store'
// Why: post-fix trailing overhang is ~0px; 16px is subpixel headroom that still
// fails the old pr-[6.5rem] (~104px) reservation.
const MAX_TRAILING_CHROME_PX = 16
const VIEWPORTS = [
{ name: 'desktop', size: { width: 1440, height: 900 } },
{ name: 'mobile', size: { width: 390, height: 844 } }
] as const
async function enableExperimentalPet(page: Page): Promise<void> {
await page.evaluate(async () => {
const store = window.__store
if (!store) {
throw new Error('window.__store is not available')
}
// Why: updateSettings swallows errors; throw so a failed persist fails loudly.
await store.getState().updateSettingsOrThrow({ experimentalPet: true })
})
await expect
.poll(
async () =>
page.evaluate(() => window.__store?.getState().settings?.experimentalPet === true),
{ message: 'experimentalPet did not become true after updateSettingsOrThrow' }
)
.toBe(true)
}
async function assertPetTriggerFitsLabel(page: Page): Promise<void> {
const trigger = page.getByRole('button', { name: 'Pet menu' })
// Why: only the label span is a direct child; avoid matching nested menu spans
// if the open state ever leaks into the measurement.
const label = trigger.locator(':scope > span')
await expect(trigger).toBeVisible()
await expect(label).toBeVisible()
// Why: measure trailing overhang (trigger right label right), not total width
// delta — the regression is empty space *after* the label (the old pr-[6.5rem]).
await expect
.poll(
async () => {
const [triggerBox, labelBox] = await Promise.all([
trigger.boundingBox(),
label.boundingBox()
])
if (!triggerBox || !labelBox) {
return Number.POSITIVE_INFINITY
}
return triggerBox.x + triggerBox.width - (labelBox.x + labelBox.width)
},
{ message: 'pet menu trigger still reserves trailing space after its label' }
)
.toBeLessThanOrEqual(MAX_TRAILING_CHROME_PX)
}
async function attachTriggerScreenshot(
page: Page,
testInfo: TestInfo,
name: string
): Promise<void> {
const trigger = page.getByRole('button', { name: 'Pet menu' })
const screenshotPath = testInfo.outputPath(`pet-status-trigger-${name}.png`)
await trigger.screenshot({ path: screenshotPath })
await testInfo.attach(`pet-status-trigger-${name}`, {
path: screenshotPath,
contentType: 'image/png'
})
}
test.describe('Pet status segment layout', () => {
test('does not reserve empty space after its label', async ({ orcaPage }, testInfo) => {
await waitForSessionReady(orcaPage)
await enableExperimentalPet(orcaPage)
for (const { name, size } of VIEWPORTS) {
await orcaPage.setViewportSize(size)
await assertPetTriggerFitsLabel(orcaPage)
await attachTriggerScreenshot(orcaPage, testInfo, name)
}
})
})