bard-tag_field 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,684 @@
1
+ import { expect } from '@esm-bundle/chai'
2
+ import { spy } from 'sinon'
3
+ import '../src/input-tag.js'
4
+ import {
5
+ setupGlobalTestHooks,
6
+ setupInputTag,
7
+ waitForUpdate,
8
+ getTagElements,
9
+ getTagValues
10
+ } from './lib/test-utils.js'
11
+
12
+ describe('API Methods', () => {
13
+ setupGlobalTestHooks()
14
+
15
+ describe('Focus Method', () => {
16
+ it('should focus the internal input when focus() is called', async () => {
17
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
18
+
19
+ const focusSpy = spy(inputTag._taggleInputTarget, 'focus')
20
+
21
+ inputTag.focus()
22
+ await waitForUpdate()
23
+
24
+ expect(focusSpy.called).to.be.true
25
+ focusSpy.restore()
26
+ })
27
+
28
+ it('should work when called multiple times', async () => {
29
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
30
+
31
+ const focusSpy = spy(inputTag._taggleInputTarget, 'focus')
32
+
33
+ inputTag.focus()
34
+ inputTag.focus()
35
+ inputTag.focus()
36
+ await waitForUpdate()
37
+
38
+ expect(focusSpy.callCount).to.be.at.least(3)
39
+ focusSpy.restore()
40
+ })
41
+
42
+ it('should work even when element is not visible', async () => {
43
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple style="display: none;"></input-tag>')
44
+
45
+ // Should not throw error
46
+ expect(() => {
47
+ inputTag.focus()
48
+ }).to.not.throw()
49
+ })
50
+
51
+ it('should handle focus when input-tag is disabled', async () => {
52
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
53
+
54
+ // Disable the component
55
+ inputTag.disable()
56
+
57
+ // Focus should still work at the API level
58
+ expect(() => {
59
+ inputTag.focus()
60
+ }).to.not.throw()
61
+ })
62
+ })
63
+
64
+ describe('Reset Method', () => {
65
+ it('should clear all tags when reset() is called', async () => {
66
+ const inputTag = await setupInputTag(`
67
+ <input-tag name="tags" multiple>
68
+ <tag-option value="tag1">Tag 1</tag-option>
69
+ <tag-option value="tag2">Tag 2</tag-option>
70
+ <tag-option value="tag3">Tag 3</tag-option>
71
+ </input-tag>
72
+ `)
73
+
74
+ expect(getTagElements(inputTag)).to.have.length(3)
75
+
76
+ inputTag.reset()
77
+ await waitForUpdate()
78
+
79
+ expect(getTagElements(inputTag)).to.have.length(0)
80
+ expect(getTagValues(inputTag)).to.deep.equal([])
81
+ })
82
+
83
+ it('should clear input field when reset() is called', async () => {
84
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
85
+
86
+ inputTag._taggleInputTarget.value = 'pending input'
87
+
88
+ inputTag.reset()
89
+ await waitForUpdate()
90
+
91
+ expect(inputTag._taggleInputTarget.value).to.equal('')
92
+ })
93
+
94
+ it('should work on empty input-tag', async () => {
95
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
96
+
97
+ expect(() => {
98
+ inputTag.reset()
99
+ }).to.not.throw()
100
+
101
+ expect(getTagElements(inputTag)).to.have.length(0)
102
+ })
103
+
104
+ it('should work multiple times', async () => {
105
+ const inputTag = await setupInputTag(`
106
+ <input-tag name="tags" multiple>
107
+ <tag-option value="test">Test</tag-option>
108
+ </input-tag>
109
+ `)
110
+
111
+ inputTag.reset()
112
+ inputTag.reset()
113
+ inputTag.reset()
114
+ await waitForUpdate()
115
+
116
+ expect(getTagElements(inputTag)).to.have.length(0)
117
+ })
118
+
119
+ it('should allow adding tags after reset', async () => {
120
+ const inputTag = await setupInputTag(`
121
+ <input-tag name="tags" multiple>
122
+ <tag-option value="original">Original</tag-option>
123
+ </input-tag>
124
+ `)
125
+
126
+ inputTag.reset()
127
+ await waitForUpdate()
128
+
129
+ inputTag.add('after-reset')
130
+ await waitForUpdate()
131
+
132
+ expect(getTagElements(inputTag)).to.have.length(1)
133
+ expect(getTagValues(inputTag)).to.deep.equal(['after-reset'])
134
+ })
135
+ })
136
+
137
+ describe('Validation Methods', () => {
138
+ describe('checkValidity()', () => {
139
+ it('should return true for valid non-required field', async () => {
140
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
141
+
142
+ expect(inputTag.checkValidity()).to.be.true
143
+ })
144
+
145
+ it('should return false for empty required field', async () => {
146
+ const inputTag = await setupInputTag('<input-tag name="tags" required multiple></input-tag>')
147
+
148
+ expect(inputTag.checkValidity()).to.be.false
149
+ })
150
+
151
+ it('should return true for required field with tags', async () => {
152
+ const inputTag = await setupInputTag(`
153
+ <input-tag name="tags" required multiple>
154
+ <tag-option value="present">Present</tag-option>
155
+ </input-tag>
156
+ `)
157
+
158
+ expect(inputTag.checkValidity()).to.be.true
159
+ })
160
+
161
+ it('should update validity when tags are added to required field', async () => {
162
+ const inputTag = await setupInputTag('<input-tag name="tags" required multiple></input-tag>')
163
+
164
+ expect(inputTag.checkValidity()).to.be.false
165
+
166
+ inputTag.add('new-tag')
167
+ await waitForUpdate()
168
+
169
+ expect(inputTag.checkValidity()).to.be.true
170
+ })
171
+
172
+ it('should update validity when tags are removed from required field', async () => {
173
+ const inputTag = await setupInputTag(`
174
+ <input-tag name="tags" required multiple>
175
+ <tag-option value="only-tag">Only Tag</tag-option>
176
+ </input-tag>
177
+ `)
178
+
179
+ expect(inputTag.checkValidity()).to.be.true
180
+
181
+ inputTag.removeAll()
182
+ await waitForUpdate()
183
+
184
+ expect(inputTag.checkValidity()).to.be.false
185
+ })
186
+
187
+ it('should delegate to internal input validation', async () => {
188
+ const inputTag = await setupInputTag('<input-tag name="tags" required multiple></input-tag>')
189
+
190
+ // Set custom validity on internal input
191
+ inputTag._taggleInputTarget.setCustomValidity('Custom error message')
192
+
193
+ expect(inputTag.checkValidity()).to.be.false
194
+
195
+ // Clear custom validity
196
+ inputTag._taggleInputTarget.setCustomValidity('')
197
+ inputTag.add('valid-tag')
198
+ await waitForUpdate()
199
+
200
+ expect(inputTag.checkValidity()).to.be.true
201
+ })
202
+ })
203
+
204
+ describe('reportValidity()', () => {
205
+ it('should return true for valid field', async () => {
206
+ const inputTag = await setupInputTag(`
207
+ <input-tag name="tags" required multiple>
208
+ <tag-option value="valid">Valid</tag-option>
209
+ </input-tag>
210
+ `)
211
+
212
+ expect(inputTag.reportValidity()).to.be.true
213
+ })
214
+
215
+ it('should return false for invalid field', async () => {
216
+ const inputTag = await setupInputTag('<input-tag name="tags" required multiple></input-tag>')
217
+
218
+ expect(inputTag.reportValidity()).to.be.false
219
+ })
220
+
221
+ it('should show validation message for invalid field', async () => {
222
+ const inputTag = await setupInputTag('<input-tag name="tags" required multiple></input-tag>')
223
+
224
+ // This would normally show browser validation UI
225
+ const result = inputTag.reportValidity()
226
+
227
+ expect(result).to.be.false
228
+ expect(inputTag._taggleInputTarget.validationMessage).to.not.be.empty
229
+ })
230
+
231
+ it('should delegate to internal input reportValidity', async () => {
232
+ const inputTag = await setupInputTag('<input-tag name="tags" required multiple></input-tag>')
233
+
234
+ inputTag._taggleInputTarget.setCustomValidity('Custom validation message')
235
+
236
+ const result = inputTag.reportValidity()
237
+
238
+ expect(result).to.be.false
239
+ expect(inputTag._taggleInputTarget.validationMessage).to.equal('Custom validation message')
240
+ })
241
+ })
242
+ })
243
+
244
+ describe('Value Getter and Setter', () => {
245
+ describe('Value Getter', () => {
246
+ it('should return array of tag values for multiple mode', async () => {
247
+ const inputTag = await setupInputTag(`
248
+ <input-tag name="tags" multiple>
249
+ <tag-option value="tag1">Tag 1</tag-option>
250
+ <tag-option value="tag2">Tag 2</tag-option>
251
+ </input-tag>
252
+ `)
253
+
254
+ expect(inputTag.value).to.deep.equal(['tag1', 'tag2'])
255
+ })
256
+
257
+ it('should return empty array for no tags in multiple mode', async () => {
258
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
259
+
260
+ expect(inputTag.value).to.deep.equal([])
261
+ })
262
+
263
+ it('should return string value for single mode with tag', async () => {
264
+ const inputTag = await setupInputTag(`
265
+ <input-tag name="tag">
266
+ <tag-option value="single-tag">Single Tag</tag-option>
267
+ </input-tag>
268
+ `)
269
+
270
+ expect(inputTag.value).to.equal('single-tag')
271
+ })
272
+
273
+ it('should return empty string for no tags in single mode', async () => {
274
+ const inputTag = await setupInputTag('<input-tag name="tag"></input-tag>')
275
+
276
+ expect(inputTag.value).to.equal('')
277
+ })
278
+
279
+ it('should return current values after modifications in multiple mode', async () => {
280
+ const inputTag = await setupInputTag(`
281
+ <input-tag name="tags" multiple>
282
+ <tag-option value="initial">Initial</tag-option>
283
+ </input-tag>
284
+ `)
285
+
286
+ expect(inputTag.value).to.deep.equal(['initial'])
287
+
288
+ inputTag.add('added')
289
+ await waitForUpdate()
290
+
291
+ expect(inputTag.value).to.deep.equal(['initial', 'added'])
292
+
293
+ inputTag.remove('initial')
294
+ await waitForUpdate()
295
+
296
+ expect(inputTag.value).to.deep.equal(['added'])
297
+ })
298
+
299
+ it('should return current value after modifications in single mode', async () => {
300
+ const inputTag = await setupInputTag(`
301
+ <input-tag name="tag">
302
+ <tag-option value="initial">Initial</tag-option>
303
+ </input-tag>
304
+ `)
305
+
306
+ expect(inputTag.value).to.equal('initial')
307
+
308
+ inputTag.remove('initial')
309
+ await waitForUpdate()
310
+
311
+ expect(inputTag.value).to.equal('')
312
+
313
+ inputTag.add('replacement')
314
+ await waitForUpdate()
315
+
316
+ expect(inputTag.value).to.equal('replacement')
317
+ })
318
+ })
319
+
320
+ describe('Value Setter', () => {
321
+ it('should set tag values from array in multiple mode', async () => {
322
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
323
+
324
+ inputTag.value = ['new1', 'new2', 'new3']
325
+ await waitForUpdate()
326
+
327
+ expect(getTagElements(inputTag)).to.have.length(3)
328
+ expect(getTagValues(inputTag)).to.deep.equal(['new1', 'new2', 'new3'])
329
+ expect(inputTag.value).to.deep.equal(['new1', 'new2', 'new3'])
330
+ })
331
+
332
+ it('should set tag value from string in single mode', async () => {
333
+ const inputTag = await setupInputTag('<input-tag name="tag"></input-tag>')
334
+
335
+ inputTag.value = 'single-tag'
336
+ await waitForUpdate()
337
+
338
+ expect(getTagElements(inputTag)).to.have.length(1)
339
+ expect(getTagValues(inputTag)).to.deep.equal(['single-tag'])
340
+ expect(inputTag.value).to.equal('single-tag')
341
+ })
342
+
343
+ it('should replace existing tags when setting array value in multiple mode', async () => {
344
+ const inputTag = await setupInputTag(`
345
+ <input-tag name="tags" multiple>
346
+ <tag-option value="old1">Old 1</tag-option>
347
+ <tag-option value="old2">Old 2</tag-option>
348
+ </input-tag>
349
+ `)
350
+
351
+ inputTag.value = ['replacement1', 'replacement2']
352
+ await waitForUpdate()
353
+
354
+ expect(getTagElements(inputTag)).to.have.length(2)
355
+ expect(getTagValues(inputTag)).to.deep.equal(['replacement1', 'replacement2'])
356
+ expect(inputTag.value).to.deep.equal(['replacement1', 'replacement2'])
357
+ })
358
+
359
+ it('should replace existing tag when setting string value in single mode', async () => {
360
+ const inputTag = await setupInputTag(`
361
+ <input-tag name="tag">
362
+ <tag-option value="old">Old</tag-option>
363
+ </input-tag>
364
+ `)
365
+
366
+ inputTag.value = 'replacement'
367
+ await waitForUpdate()
368
+
369
+ expect(getTagElements(inputTag)).to.have.length(1)
370
+ expect(getTagValues(inputTag)).to.deep.equal(['replacement'])
371
+ expect(inputTag.value).to.equal('replacement')
372
+ })
373
+
374
+ it('should clear tags when setting empty array in multiple mode', async () => {
375
+ const inputTag = await setupInputTag(`
376
+ <input-tag name="tags" multiple>
377
+ <tag-option value="will-be-cleared">Will Be Cleared</tag-option>
378
+ </input-tag>
379
+ `)
380
+
381
+ inputTag.value = []
382
+ await waitForUpdate()
383
+
384
+ expect(getTagElements(inputTag)).to.have.length(0)
385
+ expect(getTagValues(inputTag)).to.deep.equal([])
386
+ expect(inputTag.value).to.deep.equal([])
387
+ })
388
+
389
+ it('should clear tag when setting empty string in single mode', async () => {
390
+ const inputTag = await setupInputTag(`
391
+ <input-tag name="tag">
392
+ <tag-option value="will-be-cleared">Will Be Cleared</tag-option>
393
+ </input-tag>
394
+ `)
395
+
396
+ inputTag.value = ''
397
+ await waitForUpdate()
398
+
399
+ expect(getTagElements(inputTag)).to.have.length(0)
400
+ expect(getTagValues(inputTag)).to.deep.equal([])
401
+ expect(inputTag.value).to.equal('')
402
+ })
403
+
404
+ it('should handle string value in single mode', async () => {
405
+ const inputTag = await setupInputTag('<input-tag name="tag"></input-tag>')
406
+
407
+ inputTag.value = 'single-value'
408
+ await waitForUpdate()
409
+
410
+ expect(getTagElements(inputTag)).to.have.length(1)
411
+ expect(getTagValues(inputTag)).to.deep.equal(['single-value'])
412
+ expect(inputTag.value).to.equal('single-value')
413
+ })
414
+
415
+ it('should handle array value in single mode (for backward compatibility)', async () => {
416
+ const inputTag = await setupInputTag('<input-tag name="tag"></input-tag>')
417
+
418
+ inputTag.value = ['single-value']
419
+ await waitForUpdate()
420
+
421
+ expect(getTagElements(inputTag)).to.have.length(1)
422
+ expect(getTagValues(inputTag)).to.deep.equal(['single-value'])
423
+ expect(inputTag.value).to.equal('single-value')
424
+ })
425
+
426
+ it('should trigger change event when array value is set programmatically in multiple mode', async () => {
427
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
428
+
429
+ let changeEventFired = false
430
+ inputTag.addEventListener('change', () => {
431
+ changeEventFired = true
432
+ })
433
+
434
+ inputTag.value = ['programmatic']
435
+ await waitForUpdate()
436
+
437
+ expect(changeEventFired).to.be.true
438
+ })
439
+
440
+ it('should trigger change event when string value is set programmatically in single mode', async () => {
441
+ const inputTag = await setupInputTag('<input-tag name="tag"></input-tag>')
442
+
443
+ let changeEventFired = false
444
+ inputTag.addEventListener('change', () => {
445
+ changeEventFired = true
446
+ })
447
+
448
+ inputTag.value = 'programmatic'
449
+ await waitForUpdate()
450
+
451
+ expect(changeEventFired).to.be.true
452
+ })
453
+
454
+ it('should not trigger change event when array value is set to same value in multiple mode', async () => {
455
+ const inputTag = await setupInputTag(`
456
+ <input-tag name="tags" multiple>
457
+ <tag-option value="same">Same</tag-option>
458
+ </input-tag>
459
+ `)
460
+
461
+ let changeEventFired = false
462
+ inputTag.addEventListener('change', () => {
463
+ changeEventFired = true
464
+ })
465
+
466
+ inputTag.value = ['same']
467
+ await waitForUpdate()
468
+
469
+ expect(changeEventFired).to.be.false
470
+ })
471
+
472
+ it('should not trigger change event when string value is set to same value in single mode', async () => {
473
+ const inputTag = await setupInputTag(`
474
+ <input-tag name="tag">
475
+ <tag-option value="same">Same</tag-option>
476
+ </input-tag>
477
+ `)
478
+
479
+ let changeEventFired = false
480
+ inputTag.addEventListener('change', () => {
481
+ changeEventFired = true
482
+ })
483
+
484
+ inputTag.value = 'same'
485
+ await waitForUpdate()
486
+
487
+ expect(changeEventFired).to.be.false
488
+ })
489
+ })
490
+ })
491
+
492
+ describe('Property Getters', () => {
493
+ describe('Form Property', () => {
494
+ it('should return associated form element', async () => {
495
+ document.body.innerHTML = `
496
+ <form id="test-form">
497
+ <input-tag name="tags" multiple></input-tag>
498
+ </form>
499
+ `
500
+ const form = document.querySelector('#test-form')
501
+ const inputTag = document.querySelector('input-tag')
502
+
503
+ await waitForUpdate(100)
504
+
505
+ expect(inputTag.form).to.equal(form)
506
+ })
507
+
508
+ it('should return null when not in a form', async () => {
509
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
510
+
511
+ expect(inputTag.form).to.be.null
512
+ })
513
+ })
514
+
515
+ describe('Name Property', () => {
516
+ it('should return name attribute value', async () => {
517
+ const inputTag = await setupInputTag('<input-tag name="test-name" multiple></input-tag>')
518
+
519
+ expect(inputTag.name).to.equal('test-name')
520
+ })
521
+
522
+ it('should return null when name attribute is not set', async () => {
523
+ const inputTag = await setupInputTag('<input-tag multiple></input-tag>')
524
+
525
+ expect(inputTag.name).to.be.null
526
+ })
527
+
528
+ it('should update when name attribute changes', async () => {
529
+ const inputTag = await setupInputTag('<input-tag name="original-name" multiple></input-tag>')
530
+
531
+ expect(inputTag.name).to.equal('original-name')
532
+
533
+ inputTag.setAttribute('name', 'updated-name')
534
+ expect(inputTag.name).to.equal('updated-name')
535
+ })
536
+ })
537
+
538
+ describe('Options Property', () => {
539
+ it('should return options from associated datalist', async () => {
540
+ document.body.innerHTML = `
541
+ <input-tag name="tags" list="test-list" multiple></input-tag>
542
+ <datalist id="test-list">
543
+ <option value="option1">Option 1</option>
544
+ <option value="option2">Option 2</option>
545
+ </datalist>
546
+ `
547
+ const inputTag = document.querySelector('input-tag')
548
+
549
+ await waitForUpdate(100)
550
+
551
+ expect(inputTag.options).to.deep.equal(['option1', 'option2'])
552
+ })
553
+
554
+ it('should return empty array when no datalist is associated', async () => {
555
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
556
+
557
+ expect(inputTag.options).to.deep.equal([])
558
+ })
559
+
560
+ it('should update when datalist changes', async () => {
561
+ document.body.innerHTML = `
562
+ <input-tag name="tags" list="dynamic-list" multiple></input-tag>
563
+ <datalist id="dynamic-list">
564
+ <option value="initial">Initial</option>
565
+ </datalist>
566
+ `
567
+ const inputTag = document.querySelector('input-tag')
568
+ const datalist = document.querySelector('#dynamic-list')
569
+
570
+ await waitForUpdate(100)
571
+
572
+ expect(inputTag.options).to.deep.equal(['initial'])
573
+
574
+ const newOption = document.createElement('option')
575
+ newOption.value = 'added'
576
+ datalist.appendChild(newOption)
577
+
578
+ expect(inputTag.options).to.deep.equal(['initial', 'added'])
579
+ })
580
+ })
581
+ })
582
+
583
+ describe('Public API Methods', () => {
584
+ it('should provide add/remove/removeAll methods', async () => {
585
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
586
+
587
+ expect(typeof inputTag.add).to.equal('function')
588
+ expect(typeof inputTag.remove).to.equal('function')
589
+ expect(typeof inputTag.removeAll).to.equal('function')
590
+ expect(typeof inputTag.has).to.equal('function')
591
+ })
592
+
593
+ it('should allow manipulation via public API methods', async () => {
594
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
595
+
596
+ // Test add
597
+ inputTag.add('public-api-tag')
598
+ await waitForUpdate()
599
+
600
+ expect(getTagValues(inputTag)).to.deep.equal(['public-api-tag'])
601
+
602
+ // Test tags getter
603
+ expect(inputTag.tags).to.deep.equal(['public-api-tag'])
604
+
605
+ // Test has
606
+ expect(inputTag.has('public-api-tag')).to.be.true
607
+ expect(inputTag.has('nonexistent')).to.be.false
608
+
609
+ // Test remove
610
+ inputTag.remove('public-api-tag')
611
+ await waitForUpdate()
612
+
613
+ expect(getTagValues(inputTag)).to.deep.equal([])
614
+ })
615
+
616
+ it('should support disable and enable methods', async () => {
617
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
618
+
619
+ expect(typeof inputTag.disable).to.equal('function')
620
+ expect(typeof inputTag.enable).to.equal('function')
621
+
622
+ // These should not throw
623
+ expect(() => {
624
+ inputTag.disable()
625
+ inputTag.enable()
626
+ }).to.not.throw()
627
+ })
628
+
629
+ it('should support addAt method for positional insertion', async () => {
630
+ const inputTag = await setupInputTag(`
631
+ <input-tag name="tags" multiple>
632
+ <tag-option value="first">First</tag-option>
633
+ <tag-option value="third">Third</tag-option>
634
+ </input-tag>
635
+ `)
636
+
637
+ expect(typeof inputTag.addAt).to.equal('function')
638
+
639
+ inputTag.addAt('second', 1)
640
+ await waitForUpdate()
641
+
642
+ expect(inputTag.tags).to.include.members(['first', 'third', 'second'])
643
+ })
644
+ })
645
+
646
+ describe('Error Handling in API Methods', () => {
647
+ it('should handle invalid parameters gracefully', async () => {
648
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
649
+
650
+ // These should not throw errors
651
+ expect(() => {
652
+ inputTag.focus(null)
653
+ inputTag.reset(undefined)
654
+ inputTag.checkValidity('invalid-param')
655
+ inputTag.reportValidity({})
656
+ }).to.not.throw()
657
+ })
658
+
659
+ it('should handle API calls before initialization', async () => {
660
+ document.body.innerHTML = '<input-tag name="tags" multiple></input-tag>'
661
+ const inputTag = document.querySelector('input-tag')
662
+
663
+ // These should not throw before internals are initialized
664
+ expect(() => {
665
+ inputTag.focus()
666
+ inputTag.checkValidity()
667
+ inputTag.reportValidity()
668
+ }).to.not.throw()
669
+ })
670
+
671
+ it('should handle API calls after disconnect', async () => {
672
+ const inputTag = await setupInputTag('<input-tag name="tags" multiple></input-tag>')
673
+
674
+ inputTag.disconnectedCallback()
675
+
676
+ // Basic API methods should still work or fail gracefully
677
+ expect(() => {
678
+ inputTag.focus()
679
+ inputTag.checkValidity()
680
+ inputTag.reportValidity()
681
+ }).to.not.throw()
682
+ })
683
+ })
684
+ })