diff --git a/.changeset/smooth-carrots-flow.md b/.changeset/smooth-carrots-flow.md new file mode 100644 index 00000000..0638cf22 --- /dev/null +++ b/.changeset/smooth-carrots-flow.md @@ -0,0 +1,5 @@ +--- +"@usebruno/api-docs": patch +--- + +test(playground): cover remaining layout persistence cases diff --git a/packages/bruno-api-docs/e2e/components/playground.component.ts b/packages/bruno-api-docs/e2e/components/playground.component.ts index b8e5df11..277a4966 100644 --- a/packages/bruno-api-docs/e2e/components/playground.component.ts +++ b/packages/bruno-api-docs/e2e/components/playground.component.ts @@ -181,4 +181,11 @@ export class PlaygroundComponent extends BaseComponent { async grabInlineResizer(): Promise { await this.grabHandle(this.inlineResizer); } + + async storedItem(area: 'session' | 'local', key: string): Promise { + return this.page.evaluate( + ([area, key]) => (area === 'local' ? localStorage : sessionStorage).getItem(key), + [area, key] as [typeof area, string] + ); + } } diff --git a/packages/bruno-api-docs/e2e/tests/playground/layout-persistence.spec.ts b/packages/bruno-api-docs/e2e/tests/playground/layout-persistence.spec.ts index 72700fd5..016fa4cc 100644 --- a/packages/bruno-api-docs/e2e/tests/playground/layout-persistence.spec.ts +++ b/packages/bruno-api-docs/e2e/tests/playground/layout-persistence.spec.ts @@ -1,4 +1,5 @@ import { test, expect } from '../../playwright'; +import { DOCK_STORAGE_KEY, HEIGHT_STORAGE_KEY } from '../../../src/utils/playgroundDock'; const DESKTOP = { width: 1280, height: 900 }; const openAt = (dock: string): string => `/#/?pg=1&dock=${dock}`; @@ -16,6 +17,8 @@ test.describe('playground layout persistence (desktop)', () => { await playground.releasePointer(); const resized = await playground.bottomPanelHeight(); expect(resized).toBeGreaterThan(560); + expect(await playground.storedItem('local', HEIGHT_STORAGE_KEY)).toBeNull(); + expect(Number(await playground.storedItem('session', HEIGHT_STORAGE_KEY))).toBeGreaterThan(560); await page.reload(); await expect(playground.bottomPanel).toBeVisible(); @@ -47,6 +50,8 @@ test.describe('playground layout persistence (desktop)', () => { await playground.selectDock('inline'); await expect(playground.inlinePanel).toBeVisible(); + expect(await playground.storedItem('session', DOCK_STORAGE_KEY)).toBe('inline'); + expect(await playground.storedItem('local', DOCK_STORAGE_KEY)).toBeNull(); await playground.close(); await expect(playground.header).toHaveCount(0); @@ -57,9 +62,9 @@ test.describe('playground layout persistence (desktop)', () => { }); test('a dock in the URL wins over the stored dock', async ({ page, playground }) => { - await page.addInitScript(() => { - sessionStorage.setItem('oc-docs:playgroundDock', 'inline'); - }); + await page.addInitScript((key) => { + sessionStorage.setItem(key, 'inline'); + }, DOCK_STORAGE_KEY); await page.goto(openAt('modal')); await expect(playground.modalPanel).toBeVisible(); @@ -71,9 +76,9 @@ test.describe('playground layout persistence (desktop)', () => { requestPage, playground }) => { - await page.addInitScript(() => { - sessionStorage.setItem('oc-docs:playgroundDock', 'sideways'); - }); + await page.addInitScript((key) => { + sessionStorage.setItem(key, 'sideways'); + }, DOCK_STORAGE_KEY); await requestPage.open(REQUEST_PATH); await requestPage.urlBar.tryButton.click(); @@ -135,4 +140,78 @@ test.describe('playground layout persistence (desktop)', () => { await expect(playground.content).toBeVisible(); expect(Math.abs((await playground.bottomPanelHeight()) - resized)).toBeLessThan(5); }); + + test('keeps the bottom height after the inline width is resized', async ({ page, playground }) => { + await playground.open('bottom'); + await playground.grabBottomResizer(); + await playground.movePointerToY(300); + await playground.releasePointer(); + const height = await playground.bottomPanelHeight(); + expect(height).toBeGreaterThan(560); + + await playground.selectDock('inline'); + await playground.grabInlineResizer(); + await playground.movePointerToX(500); + await playground.releasePointer(); + const width = await playground.inlinePanelWidth(); + expect(width).toBeGreaterThan(700); + + await playground.selectDock('bottom'); + expect(Math.abs((await playground.bottomPanelHeight()) - height)).toBeLessThan(5); + + await page.reload(); + await expect(playground.bottomPanel).toBeVisible(); + expect(Math.abs((await playground.bottomPanelHeight()) - height)).toBeLessThan(5); + + await playground.selectDock('inline'); + expect(Math.abs((await playground.inlinePanelWidth()) - width)).toBeLessThan(5); + }); + + test('opens at the default bottom height when nothing is stored', async ({ playground }) => { + await playground.open('bottom'); + await expect(playground.bottomPanel).toBeVisible(); + const height = await playground.bottomPanelHeight(); + expect(height).toBeGreaterThan(520); + expect(height).toBeLessThanOrEqual(560); + }); + + test('opens at the default inline width when nothing is stored', async ({ playground }) => { + await playground.open('inline'); + await expect(playground.inlinePanel).toBeVisible(); + const width = await playground.inlinePanelWidth(); + expect(width).toBeGreaterThan(490); + expect(width).toBeLessThanOrEqual(540); + }); + + test('ignores a corrupt stored height and uses the default', async ({ page, playground }) => { + await page.addInitScript((key) => { + sessionStorage.setItem(key, 'not-a-number'); + }, HEIGHT_STORAGE_KEY); + + await playground.open('bottom'); + await expect(playground.bottomPanel).toBeVisible(); + const height = await playground.bottomPanelHeight(); + expect(height).toBeGreaterThan(520); + expect(height).toBeLessThanOrEqual(560); + }); + + test('clamps an out-of-range stored height to the viewport', async ({ page, playground }) => { + await page.addInitScript((key) => { + sessionStorage.setItem(key, '99999'); + }, HEIGHT_STORAGE_KEY); + + await playground.open('bottom'); + await expect(playground.bottomPanel).toBeVisible(); + const height = await playground.bottomPanelHeight(); + expect(height).toBeGreaterThan(850); + expect(height).toBeLessThanOrEqual(900); + }); + + test('a fresh Try it with no stored dock opens in the bottom dock', async ({ requestPage, playground }) => { + await requestPage.open(REQUEST_PATH); + await requestPage.urlBar.tryButton.click(); + await expect(playground.bottomPanel).toBeVisible(); + await expect(playground.inlinePanel).toHaveCount(0); + await expect(playground.modalPanel).toHaveCount(0); + }); }); diff --git a/packages/bruno-api-docs/src/utils/playgroundDock.ts b/packages/bruno-api-docs/src/utils/playgroundDock.ts index 4a47f28e..917f4ae8 100644 --- a/packages/bruno-api-docs/src/utils/playgroundDock.ts +++ b/packages/bruno-api-docs/src/utils/playgroundDock.ts @@ -12,6 +12,9 @@ export const isDockMode = (value: string | null | undefined): value is DockMode value === 'inline' || value === 'bottom' || value === 'modal'; export const DOCK_STORAGE_KEY = 'oc-docs:playgroundDock'; +export const HEIGHT_STORAGE_KEY = 'oc-docs:playgroundBottomHeight'; +export const WIDTH_STORAGE_KEY = 'oc-docs:playgroundInlineWidth'; +export const COLLAPSED_STORAGE_KEY = 'oc-docs:playgroundBottomCollapsed'; export const readStoredDock = (storage: Storage | null): DockMode | null => { if (!storage) return null;