Skip to content

Commit 45308dd

Browse files
authored
🧪 TESTS: Add tests for JS tab functions (#109)
* Improve function and variable names * Add JS tests for basic tab usage * Fix relative JS imports in tests * Add test for changeTabs and selectNamedTabs * Update test Actions workflow to include JS tests * Fix JS tests Actions workflow * Update Actions publish to depend on JS tests
1 parent 9caafb2 commit 45308dd

File tree

9 files changed

+369
-28
lines changed

9 files changed

+369
-28
lines changed

‎.github/workflows/tests.yml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
python-version: 3.8
2525
- uses: pre-commit/[email protected]
2626

27-
tests:
27+
py-tests:
2828

2929
runs-on: ubuntu-latest
3030
strategy:
@@ -55,10 +55,24 @@ jobs:
5555
file: ./coverage.xml
5656
fail_ci_if_error: true
5757

58+
js-tests:
59+
60+
runs-on: ubuntu-latest
61+
steps:
62+
- uses: actions/checkout@v2
63+
- name: Use Node.js 15
64+
uses: actions/setup-node@v1
65+
with:
66+
node-version: '15'
67+
- name: Install jest
68+
run: npm install jest
69+
- name: Run JS tests
70+
run: npm test
71+
5872
publish:
5973

6074
name: Publish to PyPi
61-
needs: [pre-commit, tests]
75+
needs: [pre-commit, py-tests, js-tests]
6276
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
6377
runs-on: ubuntu-latest
6478
steps:

‎MANIFEST.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ include CHANGELOG.md
1717

1818
recursive-include sphinx_tabs *.css
1919
recursive-include sphinx_tabs *.js
20+
21+
include *.js
22+
include *.json
23+
recursive-include __tests__ *.js

‎__tests__/changeTabs.spec.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
const { changeTabs } = require("../sphinx_tabs/static/tabs");
2+
global.scrollTo = jest.fn();
3+
4+
describe("changeTabs", () => {
5+
it("changes tab when new tab is selected", () => {
6+
document.body.innerHTML =
7+
'<div>' +
8+
' <div>' +
9+
' <button id="tab-1" aria-controls="panel-1" aria-selected="true">Test tab 1</button>' +
10+
' <button id="tab-2" aria-controls="panel-2" aria-selected="false">Test tab 2</button>' +
11+
' </div>' +
12+
' <div id="panel-1">Test panel 1</div>' +
13+
' <div id="panel-2" hidden="true">Test panel 2</div>' +
14+
'</div>';
15+
16+
const allTabs = document.querySelectorAll('button');
17+
allTabs.forEach(tab => {
18+
tab.addEventListener("click", changeTabs);
19+
});
20+
21+
let tab1 = document.getElementById('tab-1');
22+
let tab2 = document.getElementById('tab-2');
23+
let panel1 = document.getElementById('panel-1');
24+
let panel2 = document.getElementById('panel-2');
25+
expect(tab1.getAttribute('aria-selected')).toEqual('true');
26+
expect(tab2.getAttribute('aria-selected')).toEqual('false');
27+
expect(panel1.getAttribute('hidden')).toEqual(null);
28+
expect(panel2.getAttribute('hidden')).toEqual('true');
29+
30+
tab2.click()
31+
32+
expect(tab1.getAttribute('aria-selected')).toEqual('false');
33+
expect(tab2.getAttribute('aria-selected')).toEqual('true');
34+
expect(panel1.getAttribute('hidden')).toEqual('true');
35+
expect(panel2.getAttribute('hidden')).toEqual(null);
36+
37+
tab1.click();
38+
39+
expect(tab1.getAttribute('aria-selected')).toEqual('true');
40+
expect(tab2.getAttribute('aria-selected')).toEqual('false');
41+
expect(panel1.getAttribute('hidden')).toEqual(null);
42+
expect(panel2.getAttribute('hidden')).toEqual('true');
43+
})
44+
it("closes tab in closeable tabList when selected", () => {
45+
document.body.innerHTML =
46+
'<div>' +
47+
' <div class="closeable">' +
48+
' <button id="tab-1" aria-controls="panel-1" aria-selected="true">Test tab 1</button>' +
49+
' </div>' +
50+
' <div id="panel-1">Test panel 1</div>' +
51+
'</div>';
52+
53+
let tab = document.getElementById('tab-1');
54+
let panel = document.getElementById('panel-1');
55+
tab.addEventListener("click", changeTabs);
56+
57+
expect(tab.getAttribute('aria-selected')).toEqual('true');
58+
expect(panel.getAttribute('hidden')).toEqual(null);
59+
60+
// Close
61+
tab.click();
62+
63+
expect(tab.getAttribute('aria-selected')).toEqual('false');
64+
expect(panel.getAttribute('hidden')).toEqual('true');
65+
66+
// Re-open
67+
tab.click();
68+
69+
expect(tab.getAttribute('aria-selected')).toEqual('true');
70+
expect(panel.getAttribute('hidden')).toEqual(null);
71+
})
72+
it("does not close tab in non-closeable tabList when selected", () => {
73+
document.body.innerHTML =
74+
'<div>' +
75+
' <div>' +
76+
' <button id="tab-1" aria-controls="panel-1" aria-selected="true">Test tab 1</button>' +
77+
' </div>' +
78+
' <div id="panel-1">Test panel 1</div>' +
79+
'</div>';
80+
81+
let tab = document.getElementById('tab-1');
82+
let panel = document.getElementById('panel-1');
83+
tab.addEventListener("click", changeTabs);
84+
85+
expect(tab.getAttribute('aria-selected')).toEqual('true');
86+
expect(panel.getAttribute('hidden')).toEqual(null);
87+
88+
tab.click();
89+
90+
expect(tab.getAttribute('aria-selected')).toEqual('true');
91+
expect(panel.getAttribute('hidden')).toEqual(null);
92+
})
93+
it("changes tab when content nested inside the tab is clicked", () => {
94+
document.body.innerHTML =
95+
'<div>' +
96+
' <div>' +
97+
' <button id="tab-1" aria-controls="panel-1" aria-selected="true">Test tab 1</button>' +
98+
' <button id="tab-2" aria-controls="panel-2" aria-selected="false"><strong id=bold>Test tab 2</strong></button>' +
99+
' </div>' +
100+
' <div id="panel-1">Test panel 1</div>' +
101+
' <div id="panel-2" hidden="true">Test panel 2</div>' +
102+
'</div>';
103+
104+
let tab1 = document.getElementById('tab-1');
105+
let tab2 = document.getElementById('tab-2');
106+
let panel1 = document.getElementById('panel-1');
107+
let panel2 = document.getElementById('panel-2');
108+
expect(tab1.getAttribute('aria-selected')).toEqual('true');
109+
expect(tab2.getAttribute('aria-selected')).toEqual('false');
110+
expect(panel1.getAttribute('hidden')).toEqual(null);
111+
expect(panel2.getAttribute('hidden')).toEqual('true');
112+
113+
let tab_2_text = document.getElementById('bold');
114+
expect(tab_2_text.getAttribute('hidden')).toEqual(null);
115+
116+
tab2.addEventListener("click", changeTabs);
117+
tab_2_text.click();
118+
119+
expect(tab1.getAttribute('aria-selected')).toEqual('false');
120+
expect(tab2.getAttribute('aria-selected')).toEqual('true');
121+
expect(panel1.getAttribute('hidden')).toEqual('true');
122+
expect(panel2.getAttribute('hidden')).toEqual(null);
123+
124+
expect(tab_2_text.getAttribute('hidden')).toEqual(null);
125+
})
126+
});

‎__tests__/deselectTabList.spec.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const { deselectTabList } = require("../sphinx_tabs/static/tabs");
2+
3+
describe("deselectTabList", () => {
4+
it("deselects all tabs in tablist when one tab is clicked", () => {
5+
document.body.innerHTML =
6+
'<div>' +
7+
' <div>' +
8+
' <button id="tab-1" aria-controls="panel-1" aria-selected="true">Test tab 1</button>' +
9+
' <button id="tab-2" aria-controls="panel-2" aria-selected="true">Test tab 2</button>' +
10+
' </div>' +
11+
' <div id="panel-1">Test panel 1</div>' +
12+
' <div id="panel-2">Test panel 2</div>' +
13+
'</div>';
14+
15+
let tab1 = document.getElementById('tab-1');
16+
let tab2 = document.getElementById('tab-2');
17+
let panel1 = document.getElementById('panel-1');
18+
let panel2 = document.getElementById('panel-2');
19+
expect(tab1.getAttribute('aria-selected')).toEqual('true');
20+
expect(tab2.getAttribute('aria-selected')).toEqual('true');
21+
expect(panel1.getAttribute('hidden')).toEqual(null);
22+
expect(panel2.getAttribute('hidden')).toEqual(null);
23+
24+
deselectTabList(tab1);
25+
26+
expect(tab1.getAttribute('aria-selected')).toEqual('false');
27+
expect(tab2.getAttribute('aria-selected')).toEqual('false');
28+
expect(panel1.getAttribute('hidden')).toEqual('true');
29+
expect(panel2.getAttribute('hidden')).toEqual('true');
30+
})
31+
})

‎__tests__/selectNamedTabs.spec.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
const { selectNamedTabs } = require("../sphinx_tabs/static/tabs");
2+
3+
describe("selectNamedTabs", () => {
4+
it("selects tabs with name, but not clickedId", () => {
5+
document.body.innerHTML =
6+
'<div>' +
7+
' <div>' +
8+
' <button class="sphinx-tabs-tab" aria-controls="panel-1-1" aria-selected="true">Test tab 1</button>' +
9+
' <button class="sphinx-tabs-tab" aria-controls="panel-1-2" aria-selected="false" name="sharedName" id="clicked">Test tab 2</button>' +
10+
' </div>' +
11+
' <div id="panel-1-1">Test panel 1</div>' +
12+
' <div id="panel-1-2" hidden="true"">Test panel 2</div>' +
13+
'</div>' +
14+
'<div>' +
15+
' <div>' +
16+
' <button class="sphinx-tabs-tab" aria-controls="panel-2-1" aria-selected="true">Test tab 1</button>' +
17+
' <button class="sphinx-tabs-tab" aria-controls="panel-2-2" aria-selected="false" name="sharedName" id="notClicked">Test tab 2</button>' +
18+
' </div>' +
19+
' <div id="panel-2-1">Test panel 1</div>' +
20+
' <div id="panel-2-2" hidden="true">Test panel 2</div>' +
21+
'</div>';
22+
23+
let clickedTab = document.getElementById('clicked');
24+
let namedTab = document.getElementById('notClicked');
25+
let clickedTabPanel = document.getElementById('panel-1-2');
26+
let namedTabPanel = document.getElementById('panel-2-2');
27+
expect(clickedTab.getAttribute('aria-selected')).toEqual('false');
28+
expect(namedTab.getAttribute('aria-selected')).toEqual('false');
29+
expect(clickedTabPanel.getAttribute('hidden')).toEqual('true');
30+
expect(namedTabPanel.getAttribute('hidden')).toEqual('true');
31+
32+
selectNamedTabs("sharedName", clickedId="clicked");
33+
34+
expect(clickedTab.getAttribute('aria-selected')).toEqual('false');
35+
expect(namedTab.getAttribute('aria-selected')).toEqual('true');
36+
expect(clickedTabPanel.getAttribute('hidden')).toEqual("true");
37+
expect(namedTabPanel.getAttribute('hidden')).toEqual(null);
38+
})
39+
it("selects first tab with same name in another tabList", () => {
40+
document.body.innerHTML =
41+
'<div>' +
42+
' <div>' +
43+
' <button class="sphinx-tabs-tab" aria-controls="panel-1-1" aria-selected="true">Test tab 1</button>' +
44+
' <button class="sphinx-tabs-tab" aria-controls="panel-1-2" aria-selected="false" name="sharedName" id="clicked">Test tab 2</button>' +
45+
' </div>' +
46+
' <div id="panel-1-1">Test panel 1</div>' +
47+
' <div id="panel-1-2" hidden="true"">Test panel 2</div>' +
48+
'</div>' +
49+
'<div>' +
50+
' <div>' +
51+
' <button class="sphinx-tabs-tab" aria-controls="panel-2-1" aria-selected="true">Test tab 1</button>' +
52+
' <button class="sphinx-tabs-tab" aria-controls="panel-2-2" aria-selected="false" name="sharedName" id="notClicked1">Test tab 2</button>' +
53+
' <button class="sphinx-tabs-tab" aria-controls="panel-2-3" aria-selected="false" name="sharedName" id="notClicked2">Test tab 3</button>' +
54+
' </div>' +
55+
' <div id="panel-2-1">Test panel 1</div>' +
56+
' <div id="panel-2-2" hidden="true">Test panel 2</div>' +
57+
' <div id="panel-2-3" hidden="true">Test panel 3</div>' +
58+
'</div>';
59+
60+
let clickedTab = document.getElementById('clicked');
61+
let firstNamedTab = document.getElementById('notClicked1');
62+
let secondNamedTab = document.getElementById('notClicked2');
63+
64+
expect(clickedTab.getAttribute('aria-selected')).toEqual('false');
65+
expect(firstNamedTab.getAttribute('aria-selected')).toEqual('false');
66+
expect(secondNamedTab.getAttribute('aria-selected')).toEqual('false');
67+
68+
selectNamedTabs("sharedName", clickedId="clicked");
69+
70+
expect(clickedTab.getAttribute('aria-selected')).toEqual('false');
71+
expect(firstNamedTab.getAttribute('aria-selected')).toEqual('true');
72+
expect(secondNamedTab.getAttribute('aria-selected')).toEqual('false');
73+
})
74+
it("doesn't change selected tab if tabList does not contain the name", () => {
75+
document.body.innerHTML =
76+
'<div>' +
77+
' <div>' +
78+
' <button class="sphinx-tabs-tab" aria-controls="panel-1-1" aria-selected="true">Test tab 1</button>' +
79+
' <button class="sphinx-tabs-tab" aria-controls="panel-1-2" aria-selected="false" name="sharedName" id="clicked">Test tab 2</button>' +
80+
' </div>' +
81+
' <div id="panel-1-1">Test panel 1</div>' +
82+
' <div id="panel-1-2" hidden="true"">Test panel 2</div>' +
83+
'</div>' +
84+
'<div>' +
85+
' <div>' +
86+
' <button class="sphinx-tabs-tab" aria-controls="panel-2-1" aria-selected="true" id="tab-2-1" >Test tab 1</button>' +
87+
' <button class="sphinx-tabs-tab" aria-controls="panel-2-2" aria-selected="false" name="aName" id="tab-2-2">Test tab 2</button>' +
88+
' </div>' +
89+
' <div id="panel-2-1">Test panel 1</div>' +
90+
' <div id="panel-2-2" hidden="true">Test panel 2</div>' +
91+
'</div>';
92+
93+
let clickedTab = document.getElementById('clicked');
94+
let tab1Tabset2 = document.getElementById('tab-2-1');
95+
let tab2Tabset2 = document.getElementById('tab-2-2');
96+
expect(clickedTab.getAttribute('aria-selected')).toEqual('false');
97+
expect(tab1Tabset2.getAttribute('aria-selected')).toEqual('true');
98+
expect(tab2Tabset2.getAttribute('aria-selected')).toEqual('false');
99+
100+
selectNamedTabs("sharedName", clickedId="clicked");
101+
102+
expect(clickedTab.getAttribute('aria-selected')).toEqual('false');
103+
expect(tab1Tabset2.getAttribute('aria-selected')).toEqual('true');
104+
expect(tab2Tabset2.getAttribute('aria-selected')).toEqual('false');
105+
})
106+
})

‎__tests__/selectTab.spec.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const { selectTab } = require("../sphinx_tabs/static/tabs");
2+
3+
describe("selectTab", () => {
4+
test("unselected tab become selected", () => {
5+
document.body.innerHTML =
6+
'<div>' +
7+
' <button id="tab" aria-controls="panel" aria-selected="false">Test</button>' +
8+
' <div id="panel" hidden="true">Test</div>' +
9+
'</div>';
10+
11+
let tab = document.getElementById('tab');
12+
let panel = document.getElementById('panel');
13+
expect(tab.getAttribute('aria-selected')).toEqual('false');
14+
expect(panel.getAttribute('hidden')).toEqual("true");
15+
16+
selectTab(tab);
17+
18+
expect(tab.getAttribute('aria-selected')).toEqual('true');
19+
expect(panel.getAttribute('hidden')).toEqual(null);
20+
})
21+
test("selected tab stays selected", () => {
22+
document.body.innerHTML =
23+
'<div>' +
24+
' <button id="test-button" aria-controls="panel" aria-selected="true">Test</button>' +
25+
' <div id="panel">Test</div>' +
26+
'</div>';
27+
28+
let tab = document.getElementById('test-button');
29+
let panel = document.getElementById('panel');
30+
expect(tab.getAttribute('aria-selected')).toEqual('true');
31+
expect(panel.getAttribute('hidden')).toEqual(null);
32+
33+
selectTab(tab);
34+
35+
expect(tab.getAttribute('aria-selected')).toEqual('true');
36+
expect(panel.getAttribute('hidden')).toEqual(null);
37+
})
38+
})

‎jest.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/*
2+
* For a detailed explanation regarding each configuration property, visit:
3+
* https://jestjs.io/docs/en/configuration.html
4+
*/
5+
6+
module.exports = {};

‎package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"scripts": {
3+
"test": "jest"
4+
}
5+
}

0 commit comments

Comments
 (0)