Skip to content

Commit 067b09f

Browse files
committed
tests: and tests for navigations.js and sidebar.js
1 parent bf17686 commit 067b09f

File tree

2 files changed

+966
-0
lines changed

2 files changed

+966
-0
lines changed

js/tests/unit/navigation.spec.js

Lines changed: 249 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
import Navigation from '../../src/navigation.js'
2+
import { clearFixture, getFixture, jQueryMock } from '../helpers/fixture.js'
3+
4+
describe('Navigation', () => {
5+
let fixtureEl
6+
7+
beforeAll(() => {
8+
fixtureEl = getFixture()
9+
})
10+
11+
afterEach(() => {
12+
clearFixture()
13+
})
14+
15+
it('should take care of element either passed as a CSS selector or DOM element', () => {
16+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
17+
18+
const navEl = fixtureEl.querySelector('nav')
19+
const navigationBySelector = new Navigation('nav')
20+
const navigationByElement = new Navigation(navEl)
21+
22+
expect(navigationBySelector._element).toEqual(navEl)
23+
expect(navigationByElement._element).toEqual(navEl)
24+
})
25+
26+
it('should return version', () => {
27+
expect(Navigation.VERSION).toEqual(jasmine.any(String))
28+
})
29+
30+
describe('Constructor', () => {
31+
it('should set default config', () => {
32+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
33+
const navEl = fixtureEl.querySelector('nav')
34+
const navigation = new Navigation(navEl) // eslint-disable-line no-unused-vars
35+
36+
expect(Navigation.Default.activeLinksExact).toBe(true)
37+
expect(Navigation.Default.groupsAutoCollapse).toBe(true)
38+
})
39+
40+
it('should merge custom config with default', () => {
41+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
42+
const navEl = fixtureEl.querySelector('nav')
43+
const customConfig = {
44+
activeLinksExact: false,
45+
groupsAutoCollapse: false
46+
}
47+
const navigation = new Navigation(navEl, customConfig)
48+
49+
expect(navigation._config.activeLinksExact).toBe(false)
50+
expect(navigation._config.groupsAutoCollapse).toBe(false)
51+
})
52+
53+
it('should call _setActiveLink on initialization', () => {
54+
fixtureEl.innerHTML = `
55+
<nav data-coreui="navigation">
56+
<a class="nav-link" href="${window.location.href}">Active Link</a>
57+
</nav>
58+
`
59+
const navEl = fixtureEl.querySelector('nav')
60+
spyOn(Navigation.prototype, '_setActiveLink')
61+
62+
const navigation = new Navigation(navEl) // eslint-disable-line no-unused-vars
63+
64+
expect(Navigation.prototype._setActiveLink).toHaveBeenCalled()
65+
})
66+
67+
it('should add event listeners on initialization', () => {
68+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
69+
const navEl = fixtureEl.querySelector('nav')
70+
spyOn(Navigation.prototype, '_addEventListeners')
71+
72+
const navigation = new Navigation(navEl) // eslint-disable-line no-unused-vars
73+
74+
expect(Navigation.prototype._addEventListeners).toHaveBeenCalled()
75+
})
76+
})
77+
78+
describe('Data API', () => {
79+
it('should initialize navigation on elements with data-coreui="navigation"', () => {
80+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
81+
const navEl = fixtureEl.querySelector('nav')
82+
spyOn(Navigation, 'navigationInterface')
83+
84+
const loadEvent = new Event('load')
85+
window.dispatchEvent(loadEvent)
86+
87+
expect(Navigation.navigationInterface).toHaveBeenCalledWith(navEl)
88+
})
89+
})
90+
91+
describe('Static methods', () => {
92+
describe('navigationInterface', () => {
93+
it('should create instance if config is object', () => {
94+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
95+
const navEl = fixtureEl.querySelector('nav')
96+
97+
Navigation.navigationInterface(navEl, {})
98+
99+
expect(Navigation.getInstance(navEl)).toBeInstanceOf(Navigation)
100+
})
101+
102+
it('should handle method calling via string config', () => {
103+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
104+
const navEl = fixtureEl.querySelector('nav')
105+
const navigation = new Navigation(navEl) // eslint-disable-line no-unused-vars
106+
107+
// Since Navigation has no public methods, we just test that the interface works
108+
// without throwing errors for valid configurations
109+
expect(() => {
110+
Navigation.navigationInterface(navEl, {})
111+
}).not.toThrow()
112+
})
113+
114+
it('should throw error for non-existent method', () => {
115+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
116+
const navEl = fixtureEl.querySelector('nav')
117+
const navigation = new Navigation(navEl) // eslint-disable-line no-unused-vars
118+
119+
const throwError = () => Navigation.navigationInterface(navEl, 'nonExistentMethod')
120+
121+
expect(throwError).toThrowError(TypeError, 'No method named "nonExistentMethod"')
122+
})
123+
})
124+
125+
describe('jQueryInterface', () => {
126+
it('should create instance when jQuery is present', () => {
127+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
128+
const navEl = fixtureEl.querySelector('nav')
129+
jQueryMock.fn.navigation = Navigation.jQueryInterface
130+
jQueryMock.elements = [navEl]
131+
132+
jQueryMock.fn.navigation.call(jQueryMock)
133+
134+
expect(Navigation.getInstance(navEl)).toBeInstanceOf(Navigation)
135+
})
136+
})
137+
})
138+
139+
describe('_setActiveLink', () => {
140+
it('should call _setActiveLink during initialization', () => {
141+
fixtureEl.innerHTML = '<nav data-coreui="navigation"></nav>'
142+
const navEl = fixtureEl.querySelector('nav')
143+
spyOn(Navigation.prototype, '_setActiveLink')
144+
145+
const navigation = new Navigation(navEl) // eslint-disable-line no-unused-vars
146+
147+
expect(Navigation.prototype._setActiveLink).toHaveBeenCalled()
148+
})
149+
150+
it('should add active class to partial matching links when activeLinksExact is false', () => {
151+
const currentUrlBase = `${window.location.origin}/context`
152+
fixtureEl.innerHTML = `
153+
<nav data-coreui="navigation">
154+
<a class="nav-link" href="${currentUrlBase}">Partial Match</a>
155+
<a class="nav-link" href="http://localhost:9876/other">No Match</a>
156+
</nav>
157+
`
158+
const navEl = fixtureEl.querySelector('nav')
159+
const partialLink = navEl.querySelector(`a[href="${currentUrlBase}"]`)
160+
const noMatchLink = navEl.querySelector('a[href="http://localhost:9876/other"]')
161+
162+
const navigation = new Navigation(navEl, { activeLinksExact: false }) // eslint-disable-line no-unused-vars
163+
164+
expect(partialLink.classList.contains('active')).toBe(true)
165+
expect(noMatchLink.classList.contains('active')).toBe(false)
166+
})
167+
168+
it('should skip nav-group-toggle elements', () => {
169+
const currentUrl = window.location.href
170+
fixtureEl.innerHTML = `
171+
<nav data-coreui="navigation">
172+
<a class="nav-link nav-group-toggle" href="${currentUrl}">Toggle</a>
173+
</nav>
174+
`
175+
const navEl = fixtureEl.querySelector('nav')
176+
const toggleLink = navEl.querySelector('a')
177+
178+
const navigation = new Navigation(navEl, { activeLinksExact: true }) // eslint-disable-line no-unused-vars
179+
180+
expect(toggleLink.classList.contains('active')).toBe(false)
181+
})
182+
})
183+
184+
describe('Parent group handling', () => {
185+
it('should process parent groups during initialization', () => {
186+
fixtureEl.innerHTML = `
187+
<nav data-coreui="navigation">
188+
<div class="nav-group">
189+
<div class="nav-group">
190+
<a class="nav-link" href="/some/path">Link</a>
191+
</div>
192+
</div>
193+
</nav>
194+
`
195+
const navEl = fixtureEl.querySelector('nav')
196+
197+
// Just test that navigation initializes without errors with nested groups
198+
expect(() => {
199+
const navigation = new Navigation(navEl) // eslint-disable-line no-unused-vars
200+
}).not.toThrow()
201+
})
202+
})
203+
204+
describe('Event handling', () => {
205+
it('should handle nav-group-toggle clicks', () => {
206+
fixtureEl.innerHTML = `
207+
<nav data-coreui="navigation">
208+
<div class="nav-group">
209+
<a class="nav-group-toggle">Toggle</a>
210+
<div class="nav-group-items">Items</div>
211+
</div>
212+
</nav>
213+
`
214+
const navEl = fixtureEl.querySelector('nav')
215+
const navigation = new Navigation(navEl) // eslint-disable-line no-unused-vars
216+
const group = navEl.querySelector('.nav-group')
217+
const toggle = navEl.querySelector('.nav-group-toggle')
218+
219+
toggle.click()
220+
221+
expect(group.classList.contains('show')).toBe(true)
222+
expect(group.getAttribute('aria-expanded')).toBe('true')
223+
})
224+
})
225+
226+
describe('Constants and getters', () => {
227+
it('should have correct NAME', () => {
228+
expect(Navigation.NAME).toBe('navigation')
229+
})
230+
231+
it('should have correct DATA_KEY', () => {
232+
expect(Navigation.DATA_KEY).toBe('coreui.navigation')
233+
})
234+
235+
it('should have correct Default config', () => {
236+
expect(Navigation.Default).toEqual({
237+
activeLinksExact: true,
238+
groupsAutoCollapse: true
239+
})
240+
})
241+
242+
it('should have correct DefaultType', () => {
243+
expect(Navigation.DefaultType).toEqual({
244+
activeLinksExact: 'boolean',
245+
groupsAutoCollapse: '(string|boolean)'
246+
})
247+
})
248+
})
249+
})

0 commit comments

Comments
 (0)