@@ -214,3 +214,92 @@ describe("override-set orphan cleanup on removeElement", () => {
214214 expect ( overrides [ "hf-sub.style.opacity" ] ) . toBe ( "1" ) ;
215215 } ) ;
216216} ) ;
217+
218+ // ─── setSelection / getSelection / selectionchange ───────────────────────────
219+
220+ describe ( "setSelection" , ( ) => {
221+ it ( "getSelection returns empty array before any setSelection call" , async ( ) => {
222+ const comp = await openComposition ( BASE_HTML ) ;
223+ expect ( comp . getSelection ( ) ) . toEqual ( [ ] ) ;
224+ } ) ;
225+
226+ it ( "setSelection updates getSelection" , async ( ) => {
227+ const comp = await openComposition ( BASE_HTML ) ;
228+ comp . setSelection ( [ "hf-title" ] ) ;
229+ expect ( comp . getSelection ( ) ) . toEqual ( [ "hf-title" ] ) ;
230+ } ) ;
231+
232+ it ( "setSelection with multiple ids" , async ( ) => {
233+ const comp = await openComposition ( BASE_HTML ) ;
234+ comp . setSelection ( [ "hf-title" , "hf-sub" ] ) ;
235+ expect ( comp . getSelection ( ) ) . toEqual ( [ "hf-title" , "hf-sub" ] ) ;
236+ } ) ;
237+
238+ it ( "setSelection([]) clears selection" , async ( ) => {
239+ const comp = await openComposition ( BASE_HTML ) ;
240+ comp . setSelection ( [ "hf-title" ] ) ;
241+ comp . setSelection ( [ ] ) ;
242+ expect ( comp . getSelection ( ) ) . toEqual ( [ ] ) ;
243+ } ) ;
244+
245+ it ( "setSelection fires selectionchange with new ids" , async ( ) => {
246+ const comp = await openComposition ( BASE_HTML ) ;
247+ const calls : string [ ] [ ] = [ ] ;
248+ comp . on ( "selectionchange" , ( ids ) => calls . push ( ids ) ) ;
249+ comp . setSelection ( [ "hf-title" ] ) ;
250+ expect ( calls ) . toEqual ( [ [ "hf-title" ] ] ) ;
251+ } ) ;
252+
253+ it ( "setSelection fires selectionchange with empty array when clearing" , async ( ) => {
254+ const comp = await openComposition ( BASE_HTML ) ;
255+ comp . setSelection ( [ "hf-title" ] ) ;
256+ const calls : string [ ] [ ] = [ ] ;
257+ comp . on ( "selectionchange" , ( ids ) => calls . push ( ids ) ) ;
258+ comp . setSelection ( [ ] ) ;
259+ expect ( calls ) . toEqual ( [ [ ] ] ) ;
260+ } ) ;
261+
262+ it ( "selectionchange listener receives a fresh copy each call" , async ( ) => {
263+ const comp = await openComposition ( BASE_HTML ) ;
264+ const snapshots : string [ ] [ ] = [ ] ;
265+ comp . on ( "selectionchange" , ( ids ) => snapshots . push ( ids ) ) ;
266+ comp . setSelection ( [ "hf-title" ] ) ;
267+ comp . setSelection ( [ "hf-sub" ] ) ;
268+ expect ( snapshots [ 0 ] ) . toEqual ( [ "hf-title" ] ) ;
269+ expect ( snapshots [ 1 ] ) . toEqual ( [ "hf-sub" ] ) ;
270+ } ) ;
271+
272+ it ( "unsubscribed listener does not fire" , async ( ) => {
273+ const comp = await openComposition ( BASE_HTML ) ;
274+ const calls : string [ ] [ ] = [ ] ;
275+ const off = comp . on ( "selectionchange" , ( ids ) => calls . push ( ids ) ) ;
276+ off ( ) ;
277+ comp . setSelection ( [ "hf-title" ] ) ;
278+ expect ( calls ) . toHaveLength ( 0 ) ;
279+ } ) ;
280+
281+ it ( "selection() proxy operates on ids at call time" , async ( ) => {
282+ const comp = await openComposition ( BASE_HTML ) ;
283+ comp . setSelection ( [ "hf-title" ] ) ;
284+ const proxy = comp . selection ( ) ;
285+ expect ( proxy . ids ) . toEqual ( [ "hf-title" ] ) ;
286+ } ) ;
287+
288+ it ( "setSelection does not affect undo stack" , async ( ) => {
289+ const comp = await openComposition ( BASE_HTML ) ;
290+ comp . setStyle ( "hf-title" , { color : "#ff0000" } ) ;
291+ comp . setSelection ( [ "hf-sub" ] ) ;
292+ expect ( comp . canUndo ( ) ) . toBe ( true ) ;
293+ comp . undo ( ) ;
294+ // selection must not have been pushed to history
295+ expect ( comp . canUndo ( ) ) . toBe ( false ) ;
296+ } ) ;
297+
298+ it ( "setSelection does not emit a patch event" , async ( ) => {
299+ const comp = await openComposition ( BASE_HTML ) ;
300+ const patches : unknown [ ] = [ ] ;
301+ comp . on ( "patch" , ( e ) => patches . push ( e ) ) ;
302+ comp . setSelection ( [ "hf-title" ] ) ;
303+ expect ( patches ) . toHaveLength ( 0 ) ;
304+ } ) ;
305+ } ) ;
0 commit comments