diff --git a/dev/window/bwin-update-pane.js b/dev/window/bwin-update-pane.js index d60d0f3..0b767ce 100644 --- a/dev/window/bwin-update-pane.js +++ b/dev/window/bwin-update-pane.js @@ -25,13 +25,13 @@ document.querySelector('#update-pane').addEventListener('click', () => { const content = document.querySelector('#content').value; // Only pass fields the user actually filled in. - const props = { id }; + const props = {}; if (position) props.position = position; if (size) props.size = size; if (title) props.title = title; if (content) props.content = content; - bwin.updatePane(props); + bwin.updatePane(id, props); }); window.bwin = bwin; diff --git a/src/binary-window/binary-window.js b/src/binary-window/binary-window.js index 33a508f..25b0794 100644 --- a/src/binary-window/binary-window.js +++ b/src/binary-window/binary-window.js @@ -68,18 +68,18 @@ export class BinaryWindow extends Frame { } // TODO: support updating glass `actions` (rebuild the action bar/menu in place). - updatePane({ position, size, id, minWidth, minHeight, title, content }) { - const sash = this.rootSash.getById(id); - if (!sash) throw new Error(`[bwin] No sash found with id ${id} when updating pane`); + updatePane(paneSashId, { position, size, minWidth, minHeight, title, content } = {}) { + const sash = this.rootSash.getById(paneSashId); + if (!sash) throw new Error(`[bwin] No sash found with id ${paneSashId} when updating pane`); if (position || size || minWidth || minHeight) { - super.updatePane(id, { position, size, minWidth, minHeight }); + super.updatePane(paneSashId, { position, size, minWidth, minHeight }); } if (title || content) { const glassEl = sash.domNode.querySelector('bw-glass'); if (!glassEl) - throw new Error(`[bwin] No glass found in pane with id ${id} when updating pane`); + throw new Error(`[bwin] No glass found in pane with id ${paneSashId} when updating pane`); updateGlass(glassEl, { title, content }); } } diff --git a/src/binary-window/binary-window.test.js b/src/binary-window/binary-window.test.js index 88e1fa5..dfd243f 100644 --- a/src/binary-window/binary-window.test.js +++ b/src/binary-window/binary-window.test.js @@ -1,56 +1,66 @@ -import { describe, it, expect } from 'vitest'; -import { normActions } from './utils'; -import { DEFAULT_GLASS_ACTIONS } from './glass'; -import { DEFAULT_DETACHED_GLASS_ACTIONS } from './detached-glass'; - -describe('normActions', () => { - it('returns the builtin actions when actions is undefined', () => { - expect(normActions(undefined)).toEqual([DEFAULT_GLASS_ACTIONS, DEFAULT_DETACHED_GLASS_ACTIONS]); +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import { BinaryWindow } from './binary-window'; + +describe('BinaryWindow#updatePane', () => { + let containerEl; + let bwin; + + beforeEach(() => { + containerEl = document.createElement('div'); + document.body.append(containerEl); + + bwin = new BinaryWindow({ + width: 444, + height: 333, + children: [ + { position: 'left', size: '40%', id: 'a', title: 'a', content: 'Pane a' }, + { position: 'right', size: '60%', id: 'b', title: 'b', content: 'Pane b' }, + ], + }); + bwin.mount(containerEl); }); - it('returns [[], []] when actions is null, empty, or not an array', () => { - expect(normActions(null)).toEqual([[], []]); - expect(normActions('a')).toEqual([[], []]); - expect(normActions({})).toEqual([[], []]); - expect(normActions([])).toEqual([[], []]); + afterEach(() => { + containerEl.remove(); }); - it('returns [glassActions, DEFAULT_DETACHED_GLASS_ACTIONS] for a single grouped array', () => { - const a = { label: 'A' }; + function getPaneEl(sashId) { + return bwin.windowElement.querySelector(`[sash-id="${sashId}"]`); + } - expect(normActions([[a]])).toEqual([[a], DEFAULT_DETACHED_GLASS_ACTIONS]); - }); + it('takes the pane sash id as the first positional argument', () => { + bwin.updatePane('a', { title: 'updated a', content: 'updated content a' }); - it('returns [actions, DEFAULT_DETACHED_GLASS_ACTIONS] when actions is a flat array', () => { - const a = { label: 'A' }; - const b = { label: 'B' }; + const titleEl = getPaneEl('a').querySelector('bw-glass-title'); + const contentEl = getPaneEl('a').querySelector('bw-glass-content'); - expect(normActions([a, b])).toEqual([[a, b], DEFAULT_DETACHED_GLASS_ACTIONS]); + expect(titleEl.textContent).toBe('updated a'); + expect(contentEl.textContent).toBe('updated content a'); }); - it('returns [[], detachedGlassActions] when first group is absent', () => { - const b = { label: 'B' }; + it('updates only the targeted pane, leaving siblings untouched', () => { + bwin.updatePane('a', { title: 'updated a' }); - expect(normActions([undefined, [b]])).toEqual([[], [b]]); - expect(normActions([null, [b]])).toEqual([[], [b]]); + expect(getPaneEl('a').querySelector('bw-glass-title').textContent).toBe('updated a'); + expect(getPaneEl('b').querySelector('bw-glass-title').textContent).toBe('b'); }); - it('returns [glassActions, []] when second group is absent', () => { - const a = { label: 'A' }; + it('updates the pane size via the layout path', () => { + bwin.updatePane('a', { size: '20%' }); - expect(normActions([[a], undefined])).toEqual([[a], []]); - expect(normActions([[a], null])).toEqual([[a], []]); + // The split is horizontal (left/right), so size maps to width. + const sashA = bwin.rootSash.getById('a'); + const sashB = bwin.rootSash.getById('b'); + expect(sashA.width).toBeLessThan(sashB.width); }); - it('returns actions as-is when both groups are arrays', () => { - const a = { label: 'A' }; - const b = { label: 'B' }; - const grouped = [[a], [b]]; - - expect(normActions(grouped)).toBe(grouped); + it('throws when no sash matches the given id', () => { + expect(() => bwin.updatePane('nope', { title: 'x' })).toThrow( + '[bwin] No sash found with id nope when updating pane' + ); }); - it('throws when an array is present but neither of the first two slots is one', () => { - expect(() => normActions([null, null, []])).toThrow('[bwin] Invalid actions format'); + it('does not require an options object', () => { + expect(() => bwin.updatePane('a')).not.toThrow(); }); }); diff --git a/src/binary-window/utils.test.js b/src/binary-window/utils.test.js new file mode 100644 index 0000000..88e1fa5 --- /dev/null +++ b/src/binary-window/utils.test.js @@ -0,0 +1,56 @@ +import { describe, it, expect } from 'vitest'; +import { normActions } from './utils'; +import { DEFAULT_GLASS_ACTIONS } from './glass'; +import { DEFAULT_DETACHED_GLASS_ACTIONS } from './detached-glass'; + +describe('normActions', () => { + it('returns the builtin actions when actions is undefined', () => { + expect(normActions(undefined)).toEqual([DEFAULT_GLASS_ACTIONS, DEFAULT_DETACHED_GLASS_ACTIONS]); + }); + + it('returns [[], []] when actions is null, empty, or not an array', () => { + expect(normActions(null)).toEqual([[], []]); + expect(normActions('a')).toEqual([[], []]); + expect(normActions({})).toEqual([[], []]); + expect(normActions([])).toEqual([[], []]); + }); + + it('returns [glassActions, DEFAULT_DETACHED_GLASS_ACTIONS] for a single grouped array', () => { + const a = { label: 'A' }; + + expect(normActions([[a]])).toEqual([[a], DEFAULT_DETACHED_GLASS_ACTIONS]); + }); + + it('returns [actions, DEFAULT_DETACHED_GLASS_ACTIONS] when actions is a flat array', () => { + const a = { label: 'A' }; + const b = { label: 'B' }; + + expect(normActions([a, b])).toEqual([[a, b], DEFAULT_DETACHED_GLASS_ACTIONS]); + }); + + it('returns [[], detachedGlassActions] when first group is absent', () => { + const b = { label: 'B' }; + + expect(normActions([undefined, [b]])).toEqual([[], [b]]); + expect(normActions([null, [b]])).toEqual([[], [b]]); + }); + + it('returns [glassActions, []] when second group is absent', () => { + const a = { label: 'A' }; + + expect(normActions([[a], undefined])).toEqual([[a], []]); + expect(normActions([[a], null])).toEqual([[a], []]); + }); + + it('returns actions as-is when both groups are arrays', () => { + const a = { label: 'A' }; + const b = { label: 'B' }; + const grouped = [[a], [b]]; + + expect(normActions(grouped)).toBe(grouped); + }); + + it('throws when an array is present but neither of the first two slots is one', () => { + expect(() => normActions([null, null, []])).toThrow('[bwin] Invalid actions format'); + }); +});