Skip to content

Commit 5d18a5b

Browse files
committed
refactor!(navigation): pass id of view to setActive
This ensures only registered views can be set as active. Otherwise one could set unknown views as active. Additionally this ensures that all views the navigation handles are validated in `registerView`. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent a362b02 commit 5d18a5b

2 files changed

Lines changed: 33 additions & 6 deletions

File tree

__tests__/navigation.spec.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ describe('Navigation', () => {
109109

110110
expect(navigation.active).toBe(null)
111111

112-
navigation.setActive(view)
112+
navigation.setActive(view.id)
113113
expect(navigation.active).toEqual(view)
114114
})
115115

@@ -122,9 +122,25 @@ describe('Navigation', () => {
122122
const listener = vi.fn()
123123
navigation.addEventListener('updateActive', listener)
124124

125-
navigation.setActive(view)
125+
navigation.setActive(view.id)
126126
expect(listener).toHaveBeenCalledOnce()
127127
// So it was called, we then expect the first argument of the first call to be the event with the view as the detail
128128
expect(listener.mock.calls[0][0].detail).toBe(view)
129129
})
130+
131+
it('Can unset the active view', async () => {
132+
const navigation = new Navigation()
133+
const { view } = mockView()
134+
navigation.register(view)
135+
navigation.setActive(view.id)
136+
expect(navigation.active).toEqual(view)
137+
138+
navigation.setActive(null)
139+
expect(navigation.active).toBeNull()
140+
})
141+
142+
it('Throws when there is no view to set active', () => {
143+
const navigation = new Navigation()
144+
expect(() => navigation.setActive('does not exist')).toThrowError()
145+
})
130146
})

lib/navigation/navigation.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,23 @@ export class Navigation extends TypedEventTarget<{ updateActive: UpdateActiveVie
8181

8282
/**
8383
* Set the currently active view
84+
*
85+
* @param id - The id of the view to set as active
86+
* @throws {Error} If no view with the given id was registered
8487
* @fires UpdateActiveViewEvent
85-
* @param view New active view
8688
*/
87-
setActive(view: IView | null): void {
88-
this._currentView = view
89-
const event = new CustomEvent<IView | null>('updateActive', { detail: view })
89+
setActive(id: string | null): void {
90+
if (id === null) {
91+
this._currentView = null
92+
} else {
93+
const view = this._views.find(({ id: viewId }) => viewId === id)
94+
if (!view) {
95+
throw new Error(`No view with ${id} registered`)
96+
}
97+
this._currentView = view
98+
}
99+
100+
const event = new CustomEvent<IView | null>('updateActive', { detail: this._currentView })
90101
this.dispatchTypedEvent('updateActive', event as UpdateActiveViewEvent)
91102
}
92103

0 commit comments

Comments
 (0)