llm-semantic-visualizer / tests /arithmeticResultsScroll.test.js
hbauzan's picture
publish(hf): Space snapshot with injected README frontmatter
39508ae
Raw
History Blame Contribute Delete
4.81 kB
import { readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
import { describe, expect, it } from 'vitest';
import {
ARITHMETIC_TOP10_SCROLL,
RESULTS_LIST_MIN_PX,
resolveResultsListMaxHeightPx,
shouldScrollArithmeticPanel,
} from '../src/ui/arithmeticResultsScroll.js';
import { MOBILE_MQ } from '../src/ui/CollapsibleDock.js';
import { Sidebar } from '../src/ui/Sidebar.js';
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
const css = readFileSync(join(root, 'src/style.css'), 'utf8');
describe('resolveResultsListMaxHeightPx — feedback loop', () => {
it('never collapses below the floor on short phone landscape', () => {
// iPhone-class landscape ~844×390
const h = resolveResultsListMaxHeightPx({ width: 844, height: 390 }, { isMobile: true });
expect(h).toBeGreaterThanOrEqual(RESULTS_LIST_MIN_PX);
expect(h).toBeLessThanOrEqual(200);
});
it('never collapses when desktop vh is below the old 380px magic offset', () => {
const h = resolveResultsListMaxHeightPx({ width: 1280, height: 360 }, { isMobile: false });
expect(h).toBeGreaterThanOrEqual(RESULTS_LIST_MIN_PX);
});
it('caps at desktop/mobile ceilings on tall screens', () => {
expect(resolveResultsListMaxHeightPx({ width: 1440, height: 900 }, { isMobile: false })).toBe(280);
expect(resolveResultsListMaxHeightPx({ width: 390, height: 844 }, { isMobile: true })).toBe(200);
});
});
describe('shouldScrollArithmeticPanel', () => {
it('switches to panel scroll on short viewports (landscape phone)', () => {
expect(shouldScrollArithmeticPanel({ height: 390 })).toBe(true);
expect(shouldScrollArithmeticPanel({ height: 844 })).toBe(false);
expect(shouldScrollArithmeticPanel({ height: 560 })).toBe(true);
expect(shouldScrollArithmeticPanel({ height: 561 })).toBe(false);
});
});
describe('ARITHMETIC_TOP10_SCROLL CSS contract', () => {
it('keeps floored max-height expressions in CSS', () => {
expect(css).toContain(ARITHMETIC_TOP10_SCROLL.desktopMaxHeight);
expect(css).toContain(ARITHMETIC_TOP10_SCROLL.mobileMaxHeight);
expect(css).toContain('@media (max-height: 560px)');
expect(css).toMatch(/#sidebar-panel\s+\.results-list\s*\{[^}]*overflow-y:\s*auto/s);
});
it('mobile MQ includes short landscape phones (hover:none)', () => {
expect(MOBILE_MQ).toContain('max-height: 500px');
expect(MOBILE_MQ).toContain('hover: none');
expect(css).toContain('(max-height: 500px) and (hover: none)');
});
});
describe('Sidebar Top-10 markup', () => {
function createMockElement(tagName = 'div') {
const children = [];
const classList = new Set();
let _className = '';
let _innerHTML = '';
const el = {
tagName: tagName.toUpperCase(),
children,
classList: {
add: (c) => { classList.add(c); _className = [...classList].join(' '); },
contains: (c) => classList.has(c),
},
appendChild: (child) => { children.push(child); return child; },
querySelector: (sel) => {
const clean = sel.replace('#', '').replace('.', '');
for (const child of children) {
if (child.id === clean || child.classList?.contains?.(clean)) return child;
const found = child.querySelector?.(sel);
if (found) return found;
}
return null;
},
addEventListener: () => {},
set innerHTML(val) {
_innerHTML = String(val);
if (_innerHTML.includes('results-list')) {
const ul = createMockElement('ul');
ul.id = 'results-list';
ul.className = 'results-list';
el.appendChild(ul);
const form = createMockElement('form');
form.id = 'arithmetic-form';
el.appendChild(form);
const btn = createMockElement('button');
btn.id = 'btn-calculate';
el.appendChild(btn);
}
},
get innerHTML() { return _innerHTML; },
set className(val) {
_className = val || '';
classList.clear();
String(val).split(/\s+/).forEach((c) => { if (c) classList.add(c); });
},
get className() { return _className; },
id: '',
textContent: '',
};
return el;
}
if (typeof global.document === 'undefined') {
global.document = {
createElement: (tag) => createMockElement(tag),
body: createMockElement('body'),
};
}
it('mounts a results-list for Top-10 neighbors', () => {
const parent = createMockElement('div');
const sidebar = new Sidebar(parent, async () => {});
expect(sidebar.resultsList).not.toBeNull();
expect(sidebar.resultsList.id).toBe('results-list');
expect(String(sidebar.element.innerHTML)).toContain('results-list');
});
});