mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
96 lines
3.5 KiB
TypeScript
96 lines
3.5 KiB
TypeScript
import { beforeEach, describe, expect, test } from 'vitest';
|
||
import {
|
||
clampSideWidth,
|
||
HANDLES_TOTAL,
|
||
maxSideWidth,
|
||
PANE_DEFAULT,
|
||
PANE_MIN,
|
||
sideWidthValue,
|
||
usePanesStore,
|
||
} from './PanesStore';
|
||
|
||
const store = () => usePanesStore.getState();
|
||
|
||
describe('clampSideWidth', () => {
|
||
// A roomy container where nothing is constrained.
|
||
const W = 1400;
|
||
|
||
test('passes a comfortable width through unchanged', () => {
|
||
expect(clampSideWidth('library', 300, W, PANE_DEFAULT.preview)).toBe(300);
|
||
expect(clampSideWidth('preview', 400, W, PANE_DEFAULT.library)).toBe(400);
|
||
});
|
||
|
||
test('never goes below the pane minimum', () => {
|
||
expect(clampSideWidth('library', 50, W, PANE_DEFAULT.preview)).toBe(PANE_MIN.library);
|
||
expect(clampSideWidth('preview', 10, W, PANE_DEFAULT.library)).toBe(PANE_MIN.preview);
|
||
});
|
||
|
||
test('caps the width so the editor keeps at least its minimum', () => {
|
||
const other = PANE_DEFAULT.preview;
|
||
const max = W - other - HANDLES_TOTAL - PANE_MIN.editor;
|
||
// Asking for far more than the editor can spare clamps to that maximum.
|
||
expect(clampSideWidth('library', W, W, other)).toBe(max);
|
||
// The editor sits exactly at its minimum at that point.
|
||
expect(W - max - other - HANDLES_TOTAL).toBe(PANE_MIN.editor);
|
||
});
|
||
|
||
test('a container too narrow for all minimums still never drops below the min', () => {
|
||
// 500px total can't fit library(180)+preview(240)+editor(320)+handles.
|
||
expect(clampSideWidth('library', 300, 500, PANE_MIN.preview)).toBe(PANE_MIN.library);
|
||
});
|
||
});
|
||
|
||
describe('sideWidthValue (aria-valuenow, 0–100 per WAI-ARIA APG window splitter)', () => {
|
||
const W = 1400;
|
||
|
||
test('reports 0 at the pane minimum and 100 at the pane maximum', () => {
|
||
const other = PANE_DEFAULT.preview;
|
||
const max = maxSideWidth('library', W, other);
|
||
expect(sideWidthValue('library', PANE_MIN.library, W, other)).toBe(0);
|
||
expect(sideWidthValue('library', max, W, other)).toBe(100);
|
||
});
|
||
|
||
test('reports the midpoint as ~50', () => {
|
||
const other = PANE_DEFAULT.preview;
|
||
const mid = (PANE_MIN.library + maxSideWidth('library', W, other)) / 2;
|
||
expect(sideWidthValue('library', mid, W, other)).toBe(50);
|
||
});
|
||
|
||
test('clamps out-of-range widths into 0–100', () => {
|
||
const other = PANE_DEFAULT.preview;
|
||
expect(sideWidthValue('library', 0, W, other)).toBe(0);
|
||
expect(sideWidthValue('library', 99999, W, other)).toBe(100);
|
||
});
|
||
|
||
test('returns null before layout is known (container width 0)', () => {
|
||
expect(sideWidthValue('library', 280, 0, PANE_DEFAULT.preview)).toBeNull();
|
||
});
|
||
|
||
test('returns null when the range has collapsed (container too narrow)', () => {
|
||
// 500px can't fit all the minimums, so min == max and there is no range.
|
||
expect(sideWidthValue('library', 200, 500, PANE_MIN.preview)).toBeNull();
|
||
});
|
||
});
|
||
|
||
describe('usePanesStore', () => {
|
||
beforeEach(() =>
|
||
store().hydrate({ libraryWidth: PANE_DEFAULT.library, previewWidth: PANE_DEFAULT.preview }),
|
||
);
|
||
|
||
test('setWidth updates the targeted side only', () => {
|
||
store().setWidth('library', 320);
|
||
expect(store().libraryWidth).toBe(320);
|
||
expect(store().previewWidth).toBe(PANE_DEFAULT.preview);
|
||
|
||
store().setWidth('preview', 420);
|
||
expect(store().previewWidth).toBe(420);
|
||
expect(store().libraryWidth).toBe(320);
|
||
});
|
||
|
||
test('hydrate fills missing values from defaults', () => {
|
||
store().hydrate({ libraryWidth: 250 });
|
||
expect(store().libraryWidth).toBe(250);
|
||
expect(store().previewWidth).toBe(PANE_DEFAULT.preview);
|
||
});
|
||
});
|