@api-client/ui 0.5.29 → 0.5.30
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.
- package/build/src/elements/currency/internals/Picker.d.ts.map +1 -1
- package/build/src/elements/currency/internals/Picker.js +0 -1
- package/build/src/elements/currency/internals/Picker.js.map +1 -1
- package/build/src/md/menu/internal/Menu.d.ts.map +1 -1
- package/build/src/md/menu/internal/Menu.js +20 -8
- package/build/src/md/menu/internal/Menu.js.map +1 -1
- package/build/src/md/select/internals/Select.d.ts +2 -1
- package/build/src/md/select/internals/Select.d.ts.map +1 -1
- package/build/src/md/select/internals/Select.js +46 -16
- package/build/src/md/select/internals/Select.js.map +1 -1
- package/build/src/md/select/internals/Select.styles.d.ts.map +1 -1
- package/build/src/md/select/internals/Select.styles.js +0 -5
- package/build/src/md/select/internals/Select.styles.js.map +1 -1
- package/demo/elements/currency/index.ts +80 -0
- package/demo/md/select/index.ts +1 -1
- package/package.json +1 -1
- package/src/elements/currency/internals/Picker.ts +0 -1
- package/src/md/menu/internal/Menu.ts +23 -8
- package/src/md/select/internals/Select.styles.ts +0 -5
- package/src/md/select/internals/Select.ts +47 -17
- package/test/md/select/Select.test.ts +229 -0
|
@@ -73,6 +73,40 @@ describe('md', () => {
|
|
|
73
73
|
return fixture(html`<ui-select label="Empty select"></ui-select>`)
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
async function selectedAttributeFixture(): Promise<UiSelect> {
|
|
77
|
+
return fixture(html`
|
|
78
|
+
<ui-select label="Select with pre-selected option">
|
|
79
|
+
<ui-option value="apple">Apple</ui-option>
|
|
80
|
+
<ui-option value="banana" selected>Banana</ui-option>
|
|
81
|
+
<ui-option value="cherry">Cherry</ui-option>
|
|
82
|
+
</ui-select>
|
|
83
|
+
`)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function multipleSelectedFixture(): Promise<UiSelect> {
|
|
87
|
+
return fixture(html`
|
|
88
|
+
<ui-select label="Select with multiple selected">
|
|
89
|
+
<ui-option value="apple" selected>Apple</ui-option>
|
|
90
|
+
<ui-option value="banana" selected>Banana</ui-option>
|
|
91
|
+
<ui-option value="cherry">Cherry</ui-option>
|
|
92
|
+
</ui-select>
|
|
93
|
+
`)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function selectedWithValueFixture(): Promise<UiSelect> {
|
|
97
|
+
return fixture(html`
|
|
98
|
+
<ui-select label="Select with both value and selected" value="cherry">
|
|
99
|
+
<ui-option value="apple">Apple</ui-option>
|
|
100
|
+
<ui-option value="banana" selected>Banana</ui-option>
|
|
101
|
+
<ui-option value="cherry">Cherry</ui-option>
|
|
102
|
+
</ui-select>
|
|
103
|
+
`)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function dynamicOptionsFixture(): Promise<UiSelect> {
|
|
107
|
+
return fixture(html` <ui-select label="Dynamic options"> </ui-select> `)
|
|
108
|
+
}
|
|
109
|
+
|
|
76
110
|
describe('Basic functionality', () => {
|
|
77
111
|
it('should create select element', async () => {
|
|
78
112
|
const element = await basicFixture()
|
|
@@ -160,6 +194,61 @@ describe('md', () => {
|
|
|
160
194
|
assert.isNull(element.selectedItem, 'selected item should be null')
|
|
161
195
|
assert.equal(element.renderValue, '')
|
|
162
196
|
})
|
|
197
|
+
|
|
198
|
+
it('should discover selected attribute on options', async () => {
|
|
199
|
+
const element = await selectedAttributeFixture()
|
|
200
|
+
await element.updateComplete
|
|
201
|
+
|
|
202
|
+
assert.equal(element.value, 'banana')
|
|
203
|
+
assert.isNotNull(element.selectedItem)
|
|
204
|
+
assert.equal(element.selectedItem!.value, 'banana')
|
|
205
|
+
assert.equal(element.renderValue, 'Banana')
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
it('should handle multiple selected options by selecting the first one', async () => {
|
|
209
|
+
const element = await multipleSelectedFixture()
|
|
210
|
+
await element.updateComplete
|
|
211
|
+
await nextFrame()
|
|
212
|
+
|
|
213
|
+
// When multiple options have selected attribute, only the first one should be selected
|
|
214
|
+
assert.equal(element.value, 'apple')
|
|
215
|
+
assert.isNotNull(element.selectedItem)
|
|
216
|
+
assert.equal(element.selectedItem!.value, 'apple') // First selected item
|
|
217
|
+
assert.equal(element.renderValue, 'Apple') // Display value should match the first selected item
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
it('should prioritize value over selected attribute', async () => {
|
|
221
|
+
const element = await selectedWithValueFixture()
|
|
222
|
+
await element.updateComplete
|
|
223
|
+
|
|
224
|
+
assert.equal(element.value, 'cherry')
|
|
225
|
+
assert.isNotNull(element.selectedItem)
|
|
226
|
+
assert.equal(element.selectedItem!.value, 'cherry')
|
|
227
|
+
assert.equal(element.renderValue, 'Cherry')
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
it('should update value when options change dynamically', async () => {
|
|
231
|
+
const element = await dynamicOptionsFixture()
|
|
232
|
+
await element.updateComplete
|
|
233
|
+
|
|
234
|
+
// Initially, there are no options, so value should be undefined
|
|
235
|
+
assert.isUndefined(element.value)
|
|
236
|
+
|
|
237
|
+
// Add options dynamically
|
|
238
|
+
element.innerHTML = `
|
|
239
|
+
<ui-option value="apple">Apple</ui-option>
|
|
240
|
+
<ui-option value="banana" selected>Banana</ui-option>
|
|
241
|
+
<ui-option value="cherry">Cherry</ui-option>
|
|
242
|
+
`
|
|
243
|
+
await element.updateComplete
|
|
244
|
+
await nextFrame()
|
|
245
|
+
|
|
246
|
+
// The value should now reflect the selected option
|
|
247
|
+
assert.equal(element.value, 'banana')
|
|
248
|
+
assert.isNotNull(element.selectedItem)
|
|
249
|
+
assert.equal(element.selectedItem!.value, 'banana')
|
|
250
|
+
assert.equal(element.renderValue, 'Banana')
|
|
251
|
+
})
|
|
163
252
|
})
|
|
164
253
|
|
|
165
254
|
describe('Form integration', () => {
|
|
@@ -663,5 +752,145 @@ describe('md', () => {
|
|
|
663
752
|
assert.equal(options[2].value, 'cherry')
|
|
664
753
|
})
|
|
665
754
|
})
|
|
755
|
+
|
|
756
|
+
describe('Selected attribute discovery', () => {
|
|
757
|
+
it('should discover and set value from selected attribute on initialization', async () => {
|
|
758
|
+
const element = await selectedAttributeFixture()
|
|
759
|
+
await element.updateComplete
|
|
760
|
+
await nextFrame()
|
|
761
|
+
|
|
762
|
+
assert.equal(element.value, 'banana', 'value should be set from selected option')
|
|
763
|
+
assert.isNotNull(element.selectedItem, 'selected item should not be null')
|
|
764
|
+
assert.equal(element.selectedItem!.value, 'banana', 'selected item should be the banana option')
|
|
765
|
+
assert.equal(element.renderValue, 'Banana', 'render value should match selected option')
|
|
766
|
+
})
|
|
767
|
+
|
|
768
|
+
it('should handle case with no selected options', async () => {
|
|
769
|
+
const element = await basicFixture()
|
|
770
|
+
await element.updateComplete
|
|
771
|
+
await nextFrame()
|
|
772
|
+
|
|
773
|
+
assert.isUndefined(element.value, 'value should be undefined when no options are selected')
|
|
774
|
+
assert.isNull(element.selectedItem, 'selected item should be null when no options are selected')
|
|
775
|
+
assert.equal(element.renderValue, '', 'render value should be empty when no options are selected')
|
|
776
|
+
})
|
|
777
|
+
|
|
778
|
+
it('should select the first option when multiple options have selected attribute', async () => {
|
|
779
|
+
const element = await multipleSelectedFixture()
|
|
780
|
+
await element.updateComplete
|
|
781
|
+
await nextFrame()
|
|
782
|
+
|
|
783
|
+
assert.equal(element.value, 'apple', 'should select the first option with selected attribute')
|
|
784
|
+
assert.isNotNull(element.selectedItem, 'selected item should not be null')
|
|
785
|
+
assert.equal(element.selectedItem!.value, 'apple', 'selected item should be the first selected option')
|
|
786
|
+
assert.equal(element.renderValue, 'Apple', 'render value should match first selected option')
|
|
787
|
+
})
|
|
788
|
+
|
|
789
|
+
it('should prioritize explicit value property over selected attribute', async () => {
|
|
790
|
+
const element = await selectedWithValueFixture()
|
|
791
|
+
await element.updateComplete
|
|
792
|
+
await nextFrame()
|
|
793
|
+
|
|
794
|
+
assert.equal(element.value, 'cherry', 'value property should take precedence')
|
|
795
|
+
assert.isNotNull(element.selectedItem, 'selected item should not be null')
|
|
796
|
+
assert.equal(element.selectedItem!.value, 'cherry', 'selected item should match value property')
|
|
797
|
+
assert.equal(element.renderValue, 'Cherry', 'render value should match value property')
|
|
798
|
+
})
|
|
799
|
+
|
|
800
|
+
it('should rediscover selected options when value is cleared', async () => {
|
|
801
|
+
const element = await selectedAttributeFixture()
|
|
802
|
+
await element.updateComplete
|
|
803
|
+
await nextFrame()
|
|
804
|
+
|
|
805
|
+
// First, verify it's initialized correctly
|
|
806
|
+
assert.equal(element.value, 'banana')
|
|
807
|
+
|
|
808
|
+
// Now clear the value and it should fall back to selected attribute
|
|
809
|
+
element.value = undefined
|
|
810
|
+
await element.updateComplete
|
|
811
|
+
await nextFrame()
|
|
812
|
+
|
|
813
|
+
assert.equal(element.value, 'banana', 'should rediscover selected option when value is cleared')
|
|
814
|
+
assert.isNotNull(element.selectedItem, 'selected item should not be null')
|
|
815
|
+
assert.equal(element.selectedItem!.value, 'banana', 'selected item should be rediscovered')
|
|
816
|
+
})
|
|
817
|
+
|
|
818
|
+
it('should handle dynamically added options with selected attribute', async () => {
|
|
819
|
+
const element = await dynamicOptionsFixture()
|
|
820
|
+
await element.updateComplete
|
|
821
|
+
await nextFrame()
|
|
822
|
+
|
|
823
|
+
// Initially no options
|
|
824
|
+
assert.isUndefined(element.value)
|
|
825
|
+
assert.isNull(element.selectedItem)
|
|
826
|
+
|
|
827
|
+
// Add options dynamically
|
|
828
|
+
element.innerHTML = `
|
|
829
|
+
<ui-option value="apple">Apple</ui-option>
|
|
830
|
+
<ui-option value="banana" selected>Banana</ui-option>
|
|
831
|
+
<ui-option value="cherry">Cherry</ui-option>
|
|
832
|
+
`
|
|
833
|
+
|
|
834
|
+
await element.updateComplete
|
|
835
|
+
await nextFrame()
|
|
836
|
+
|
|
837
|
+
assert.equal(element.value, 'banana', 'should discover selected option from dynamically added content')
|
|
838
|
+
assert.isNotNull(element.selectedItem, 'selected item should not be null')
|
|
839
|
+
assert.equal(
|
|
840
|
+
(element.selectedItem as UiOption)!.value,
|
|
841
|
+
'banana',
|
|
842
|
+
'selected item should be the dynamically added selected option'
|
|
843
|
+
)
|
|
844
|
+
})
|
|
845
|
+
|
|
846
|
+
it('should update when selected attribute is added to existing option', async () => {
|
|
847
|
+
const element = await basicFixture()
|
|
848
|
+
await element.updateComplete
|
|
849
|
+
await nextFrame()
|
|
850
|
+
|
|
851
|
+
// Initially no selection
|
|
852
|
+
assert.isUndefined(element.value)
|
|
853
|
+
assert.isNull(element.selectedItem)
|
|
854
|
+
|
|
855
|
+
// Add selected attribute to an option
|
|
856
|
+
const bananaOption = element.querySelector('ui-option[value="banana"]') as UiOption
|
|
857
|
+
bananaOption.selected = true
|
|
858
|
+
|
|
859
|
+
// Trigger setCurrentOption manually since we changed the DOM
|
|
860
|
+
await (element as UiSelect & { setCurrentOption(): Promise<void> }).setCurrentOption()
|
|
861
|
+
await element.updateComplete
|
|
862
|
+
await nextFrame()
|
|
863
|
+
|
|
864
|
+
assert.equal(element.value, 'banana', 'should discover newly selected option')
|
|
865
|
+
assert.isNotNull(element.selectedItem, 'selected item should not be null')
|
|
866
|
+
assert.equal(
|
|
867
|
+
(element.selectedItem as UiOption)!.value,
|
|
868
|
+
'banana',
|
|
869
|
+
'selected item should be the newly selected option'
|
|
870
|
+
)
|
|
871
|
+
})
|
|
872
|
+
|
|
873
|
+
it('should clear selection when selected attribute is removed from all options', async () => {
|
|
874
|
+
const element = await selectedAttributeFixture()
|
|
875
|
+
await element.updateComplete
|
|
876
|
+
await nextFrame()
|
|
877
|
+
|
|
878
|
+
// Initially has selection
|
|
879
|
+
assert.equal(element.value, 'banana')
|
|
880
|
+
|
|
881
|
+
// Remove selected attribute
|
|
882
|
+
const bananaOption = element.querySelector('ui-option[value="banana"]') as UiOption
|
|
883
|
+
bananaOption.selected = false
|
|
884
|
+
|
|
885
|
+
// Clear the value to trigger rediscovery
|
|
886
|
+
element.value = undefined
|
|
887
|
+
await element.updateComplete
|
|
888
|
+
await nextFrame()
|
|
889
|
+
|
|
890
|
+
assert.isUndefined(element.value, 'value should be undefined when no options are selected')
|
|
891
|
+
assert.isNull(element.selectedItem, 'selected item should be null when no options are selected')
|
|
892
|
+
assert.equal(element.renderValue, '', 'render value should be empty when no options are selected')
|
|
893
|
+
})
|
|
894
|
+
})
|
|
666
895
|
})
|
|
667
896
|
})
|