Skip to content

Commit 2a1df39

Browse files
committed
fix: ♿ Ajoute des écouteurs d'événements claviers
1 parent abdb540 commit 2a1df39

File tree

3 files changed

+146
-1
lines changed

3 files changed

+146
-1
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { mount } from '@cypress/vue'
2+
import DsfrTabs from './DsfrTabs.vue'
3+
import VIcon from '../../icons.js'
4+
5+
import '../../main.css'
6+
7+
describe('DsfrTabs', () => {
8+
it('should mount Tabs', () => {
9+
mount(DsfrTabs, {
10+
global: {
11+
components: {
12+
VIcon,
13+
},
14+
},
15+
props: {
16+
tabListName: 'Liste d’onglets',
17+
tabTitles: [
18+
{ title: 'Titre 1', icon: 'ri-checkbox-circle-line' },
19+
{ title: 'Titre 2', icon: 'ri-checkbox-circle-line' },
20+
{ title: 'Titre 3', icon: 'ri-checkbox-circle-line' },
21+
{ title: 'Titre 4', icon: 'ri-checkbox-circle-line' },
22+
],
23+
tabContents: [
24+
'Contenu Tab1',
25+
'Contenu Tab2',
26+
'Contenu Tab3',
27+
'Contenu Tab4',
28+
],
29+
},
30+
})
31+
32+
cy.tab()
33+
34+
cy.get('li:first-child button')
35+
.should('have.focus')
36+
.type('{rightArrow}')
37+
.should('not.have.focus')
38+
39+
cy.get('li:nth-child(2) button')
40+
.should('have.focus')
41+
.type('{end}')
42+
.should('not.have.focus')
43+
44+
cy.get('li:last-child button')
45+
.should('have.focus')
46+
.type('{home}')
47+
.should('not.have.focus')
48+
49+
cy.get('li:first-child button')
50+
.should('have.focus')
51+
.type('{leftArrow}')
52+
.should('not.have.focus')
53+
54+
cy.get('li:last-child button')
55+
.should('have.focus')
56+
.type('{rightArrow}')
57+
.should('not.have.focus')
58+
59+
cy.get('li:first-child button')
60+
.should('have.focus')
61+
})
62+
})

src/components/DsfrTabs/DsfrTabs.spec.js

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('DsfrTabs', () => {
2323
const tabContents = ['Contenu1', 'Contenu2', 'Contenu3', 'Contenu4']
2424

2525
// When
26-
const { getByText, getByTestId, getAllByRole } = render(DsfrTabs, {
26+
const { getByText, getByTestId, getAllByRole, getByRole } = render(DsfrTabs, {
2727
global: {
2828
components: {
2929
VIcon,
@@ -36,17 +36,92 @@ describe('DsfrTabs', () => {
3636
},
3737
})
3838

39+
const tabListEl = getByRole('tablist')
40+
3941
const firstTabEl = getByTestId('test-tab1')
4042
const secondTabEl = getByText(title2)
4143
const thirdTabEl = getByText(title3)
4244
const tabTitleEls = getAllByRole('presentation')
45+
const tabItemEls = getAllByRole('tab')
46+
47+
let i = 0
48+
for (const tabItemEl of tabItemEls) {
49+
if (i === 0) {
50+
expect(tabItemEl).toHaveAttribute('aria-selected', 'true')
51+
} else {
52+
expect(tabItemEl).toHaveAttribute('aria-selected', 'false')
53+
}
54+
expect(tabItemEl).toHaveClass('fr-tabs__tab')
55+
i++
56+
}
57+
4358
await fireEvent.click(secondTabEl)
4459
await fireEvent.click(thirdTabEl)
4560
await fireEvent.click(secondTabEl)
4661

62+
i = 0
63+
for (const tabItemEl of tabItemEls) {
64+
if (i === 1) {
65+
expect(tabItemEl).toHaveAttribute('aria-selected', 'true')
66+
} else {
67+
expect(tabItemEl).toHaveAttribute('aria-selected', 'false')
68+
}
69+
i++
70+
}
71+
4772
// Then
4873
expect(tabTitleEls[0]).toContainElement(firstTabEl)
4974
expect(tabTitleEls[0].textContent).toContain(title1)
5075
expect(tabTitleEls[0].textContent).toContain(title1)
76+
expect(tabListEl).toHaveClass('fr-tabs__list')
77+
expect(tabItemEls).toHaveLength(4)
78+
})
79+
80+
it('should render tabs with proper aria-* attributes', async () => {
81+
// Given
82+
const tabListName = 'Liste d’onglet'
83+
const title1 = 'Titre 1'
84+
const title2 = 'Titre 2'
85+
const title3 = 'Titre 3'
86+
87+
const tabTitles = [
88+
{ title: title1 },
89+
{ title: title2 },
90+
{ title: title3 },
91+
{ title: 'Titre 4' },
92+
]
93+
94+
const tabContents = ['Contenu1', 'Contenu2', 'Contenu3', 'Contenu4']
95+
96+
// When
97+
const { container, getAllByRole, getByRole } = render(DsfrTabs, {
98+
global: {
99+
components: {
100+
VIcon,
101+
},
102+
},
103+
props: {
104+
tabListName,
105+
tabTitles,
106+
tabContents,
107+
},
108+
})
109+
110+
getByRole('tablist')
111+
112+
const tabItemEls = getAllByRole('tab')
113+
const panelEls = container.querySelectorAll('.fr-tabs__panel')
114+
115+
// Then
116+
expect(tabItemEls).toHaveLength(tabTitles.length)
117+
expect(panelEls).toHaveLength(tabTitles.length)
118+
let i = 0
119+
for (const tabPanelEl of panelEls) {
120+
expect(tabPanelEl).toHaveAttribute('role', 'tabpanel')
121+
expect(tabItemEls[i]).toHaveAttribute('role', 'tab')
122+
expect(tabPanelEl).toHaveAttribute('aria-labelledby', tabItemEls[i].id)
123+
expect(tabItemEls[i]).toHaveAttribute('aria-controls', tabPanelEl.id)
124+
i++
125+
}
51126
})
52127
})

src/components/DsfrTabs/DsfrTabs.vue

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
@click="selectIndex(index)"
1616
@next="selectNext()"
1717
@previous="selectPrevious()"
18+
@first="selectFirst()"
19+
@last="selectLast()"
1820
>
1921
{{ tabTitle.title }}
2022
</DsfrTabItem>
@@ -101,6 +103,12 @@ export default {
101103
const newIndex = this.selectedIndex === this.tabTitles.length - 1 ? 0 : this.selectedIndex + 1
102104
this.selectIndex(newIndex)
103105
},
106+
async selectFirst () {
107+
this.selectIndex(0)
108+
},
109+
async selectLast () {
110+
this.selectIndex(this.tabTitles.length - 1)
111+
},
104112
},
105113
}
106114
</script>

0 commit comments

Comments
 (0)