Skip to content

Commit e448011

Browse files
authored
Merge pull request #5777 from nextcloud-libraries/fix/checkbox-attrs-aria
2 parents 6252057 + 083cd8f commit e448011

File tree

7 files changed

+78
-23
lines changed

7 files changed

+78
-23
lines changed

.reuse/dep5

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Files: package.json package-lock.json .github/pull_request_template.md
77
Copyright: Nextcloud GmbH and Nextcloud contributors
88
License: AGPL-3.0-or-later
99

10-
Files: styleguide/assets/icons.css styleguide/assets/server.css cypress/snapshots/* tests/unit/functions/usernameToColor/__snapshots__/usernameToColor.spec.js.snap
10+
Files: styleguide/assets/icons.css cypress/snapshots/* tests/unit/functions/usernameToColor/__snapshots__/usernameToColor.spec.js.snap
1111
Copyright: Nextcloud GmbH and Nextcloud contributors
1212
License: AGPL-3.0-or-later
1313

cypress/commands.d.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import type { mount } from '@cypress/vue2'
7+
8+
// Augment the Cypress namespace to include type definitions for
9+
// your custom commands
10+
declare global {
11+
// eslint-disable-next-line @typescript-eslint/no-namespace
12+
namespace Cypress {
13+
interface Chainable {
14+
mount: typeof mount
15+
}
16+
}
17+
}
18+
19+
export {}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import NcCheckboxRadioSwitch from '../../src/components/NcCheckboxRadioSwitch/NcCheckboxRadioSwitch.vue'
7+
8+
describe('NcCheckboxRadioSwitch', () => {
9+
it('Sets attributes correctly', () => {
10+
cy.mount({
11+
render: (h) => h(NcCheckboxRadioSwitch, {
12+
// TODO: With Vue3 move class and style to attrs
13+
class: 'my-class',
14+
style: 'background: red;',
15+
attrs: {
16+
'aria-describedby': 'unique-id',
17+
'data-my-attribute': 'yes',
18+
},
19+
}, ['My checkbox']),
20+
}).then(({ wrapper }) => {
21+
// Class and style belong the wrapper
22+
expect(wrapper.classes('my-class')).to.be.true
23+
// expect(wrapper.attributes('style')).to.equal('background: red;')
24+
// Custom data attributes too
25+
expect(wrapper.attributes('data-my-attribute')).to.equal('yes')
26+
// real HTML attributes are passed to the real checkbox
27+
expect(wrapper.attributes('aria-describedby')).to.be.undefined
28+
})
29+
30+
cy.findByRole('checkbox').should('have.attr', 'aria-describedby', 'unique-id')
31+
})
32+
})

cypress/support/commands.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
55

6+
import { mount } from '@cypress/vue2'
67
import { addCompareSnapshotCommand } from 'cypress-visual-regression/dist/command'
78

89
import '@testing-library/cypress/add-commands'
910

1011
addCompareSnapshotCommand()
12+
13+
// Example use:
14+
// cy.mount(MyComponent)
15+
Cypress.Commands.add('mount', mount)

cypress/support/component.ts

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,3 @@ import '../../styleguide/assets/icons.css'
1010

1111
// cypress commands
1212
import './commands'
13-
import { mount } from '@cypress/vue2'
14-
15-
// Augment the Cypress namespace to include type definitions for
16-
// your custom command.
17-
// Alternatively, can be defined in cypress/support/component.d.ts
18-
// with a <reference path="./component" /> at the top of your spec.
19-
20-
declare global {
21-
// eslint-disable-next-line @typescript-eslint/no-namespace
22-
namespace Cypress {
23-
interface Chainable {
24-
mount: typeof mount
25-
}
26-
}
27-
}
28-
29-
// Example use:
30-
// cy.mount(MyComponent)
31-
Cypress.Commands.add('mount', mount)

src/components/NcCheckboxRadioSwitch/NcCheckboxRadioSwitch.vue

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ export default {
258258
class="checkbox-radio-switch"
259259
:style="cssVars"
260260
:type="isButtonType ? 'button' : null"
261-
v-bind="isButtonType ? $attrs : {}"
261+
v-bind="isButtonType ? $attrs : dataAttrs"
262262
v-on="isButtonType ? listeners : null">
263263
<input v-if="!isButtonType"
264264
:id="id"
@@ -272,7 +272,7 @@ export default {
272272
:indeterminate.prop="hasIndeterminate ? indeterminate : null"
273273
:required="required"
274274
:name="name"
275-
v-bind="$attrs"
275+
v-bind="nonDataAttrs"
276276
v-on="listeners">
277277
<NcCheckboxContent :id="id"
278278
class="checkbox-radio-switch__content"
@@ -450,6 +450,18 @@ export default {
450450
emits: ['update:checked'],
451451

452452
computed: {
453+
dataAttrs() {
454+
// filter all data attributes
455+
return Object.fromEntries(Object.entries(this.$attrs)
456+
.filter(([key]) => key.startsWith('data-')))
457+
},
458+
459+
nonDataAttrs() {
460+
// filter all non-data attributes
461+
return Object.fromEntries(Object.entries(this.$attrs)
462+
.filter(([key]) => !key.startsWith('data-')))
463+
},
464+
453465
isButtonType() {
454466
return this.type === TYPE_BUTTON
455467
},

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,25 @@ describe('NcCheckboxRadioSwitch', () => {
1717
expect(wrapper.text()).toContain('Test')
1818
})
1919

20-
it('forwards aria-invalid and aria-errormessage to input', () => {
20+
it('forwards all but data- attributes to the input', () => {
2121
const wrapper = shallowMount(NcCheckboxRadioSwitch, {
2222
slots: {
2323
default: 'Test',
2424
},
2525
attrs: {
2626
'aria-invalid': 'true',
2727
'aria-errormessage': 'id-test',
28+
'data-test': 'checkbox-test-data-attr',
29+
title: 'Test title',
2830
},
2931
})
3032

3133
const input = wrapper.find('input')
3234
expect(input.attributes('aria-invalid')).toBe('true')
3335
expect(input.attributes('aria-errormessage')).toBe('id-test')
36+
expect(input.attributes('title')).toBe('Test title')
37+
expect(input.attributes('data-test')).not.toBe('checkbox-test-data-attr')
38+
expect(wrapper.attributes('data-test')).toBe('checkbox-test-data-attr')
39+
expect(wrapper.attributes('title')).not.toBe('Test title')
3440
})
3541
})

0 commit comments

Comments
 (0)