Skip to content

Commit def5802

Browse files
authored
Merge pull request #8324 from nextcloud-libraries/fix/8321/checkbox-keyboard-stale-value
2 parents 6eec54e + 513cd21 commit def5802

2 files changed

Lines changed: 66 additions & 17 deletions

File tree

src/components/NcCheckboxRadioSwitch/NcCheckboxRadioSwitch.vue

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -688,26 +688,13 @@ export default {
688688
return
689689
}
690690
691-
// Dispatch the checked values as an array if multiple, or single value otherwise
692-
const values = this.getInputsSet()
693-
.filter((input) => input.checked)
694-
.map((input) => input.value)
695-
696-
if (values.includes(this.value)) {
697-
this.internalModelValue = values.filter((v) => v !== this.value)
691+
// Toggle this value in/out of the array
692+
if (this.isChecked) {
693+
this.internalModelValue = this.internalModelValue.filter((v) => v !== this.value)
698694
} else {
699-
this.internalModelValue = [...values, this.value]
695+
this.internalModelValue = [...this.internalModelValue, this.value]
700696
}
701697
},
702-
703-
/**
704-
* Get the input set based on this name
705-
*
706-
* @return {Node[]}
707-
*/
708-
getInputsSet() {
709-
return [...document.getElementsByName(this.name)]
710-
},
711698
},
712699
}
713700
</script>

tests/unit/components/NcCheckboxRadioSwitch/checkbox.spec.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,66 @@ describe('NcCheckboxRadioSwitch', () => {
7878
expect(descriptionElement.exists()).toBe(true)
7979
expect(descriptionElement.text()).toContain('My description')
8080
})
81+
82+
it('emits correct value on keyboard toggle for boolean checkbox', async () => {
83+
const wrapper = mount(NcCheckboxRadioSwitch, {
84+
props: {
85+
modelValue: false,
86+
},
87+
slots: {
88+
default: 'Toggle me',
89+
},
90+
})
91+
92+
await wrapper.find('input').trigger('change')
93+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([true])
94+
})
95+
96+
it('emits correct value on keyboard toggle for checkbox group', async () => {
97+
const wrapper = mount(NcCheckboxRadioSwitch, {
98+
props: {
99+
modelValue: ['a'],
100+
value: 'b',
101+
name: 'test-group',
102+
},
103+
slots: {
104+
default: 'Option B',
105+
},
106+
attachTo: document.body,
107+
})
108+
109+
// Simulate keyboard spacebar: browser toggles input.checked BEFORE firing change
110+
const input = wrapper.find('input')
111+
const inputEl = input.element as HTMLInputElement
112+
inputEl.checked = true // Browser would do this before firing change
113+
await input.trigger('change')
114+
115+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['a', 'b']])
116+
117+
wrapper.unmount()
118+
})
119+
120+
it('emits correct value on keyboard un-toggle for checkbox group', async () => {
121+
const wrapper = mount(NcCheckboxRadioSwitch, {
122+
props: {
123+
modelValue: ['a', 'b'],
124+
value: 'b',
125+
name: 'test-group',
126+
},
127+
slots: {
128+
default: 'Option B',
129+
},
130+
attachTo: document.body,
131+
})
132+
133+
// Simulate keyboard spacebar unchecking: browser sets checked=false before change
134+
const input = wrapper.find('input')
135+
const inputEl = input.element as HTMLInputElement
136+
inputEl.checked = false
137+
await input.trigger('change')
138+
139+
expect(wrapper.emitted('update:modelValue')?.[0]).toEqual([['a']])
140+
141+
wrapper.unmount()
142+
})
81143
})

0 commit comments

Comments
 (0)