Skip to content

Commit 591b6ce

Browse files
authored
Merge pull request #62 from SolidOS/newFace-1
New face 1
2 parents 65715c9 + 8d82265 commit 591b6ce

File tree

6 files changed

+5776
-2151
lines changed

6 files changed

+5776
-2151
lines changed

TESTING.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Testing Guide
2+
3+
## Running Tests
4+
5+
```bash
6+
# Run all tests
7+
npm test
8+
9+
# Run tests in watch mode
10+
npm run test:watch
11+
12+
# Run linting only
13+
npm run test:lint
14+
15+
# Auto-fix linting issues
16+
npm run lint-fix
17+
```
18+
19+
## Test Coverage
20+
21+
The tests provide 100% code coverage for all functionality:
22+
23+
- **Initial State Tests**: Verify registry starts empty
24+
- **Registration Tests**: Test pane registration with various scenarios
25+
- **Lookup Tests**: Test finding panes by name
26+
- **Integration Tests**: Complex workflows and edge cases
27+
28+
## Test Structure
29+
30+
- `__tests__/paneRegistry.test.js` - Main test suite
31+
- Tests use Jest framework with comprehensive mocking
32+
- Console output is mocked to avoid noise during testing
33+
- State is reset between tests for isolation
34+
35+
## Coverage Report
36+
37+
After running tests, view the coverage report:
38+
- Text summary in console
39+
- HTML report in `coverage/` directory

__tests__/paneRegistry.test.js

Lines changed: 336 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,336 @@
1+
const paneRegistry = require('../src/paneRegistry')
2+
3+
describe('PaneRegistry', () => {
4+
let originalConsoleLog
5+
let originalConsoleWarn
6+
let mockConsoleLog
7+
let mockConsoleWarn
8+
9+
beforeEach(() => {
10+
// Reset the registry state before each test
11+
paneRegistry.list = []
12+
paneRegistry.paneForIcon = []
13+
paneRegistry.paneForPredicate = []
14+
15+
// Clear any dynamically added panes
16+
Object.keys(paneRegistry).forEach(key => {
17+
if (!['list', 'paneForIcon', 'paneForPredicate', 'register', 'byName'].includes(key)) {
18+
delete paneRegistry[key]
19+
}
20+
})
21+
22+
// Mock console methods to avoid noise during tests
23+
originalConsoleLog = console.log
24+
originalConsoleWarn = console.warn
25+
mockConsoleLog = jest.fn()
26+
mockConsoleWarn = jest.fn()
27+
console.log = mockConsoleLog
28+
console.warn = mockConsoleWarn
29+
})
30+
31+
afterEach(() => {
32+
// Restore console methods
33+
console.log = originalConsoleLog
34+
console.warn = originalConsoleWarn
35+
})
36+
37+
describe('Initial State', () => {
38+
it('should have empty arrays for list, paneForIcon, and paneForPredicate', () => {
39+
expect(paneRegistry.list).toEqual([])
40+
expect(paneRegistry.paneForIcon).toEqual([])
41+
expect(paneRegistry.paneForPredicate).toEqual([])
42+
})
43+
44+
it('should have register and byName functions', () => {
45+
expect(typeof paneRegistry.register).toBe('function')
46+
expect(typeof paneRegistry.byName).toBe('function')
47+
})
48+
})
49+
50+
describe('register function', () => {
51+
const createValidPane = (overrides = {}) => ({
52+
name: 'testPane',
53+
label: 'Test Pane',
54+
icon: 'test-icon',
55+
predicates: { 'http://example.com/test': 1 },
56+
...overrides
57+
})
58+
59+
it('should register a valid pane successfully', () => {
60+
const pane = createValidPane()
61+
62+
paneRegistry.register(pane)
63+
64+
expect(paneRegistry.list).toHaveLength(1)
65+
expect(paneRegistry.list[0]).toEqual(expect.objectContaining({
66+
name: 'testPane',
67+
label: 'Test Pane',
68+
requireQueryButton: undefined
69+
}))
70+
expect(mockConsoleLog).toHaveBeenCalledWith(' registering pane: testPane')
71+
})
72+
73+
it('should set requireQueryButton property', () => {
74+
const pane = createValidPane()
75+
76+
paneRegistry.register(pane, true)
77+
78+
expect(paneRegistry.list[0].requireQueryButton).toBe(true)
79+
})
80+
81+
it('should add pane to paneRegistry object by name', () => {
82+
const pane = createValidPane()
83+
84+
paneRegistry.register(pane)
85+
86+
expect(paneRegistry.testPane).toBe(pane)
87+
})
88+
89+
it('should not overwrite existing pane methods', () => {
90+
const existingRegister = paneRegistry.register
91+
const pane = createValidPane({ name: 'register' })
92+
93+
paneRegistry.register(pane)
94+
95+
expect(paneRegistry.register).toBe(existingRegister)
96+
expect(paneRegistry.list).toHaveLength(1)
97+
})
98+
99+
it('should index pane by icon', () => {
100+
const pane = createValidPane({ icon: 'special-icon' })
101+
102+
paneRegistry.register(pane)
103+
104+
expect(paneRegistry.paneForIcon['special-icon']).toBe(pane)
105+
})
106+
107+
it('should index pane by predicates', () => {
108+
const pane = createValidPane({
109+
predicates: {
110+
'http://example.com/test1': 1,
111+
'http://example.com/test2': 2
112+
}
113+
})
114+
115+
paneRegistry.register(pane)
116+
117+
expect(paneRegistry.paneForPredicate['http://example.com/test1']).toEqual({
118+
pred: 'http://example.com/test1',
119+
code: 1
120+
})
121+
expect(paneRegistry.paneForPredicate['http://example.com/test2']).toEqual({
122+
pred: 'http://example.com/test2',
123+
code: 2
124+
})
125+
})
126+
127+
it('should handle pane without icon', () => {
128+
const pane = createValidPane({ icon: undefined })
129+
delete pane.icon
130+
131+
paneRegistry.register(pane)
132+
133+
expect(paneRegistry.list).toHaveLength(1)
134+
expect(Object.keys(paneRegistry.paneForIcon)).toHaveLength(0)
135+
})
136+
137+
it('should handle pane without predicates', () => {
138+
const pane = createValidPane({ predicates: undefined })
139+
delete pane.predicates
140+
141+
paneRegistry.register(pane)
142+
143+
expect(paneRegistry.list).toHaveLength(1)
144+
expect(Object.keys(paneRegistry.paneForPredicate)).toHaveLength(0)
145+
})
146+
147+
it('should not register pane without name', () => {
148+
const pane = createValidPane({ name: undefined })
149+
delete pane.name
150+
151+
paneRegistry.register(pane)
152+
153+
expect(paneRegistry.list).toHaveLength(0)
154+
expect(mockConsoleLog).toHaveBeenCalledWith('*** No name for pane!')
155+
})
156+
157+
it('should not register pane with empty name', () => {
158+
const pane = createValidPane({ name: '' })
159+
160+
paneRegistry.register(pane)
161+
162+
expect(paneRegistry.list).toHaveLength(0)
163+
expect(mockConsoleLog).toHaveBeenCalledWith('*** No name for pane!')
164+
})
165+
166+
it('should not register pane without label', () => {
167+
const pane = createValidPane({ label: undefined })
168+
delete pane.label
169+
170+
paneRegistry.register(pane)
171+
172+
expect(paneRegistry.list).toHaveLength(0)
173+
expect(mockConsoleLog).toHaveBeenCalledWith('*** No label for pane!')
174+
})
175+
176+
it('should not register pane with empty label', () => {
177+
const pane = createValidPane({ label: '' })
178+
179+
paneRegistry.register(pane)
180+
181+
expect(paneRegistry.list).toHaveLength(0)
182+
expect(mockConsoleLog).toHaveBeenCalledWith('*** No label for pane!')
183+
})
184+
185+
it('should register multiple panes', () => {
186+
const pane1 = createValidPane({ name: 'pane1', icon: 'icon1' })
187+
const pane2 = createValidPane({ name: 'pane2', icon: 'icon2' })
188+
189+
paneRegistry.register(pane1)
190+
paneRegistry.register(pane2)
191+
192+
expect(paneRegistry.list).toHaveLength(2)
193+
expect(paneRegistry.pane1).toBe(pane1)
194+
expect(paneRegistry.pane2).toBe(pane2)
195+
expect(paneRegistry.paneForIcon.icon1).toBe(pane1)
196+
expect(paneRegistry.paneForIcon.icon2).toBe(pane2)
197+
})
198+
})
199+
200+
describe('byName function', () => {
201+
it('should return pane when found by name', () => {
202+
const pane = {
203+
name: 'testPane',
204+
label: 'Test Pane'
205+
}
206+
207+
paneRegistry.register(pane)
208+
const result = paneRegistry.byName('testPane')
209+
210+
expect(result).toBe(pane)
211+
expect(mockConsoleWarn).not.toHaveBeenCalled()
212+
})
213+
214+
it('should return null when pane not found', () => {
215+
const result = paneRegistry.byName('nonexistentPane')
216+
217+
expect(result).toBeNull()
218+
expect(mockConsoleWarn).toHaveBeenCalledWith(
219+
'No view with name nonexistentPane found in the registry of views (aka paneRegistry)'
220+
)
221+
})
222+
223+
it('should return first matching pane when multiple panes exist', () => {
224+
const pane1 = { name: 'testPane', label: 'Test Pane 1' }
225+
const pane2 = { name: 'otherPane', label: 'Other Pane' }
226+
const pane3 = { name: 'thirdPane', label: 'Third Pane' }
227+
228+
paneRegistry.register(pane1)
229+
paneRegistry.register(pane2)
230+
paneRegistry.register(pane3)
231+
232+
const result = paneRegistry.byName('otherPane')
233+
234+
expect(result).toBe(pane2)
235+
})
236+
237+
it('should handle empty string name', () => {
238+
const result = paneRegistry.byName('')
239+
240+
expect(result).toBeNull()
241+
expect(mockConsoleWarn).toHaveBeenCalledWith(
242+
'No view with name found in the registry of views (aka paneRegistry)'
243+
)
244+
})
245+
246+
it('should handle null/undefined name', () => {
247+
const resultNull = paneRegistry.byName(null)
248+
const resultUndefined = paneRegistry.byName(undefined)
249+
250+
expect(resultNull).toBeNull()
251+
expect(resultUndefined).toBeNull()
252+
})
253+
})
254+
255+
describe('Integration Tests', () => {
256+
it('should handle complex pane registration workflow', () => {
257+
const chatPane = {
258+
name: 'chat',
259+
label: 'Chat Pane',
260+
icon: 'chat-icon',
261+
predicates: {
262+
'http://www.w3.org/ns/pim/meeting#Chat': 1
263+
}
264+
}
265+
266+
const profilePane = {
267+
name: 'profile',
268+
label: 'Profile Pane',
269+
icon: 'profile-icon',
270+
predicates: {
271+
'http://xmlns.com/foaf/0.1/Person': 2
272+
}
273+
}
274+
275+
// Register panes
276+
paneRegistry.register(chatPane, true)
277+
paneRegistry.register(profilePane, false)
278+
279+
// Verify registration
280+
expect(paneRegistry.list).toHaveLength(2)
281+
expect(paneRegistry.chat).toBe(chatPane)
282+
expect(paneRegistry.profile).toBe(profilePane)
283+
expect(chatPane.requireQueryButton).toBe(true)
284+
expect(profilePane.requireQueryButton).toBe(false)
285+
286+
// Verify icon indexing
287+
expect(paneRegistry.paneForIcon['chat-icon']).toBe(chatPane)
288+
expect(paneRegistry.paneForIcon['profile-icon']).toBe(profilePane)
289+
290+
// Verify predicate indexing
291+
expect(paneRegistry.paneForPredicate['http://www.w3.org/ns/pim/meeting#Chat']).toEqual({
292+
pred: 'http://www.w3.org/ns/pim/meeting#Chat',
293+
code: 1
294+
})
295+
296+
// Verify lookup
297+
expect(paneRegistry.byName('chat')).toBe(chatPane)
298+
expect(paneRegistry.byName('profile')).toBe(profilePane)
299+
expect(paneRegistry.byName('unknown')).toBeNull()
300+
})
301+
302+
it('should maintain registry integrity across multiple operations', () => {
303+
const panes = Array.from({ length: 5 }, (_, i) => ({
304+
name: `pane${i}`,
305+
label: `Pane ${i}`,
306+
icon: `icon${i}`,
307+
predicates: { [`http://example.com/pred${i}`]: i }
308+
}))
309+
310+
// Register all panes
311+
panes.forEach(pane => paneRegistry.register(pane))
312+
313+
// Verify all are registered
314+
expect(paneRegistry.list).toHaveLength(5)
315+
316+
// Verify all can be found by name
317+
panes.forEach(pane => {
318+
expect(paneRegistry.byName(pane.name)).toBe(pane)
319+
})
320+
321+
// Verify icon indexing
322+
panes.forEach(pane => {
323+
expect(paneRegistry.paneForIcon[pane.icon]).toBe(pane)
324+
})
325+
326+
// Verify predicate indexing
327+
panes.forEach((pane, i) => {
328+
const predKey = `http://example.com/pred${i}`
329+
expect(paneRegistry.paneForPredicate[predKey]).toEqual({
330+
pred: predKey,
331+
code: i
332+
})
333+
})
334+
})
335+
})
336+
})

0 commit comments

Comments
 (0)