@internetarchive/ia-item-navigator 0.0.0-a10 → 0.0.0-a16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. package/README.md +29 -19
  2. package/demo/app-root.ts +37 -31
  3. package/demo/index.html +1 -0
  4. package/dist/demo/app-root.d.ts +11 -15
  5. package/dist/demo/app-root.js +26 -26
  6. package/dist/demo/app-root.js.map +1 -1
  7. package/dist/src/interfaces/custom-theater-interface.d.ts +20 -0
  8. package/dist/src/interfaces/custom-theater-interface.js +2 -0
  9. package/dist/src/interfaces/custom-theater-interface.js.map +1 -0
  10. package/dist/src/interfaces/event-interfaces.d.ts +11 -11
  11. package/dist/src/interfaces/event-interfaces.js.map +1 -1
  12. package/dist/src/interfaces/menu-interfaces.d.ts +6 -7
  13. package/dist/src/interfaces/menu-interfaces.js.map +1 -1
  14. package/dist/src/interfaces/nav-controller-interface.d.ts +11 -6
  15. package/dist/src/interfaces/nav-controller-interface.js.map +1 -1
  16. package/dist/src/item-inspector/item-inspector.d.ts +0 -47
  17. package/dist/src/item-inspector/item-inspector.js +253 -271
  18. package/dist/src/item-inspector/item-inspector.js.map +1 -1
  19. package/dist/src/item-navigator.d.ts +41 -27
  20. package/dist/src/item-navigator.js +87 -84
  21. package/dist/src/item-navigator.js.map +1 -1
  22. package/dist/src/no-theater-available.d.ts +9 -0
  23. package/dist/src/no-theater-available.js +79 -0
  24. package/dist/src/no-theater-available.js.map +1 -0
  25. package/dist/test/book-nav-stub.d.ts +22 -0
  26. package/dist/test/book-nav-stub.js +49 -0
  27. package/dist/test/book-nav-stub.js.map +1 -0
  28. package/dist/test/ia-item-navigator.test.d.ts +1 -0
  29. package/dist/test/ia-item-navigator.test.js +279 -131
  30. package/dist/test/ia-item-navigator.test.js.map +1 -1
  31. package/dist/test/ia-stub.d.ts +22 -0
  32. package/dist/test/ia-stub.js +34 -3
  33. package/dist/test/ia-stub.js.map +1 -1
  34. package/dist/test/no-theater-available.test.d.ts +1 -0
  35. package/dist/test/no-theater-available.test.js +27 -0
  36. package/dist/test/no-theater-available.test.js.map +1 -0
  37. package/package.json +4 -3
  38. package/src/interfaces/custom-theater-interface.ts +28 -0
  39. package/src/interfaces/event-interfaces.ts +15 -11
  40. package/src/interfaces/menu-interfaces.ts +9 -10
  41. package/src/item-navigator.ts +124 -114
  42. package/src/no-theater-available.ts +85 -0
  43. package/test/book-nav-stub.ts +47 -0
  44. package/test/ia-item-navigator.test.ts +365 -156
  45. package/test/ia-stub.ts +78 -2
  46. package/test/no-theater-available.test.ts +32 -0
  47. package/demo/demo-book-manifest.json +0 -1163
  48. package/src/interfaces/nav-controller-interface.ts +0 -18
  49. package/src/item-inspector/files-by-type/files-by-type-provider.ts +0 -43
  50. package/src/item-inspector/files-by-type/ia-files-by-type.ts +0 -100
  51. package/src/item-inspector/item-inspector.ts +0 -296
  52. package/src/item-inspector/share-provider.ts +0 -51
  53. package/src/item-inspector/visual-mod-provider.ts +0 -65
  54. package/src/item-navigator-js.js +0 -372
@@ -1,229 +1,438 @@
1
1
  /* eslint-disable camelcase */
2
- /* eslint-disable import/no-duplicates */
3
2
  import { html, fixture, expect } from '@open-wc/testing';
4
3
  import Sinon from 'sinon';
5
- // import { MetadataResponse, Metadata, File, Review, SpeechMusicASREntry } from '@internetarchive/search-service';
6
- import {
7
- SharedResizeObserver,
8
- // SharedResizeObserverInterface
9
- } from '@internetarchive/shared-resize-observer';
10
4
 
11
- // import { IntLoadingStateUpdatedEvent } from '../src/interfaces/event-interfaces';
12
- import { ItemNavigator } from '../src/item-navigator';
5
+ import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
6
+ import { ModalManager } from '@internetarchive/modal-manager';
7
+ import { CustomTheaterInterface } from '../src/interfaces/custom-theater-interface';
8
+ import { ItemNavigator, ItemType } from '../src/item-navigator';
13
9
  import '../src/item-navigator';
14
- // import { IaItemInspector } from '../src/item-inspector/item-inspector';
15
10
 
16
- // class ItemStub implements MetadataResponse {
17
- // constructor() {
18
- // this.rawResponse = '';
19
- // this.created = 1;
20
- // this.d1 = 'hello';
21
- // this.d2 = 'boop';
22
- // this.dir = 'whee';
23
- // this.files = [];
24
- // this.files_count = 0;
25
- // this.item_last_updated = 2020;
26
- // this.item_size = 111;
27
- // this.metadata = { identifier: 'foo' } as Metadata;
28
- // this.server = 'foo-server';
29
- // this.uniq = 2;
30
- // this.workable_servers = ['abc'];
31
- // }
11
+ import '../test/book-nav-stub';
12
+ import { ItemStub, menuProvider, shortcut } from '../test/ia-stub';
13
+ import {
14
+ ManageFullscreenEvent,
15
+ ToggleSideMenuOpenEvent,
16
+ SetSideMenuContentsEvent,
17
+ SetSideMenuShortcutsEvent,
18
+ ToggleSidePanelOpenEvent,
19
+ } from '../src/interfaces/event-interfaces';
32
20
 
33
- // rawResponse: any;
21
+ afterEach(() => {
22
+ Sinon.restore();
23
+ });
34
24
 
35
- // created: number;
25
+ describe('ItemNavigator', () => {
26
+ describe('Theaters', () => {
27
+ it('shows <ia-no-theater-available> by default', async () => {
28
+ const el = await fixture<ItemNavigator>(
29
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
30
+ );
31
+ expect(el.shadowRoot?.querySelector('ia-no-theater-available')).to.exist;
32
+ });
36
33
 
37
- // d1: string;
34
+ it('shows <book-navigator> if `this.itemType = "bookreader"`', async () => {
35
+ const el = await fixture<ItemNavigator>(
36
+ html`<ia-item-navigator
37
+ .itemType=${ItemType.BOOK}
38
+ .item=${new ItemStub()}
39
+ .modal=${new ModalManager()}
40
+ .sharedObserver=${new SharedResizeObserver()}
41
+ ></ia-item-navigator>`
42
+ );
38
43
 
39
- // d2: string;
44
+ await el.updateComplete;
40
45
 
41
- // dir: string;
46
+ el.toggleMenu();
47
+ await el.updateComplete;
42
48
 
43
- // files: File[];
49
+ const bookNavigator = el.shadowRoot?.querySelector(
50
+ 'book-navigator'
51
+ ) as CustomTheaterInterface;
52
+ await bookNavigator.updateComplete;
53
+
54
+ console.log('132234234324324324');
55
+ // TODO: add BookNavigator type & import via @internetarchive/bookreader
56
+ // For now, let's check that the BookNavigator element and its properties exist w/ stub
57
+ expect(bookNavigator).to.exist;
58
+ expect(bookNavigator?.modal).to.exist;
59
+ expect(bookNavigator?.baseHost).to.exist;
60
+ expect(bookNavigator?.signedIn).to.be.null;
61
+ expect(bookNavigator?.sharedObserver).to.exist;
62
+ expect(bookNavigator?.sideMenuOpen).to.exist;
63
+ });
64
+ });
65
+ describe('`el.loaded`', () => {
66
+ it('toggles the spinning loader', async () => {
67
+ const el = await fixture<ItemNavigator>(
68
+ html`<ia-item-navigator></ia-item-navigator>`
69
+ );
70
+ expect(el.loaded).to.be.null; // initial load
71
+ expect(el.shadowRoot?.querySelector('ia-itemnav-loader')).to.exist;
72
+ });
73
+ it('hides reader section if `!loaded`', async () => {
74
+ const el = await fixture<ItemNavigator>(
75
+ html`<ia-item-navigator></ia-item-navigator>`
76
+ );
44
77
 
45
- // files_count: number;
78
+ expect(
79
+ el.shadowRoot?.querySelector('#reader')?.getAttribute('class')
80
+ ).to.contain('hide');
81
+ });
82
+ it('shows reader when `loaded` ', async () => {
83
+ const el = await fixture<ItemNavigator>(
84
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
85
+ );
46
86
 
47
- // item_last_updated: number;
87
+ const mainTheaterSection = el.shadowRoot?.querySelector('#reader');
88
+ expect(mainTheaterSection?.classList.contains('hide')).to.be.false;
89
+ expect(el.loaded).to.be.true;
90
+ // `loaded` property is reflected as DOM attribute
91
+ expect(el.hasAttribute('loaded')).to.equal(true);
92
+ expect(el.shadowRoot?.querySelector('ia-no-theater-available')).to.exist;
93
+ });
94
+ it('listens to `@loadingStateUpdated` to update `loaded`', async () => {
95
+ const el = await fixture<ItemNavigator>(
96
+ html`<ia-item-navigator></ia-item-navigator>`
97
+ );
48
98
 
49
- // item_size: number;
99
+ await el.updateComplete;
100
+ const spy = Sinon.spy();
101
+ el.loadingStateUpdated = spy;
102
+ el.loaded = null;
103
+ await el.updateComplete;
104
+ // check base properties
105
+ expect(el.loaded).to.equal(null);
106
+ expect(el.item).to.be.undefined;
50
107
 
51
- // metadata: Metadata;
108
+ // hydrate item
109
+ el.item = new ItemStub();
110
+ await el.updateComplete;
52
111
 
53
- // server: string;
112
+ // spy fires
113
+ expect(spy.called).to.equal(true);
114
+ expect(spy.callCount).to.equal(1);
115
+ });
116
+ });
54
117
 
55
- // uniq: number;
118
+ describe('`el.sharedObserver`', () => {
119
+ it('uses one', async () => {
120
+ const sharedObserver = new SharedResizeObserver();
121
+ const el = await fixture<ItemNavigator>(
122
+ html`<ia-item-navigator
123
+ .sharedObserver=${sharedObserver}
124
+ ></ia-item-navigator>`
125
+ );
56
126
 
57
- // workable_servers: string[];
127
+ expect(el.sharedObserver).to.equal(sharedObserver);
128
+ expect(typeof el.handleResize).to.equal('function');
129
+ });
130
+ it('freshly registers handler', async () => {
131
+ const sharedObserver = new SharedResizeObserver();
132
+ const addObserverSpy = Sinon.spy(sharedObserver, 'addObserver');
58
133
 
59
- // speech_vs_music_asr?: SpeechMusicASREntry[] | undefined;
134
+ await fixture<ItemNavigator>(
135
+ html`<ia-item-navigator
136
+ .sharedObserver=${sharedObserver}
137
+ ></ia-item-navigator>`
138
+ );
60
139
 
61
- // reviews?: Review[] | undefined;
62
- // };
140
+ expect(addObserverSpy.callCount).to.equal(1);
141
+ });
142
+ it('removes handler when component disconnects', async () => {
143
+ const sharedObserver = new SharedResizeObserver();
144
+ const removeObserverSpy = Sinon.spy(sharedObserver, 'removeObserver');
63
145
 
64
- afterEach(() => {
65
- Sinon.restore();
66
- });
146
+ const el = await fixture<ItemNavigator>(
147
+ html`<ia-item-navigator
148
+ .sharedObserver=${sharedObserver}
149
+ ></ia-item-navigator>`
150
+ );
67
151
 
68
- describe('ItemNavigator', () => {
69
- describe('Loading Behavior', () => {
70
- it('shows the spinning loader', async () => {
152
+ el.disconnectedCallback();
153
+ await el.updateComplete;
154
+
155
+ expect(removeObserverSpy.callCount).to.equal(1);
156
+ });
157
+ it('sets menu to overlay if container width is <= 600px', async () => {
71
158
  const el = await fixture<ItemNavigator>(
72
159
  html`<ia-item-navigator></ia-item-navigator>`
73
160
  );
74
- expect(el.shadowRoot?.querySelector('ia-itemnav-loader')).to.be.exist;
161
+
162
+ expect(el.openMenuState).to.equal('shift'); // as starting point
163
+
164
+ const overlaySize = {
165
+ contentRect: { width: 600 },
166
+ } as ResizeObserverEntry;
167
+ el.handleResize(overlaySize);
168
+ await el.updateComplete;
169
+
170
+ expect(el.openMenuState).to.equal('overlay'); // changes open menu display to an overlay
171
+
172
+ const shiftSize = {
173
+ contentRect: { width: 601 },
174
+ } as ResizeObserverEntry;
175
+ el.handleResize(shiftSize);
176
+ await el.updateComplete;
177
+
178
+ expect(el.openMenuState).to.equal('shift');
179
+ });
180
+ });
181
+
182
+ describe('`el.modal`', () => {
183
+ it('uses one', async () => {
184
+ const modal = new ModalManager();
185
+ const el = await fixture<ItemNavigator>(
186
+ html`<ia-item-navigator .modal=${modal}></ia-item-navigator>`
187
+ );
188
+ expect(el.modal).to.equal(modal);
75
189
  });
76
- it('hides reader section if not `loaded`', async () => {
190
+ });
191
+
192
+ describe('full browser window immersion "fullscreen"', () => {
193
+ it('creates reflected attribute `viewportinfullscreen`', async () => {
194
+ /** to help with external styling adjustmnents */
77
195
  const el = await fixture<ItemNavigator>(
78
196
  html`<ia-item-navigator></ia-item-navigator>`
79
197
  );
80
- const mainTheaterSection = el.shadowRoot?.querySelector('#reader');
81
- expect(mainTheaterSection).to.be.exist;
82
- expect(mainTheaterSection?.classList.contains('hide')).to.be.true;
83
- expect(el.loaded).to.be.false;
84
- expect(el.hasAttribute('loaded')).to.equal(false);
198
+ expect(el.getAttribute('viewportinfullscreen')).to.be.null;
199
+
200
+ el.viewportInFullscreen = true;
201
+ await el.updateComplete;
202
+
203
+ expect(el.getAttribute('viewportinfullscreen')).to.exist;
85
204
  });
86
- it('shows reader once `loaded`', async () => {
205
+ it('@ViewportInFullScreen', async () => {
87
206
  const el = await fixture<ItemNavigator>(
88
207
  html`<ia-item-navigator></ia-item-navigator>`
89
208
  );
90
- el.loaded = true;
209
+ expect(el.viewportInFullscreen).to.be.null;
210
+
211
+ const yesFullscreenEvent = {
212
+ detail: {
213
+ isFullScreen: true,
214
+ },
215
+ } as ManageFullscreenEvent;
216
+ el.manageViewportFullscreen(yesFullscreenEvent);
91
217
  await el.updateComplete;
218
+ expect(el.viewportInFullscreen).to.be.true;
219
+
220
+ const noFullscreenEvent = {
221
+ detail: {
222
+ isFullScreen: false,
223
+ },
224
+ } as ManageFullscreenEvent;
225
+ el.manageViewportFullscreen(noFullscreenEvent);
226
+ await el.updateComplete;
227
+ expect(el.viewportInFullscreen).to.be.null;
228
+ });
229
+ });
92
230
 
93
- const mainTheaterSection = el.shadowRoot?.querySelector('#reader');
94
- expect(mainTheaterSection?.classList.contains('hide')).to.be.false;
95
- expect(el.loaded).to.be.true;
96
- // `loaded` property is reflected as DOM attribute
97
- expect(el.hasAttribute('loaded')).to.equal(true);
231
+ /* Side menu & shortcuts tests */
232
+ describe('el.menuOpened', () => {
233
+ it('toggles side menu open', async () => {
234
+ const el = await fixture<ItemNavigator>(
235
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
236
+ );
237
+
238
+ el.menuContents = [menuProvider];
239
+ await el.updateComplete;
240
+
241
+ const nav = el.shadowRoot?.querySelector('nav');
242
+
243
+ expect(nav?.querySelector('#menu')).to.exist;
244
+ // side menu starts closed
245
+ expect(el.menuOpened).to.be.false;
246
+ expect(nav?.querySelector('#menu')?.getAttribute('class')).to.contain(
247
+ 'hidden'
248
+ );
249
+
250
+ // let's open menu
251
+ el.toggleMenu();
252
+ await el.updateComplete;
253
+
254
+ expect(el.menuOpened).to.be.true;
255
+ expect(nav?.querySelector('#menu')?.getAttribute('class')).to.not.contain(
256
+ 'hidden'
257
+ );
98
258
  });
99
259
 
100
- // it('listens to event `loadingStateUpdated` to signal load', async () => {
101
- // const item = new ItemStub() as MetadataResponse;
102
- // const el = await fixture<ItemNavigator>(
103
- // html`<ia-item-navigator .item=${item}></ia-item-navigator>`
104
- // );
105
- // // const loadSpy = Sinon.spy();
106
- // // el.loadingStateUpdated = loadSpy;
107
- // await el.updateComplete;
260
+ it('opens menu shortcut with `@manageSideMenuEvents`', async () => {
261
+ const el = await fixture<ItemNavigator>(
262
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
263
+ );
264
+ const detail = {
265
+ menuId: 'fullscreen',
266
+ action: 'open',
267
+ };
108
268
 
109
- // expect(el?.item).to.not.be.undefined;
269
+ el.menuContents = [menuProvider];
270
+ await el.updateComplete;
271
+ const frame = el.shadowRoot?.querySelector('#frame');
272
+ // default menu open behavior is to side menu open, not overlay
273
+ expect(frame?.getAttribute('class')).to.contain('shift');
274
+
275
+ expect(el.menuOpened).to.be.false;
276
+ expect(el.openMenu).to.be.undefined;
277
+ expect(frame?.getAttribute('class')).to.not.contain('open');
278
+
279
+ const event = new CustomEvent('updateSideMenu', {
280
+ detail,
281
+ }) as ToggleSideMenuOpenEvent;
282
+ el.manageSideMenuEvents(event);
283
+ await el.updateComplete;
284
+
285
+ expect(el.shouldRenderMenu).to.be.true;
286
+ expect(el.menuOpened).to.be.true;
287
+ expect(el.openMenu).to.equal(detail.menuId);
110
288
 
111
- // const mainTheaterSection = el.shadowRoot?.querySelector('#reader');
289
+ expect(frame?.getAttribute('class')).to.contain('open');
112
290
 
113
- // const contentController = mainTheaterSection?.querySelector('ia-item-inspector');
291
+ // no menu provided
292
+ const openShortcutSpy = Sinon.spy(el, 'openShortcut');
293
+ const toggleMenuSpy = Sinon.spy(el, 'toggleMenu');
114
294
 
115
- // expect(contentController).to.equal(32324);
295
+ const noMenuProvidedEvent = new CustomEvent('updateSideMenu', {
296
+ detail: {},
297
+ }) as any;
298
+ el.manageSideMenuEvents(noMenuProvidedEvent);
299
+ await el.updateComplete;
116
300
 
117
- // // const loadingEvent = new CustomEvent('loadingStateUpdated', { detail: { loaded: true }}) as IntLoadingStateUpdatedEvent;
118
- // // contentController?.emitLoadingStatusUpdate(true);
301
+ expect(openShortcutSpy.called).to.be.false;
302
+ expect(toggleMenuSpy.called).to.be.false;
303
+
304
+ // toggle menu
305
+ const toggleMenuEvent = new CustomEvent('updateSideMenu', {
306
+ detail: { action: 'toggle', menuId: 'fullscreen' },
307
+ }) as any;
308
+ el.manageSideMenuEvents(toggleMenuEvent);
309
+ await el.updateComplete;
119
310
 
120
- // // await contentController?.updateComplete;
121
- // // await el.updateComplete;
311
+ expect(toggleMenuSpy.callCount).to.equal(1);
122
312
 
123
- // });
313
+ // open menu
314
+ const openMenuEvent = new CustomEvent('updateSideMenu', {
315
+ detail: { action: 'open', menuId: 'fullscreen' },
316
+ }) as any;
317
+ el.manageSideMenuEvents(openMenuEvent);
318
+ await el.updateComplete;
319
+
320
+ expect(openShortcutSpy.callCount).to.equal(1);
321
+ });
124
322
  });
125
323
 
126
- describe('It uses a shared ResizeObserver', () => {
127
- it('can create one', async () => {
324
+ describe('el.menuContents', () => {
325
+ it('draws side menu when populated', async () => {
128
326
  const el = await fixture<ItemNavigator>(
129
- html`<ia-item-navigator></ia-item-navigator>`
327
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
130
328
  );
329
+
330
+ el.menuContents = [menuProvider];
131
331
  await el.updateComplete;
132
- expect(el.sharedObserver).to.not.be.null;
133
- expect(el.sharedObserver).to.be.instanceOf(SharedResizeObserver);
134
- });
332
+ expect(el.menuContents.length).to.exist;
333
+ expect(el.shouldRenderMenu).to.be.true;
135
334
 
136
- it('can recieve one', async () => {
137
- const sharedObserver = new SharedResizeObserver();
335
+ const nav = el.shadowRoot?.querySelector('nav');
336
+ expect(nav).to.exist;
337
+
338
+ const menuSlider = nav?.querySelector('ia-menu-slider');
339
+ expect(menuSlider).to.exist;
340
+ expect(menuSlider?.getAttribute('manuallyhandleclose')).to.exist;
341
+ expect(menuSlider?.getAttribute('open')).to.exist;
342
+ });
343
+ });
138
344
 
345
+ describe('`el.menuShortcuts`', () => {
346
+ it('displays shortcut & toggle side menu button', async () => {
139
347
  const el = await fixture<ItemNavigator>(
140
- html`<ia-item-navigator
141
- .sharedObserver=${sharedObserver}
142
- ></ia-item-navigator>`
348
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
143
349
  );
350
+
351
+ const anotherShortcut = {
352
+ id: 'foo',
353
+ icon: html`<i class="foo-shortcut"></i>`,
354
+ };
355
+ el.menuContents = [menuProvider];
356
+ el.menuShortcuts = [shortcut, anotherShortcut];
144
357
  await el.updateComplete;
145
- expect(el.sharedObserver).to.be.instanceOf(SharedResizeObserver);
358
+
359
+ const nav = el.shadowRoot?.querySelector('nav');
360
+
361
+ const shortcutsContainer = nav?.querySelector('.shortcuts');
362
+ expect(el.menuShortcuts.length).to.exist;
363
+ expect(nav).to.exist;
364
+ expect(shortcutsContainer).to.exist;
365
+ expect(shortcutsContainer?.querySelector('i.fullscreen-test')).to.exist;
366
+ expect(shortcutsContainer?.querySelector('button.shortcut.foo')).to.exist;
367
+ expect(nav?.querySelector('.toggle-menu')).to.exist;
146
368
  });
147
369
  });
148
370
 
149
- describe('It uses a shared modal component', () => {
150
- it('can create one', async () => {
371
+ describe('Menu events', () => {
372
+ it('`el.setMenuShortcuts`', async () => {
151
373
  const el = await fixture<ItemNavigator>(
152
- html`<ia-item-navigator></ia-item-navigator>`
374
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
153
375
  );
376
+ expect(el.menuShortcuts.length).to.equal(0);
377
+
378
+ const menuShortcuts = [shortcut];
379
+
380
+ el.setMenuShortcuts({
381
+ detail: menuShortcuts,
382
+ } as SetSideMenuShortcutsEvent);
154
383
  await el.updateComplete;
155
- expect(el.sharedObserver).to.not.be.null;
156
- expect(el.sharedObserver).to.be.instanceOf(SharedResizeObserver);
384
+
385
+ expect(el.menuShortcuts.length).to.equal(1);
157
386
  });
387
+ it('`el.setMenuContents`', async () => {
388
+ const el = await fixture<ItemNavigator>(
389
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
390
+ );
391
+ expect(el.menuContents.length).to.equal(0);
158
392
 
159
- it('can recieve one', async () => {
160
- const sharedObserver = new SharedResizeObserver();
161
- const observerSpy = Sinon.stub(sharedObserver, 'addObserver');
393
+ el.setMenuShortcuts({
394
+ detail: [menuProvider],
395
+ } as SetSideMenuContentsEvent);
396
+ await el.updateComplete;
162
397
 
398
+ expect(el.menuShortcuts.length).to.equal(1);
399
+ });
400
+ it('`el.setOpenMenu`', async () => {
163
401
  const el = await fixture<ItemNavigator>(
164
- html`<ia-item-navigator
165
- .sharedObserver=${sharedObserver}
166
- ></ia-item-navigator>`
402
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
167
403
  );
404
+
405
+ el.setOpenMenu({
406
+ detail: { id: 'foo' },
407
+ } as ToggleSidePanelOpenEvent);
168
408
  await el.updateComplete;
169
- expect(el.sharedObserver).to.be.instanceOf(SharedResizeObserver);
170
- expect(observerSpy.called).to.equal(true);
171
- });
172
- });
173
409
 
174
- // describe('full browser window immersion "fullscreen"', () => {
175
- // it('creates reflected attribute `viewportinfullscreen`', () =>{
176
- // /** to help with external styling adjustmnents */
177
- // });
178
- // });
410
+ expect(el.openMenu).to.equal('foo');
411
+ expect(el.selectedMenuId).to.equal('foo');
179
412
 
180
- // describe('Loads side menu contents', () =>{
181
- // });
413
+ // toggles it off
414
+ el.setOpenMenu({
415
+ detail: { id: 'foo' },
416
+ } as ToggleSidePanelOpenEvent);
417
+ await el.updateComplete;
182
418
 
183
- // describe('Menu Shortcuts', () => {
184
- // });
419
+ expect(el.openMenu).to.be.undefined;
420
+ expect(el.selectedMenuId).to.equal('');
421
+ });
422
+ it('`el.closeMenu`', async () => {
423
+ const el = await fixture<ItemNavigator>(
424
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
425
+ );
185
426
 
186
- // it('passes the a11y audit', async () => {
187
- // const el = await fixture<YourWebComponent>(
188
- // html`<your-webcomponent></your-webcomponent>`
189
- // );
427
+ el.menuOpened = true;
428
+ await el.updateComplete;
190
429
 
191
- // await expect(el).shadowDom.to.be.accessible();
192
- // });
193
- });
430
+ expect(el.menuOpened).to.be.true;
194
431
 
195
- // describe('YourWebComponent', () => {
196
- // it('has a default title "Hey there" and counter 5', async () => {
197
- // const el = await fixture<YourWebComponent>(
198
- // html`<your-webcomponent></your-webcomponent>`
199
- // );
200
-
201
- // expect(el.title).to.equal('Hey there');
202
- // expect(el.counter).to.equal(5);
203
- // });
204
-
205
- // it('increases the counter on button click', async () => {
206
- // const el = await fixture<YourWebComponent>(
207
- // html`<your-webcomponent></your-webcomponent>`
208
- // );
209
- // el.shadowRoot!.querySelector('button')!.click();
210
-
211
- // expect(el.counter).to.equal(6);
212
- // });
213
-
214
- // it('can override the title via attribute', async () => {
215
- // const el = await fixture<YourWebComponent>(
216
- // html`<your-webcomponent title="attribute title"></your-webcomponent>`
217
- // );
218
-
219
- // expect(el.title).to.equal('attribute title');
220
- // });
221
-
222
- // it('passes the a11y audit', async () => {
223
- // const el = await fixture<YourWebComponent>(
224
- // html`<your-webcomponent></your-webcomponent>`
225
- // );
226
-
227
- // await expect(el).shadowDom.to.be.accessible();
228
- // });
229
- // });
432
+ el.closeMenu();
433
+ await el.updateComplete;
434
+
435
+ expect(el.menuOpened).to.be.false;
436
+ });
437
+ });
438
+ });
package/test/ia-stub.ts CHANGED
@@ -1,3 +1,79 @@
1
- // const parsed = JSON.parse(raw);
1
+ /* eslint-disable camelcase */
2
+ import {
3
+ MetadataResponse,
4
+ Metadata,
5
+ File,
6
+ Review,
7
+ SpeechMusicASREntry,
8
+ } from '@internetarchive/search-service';
9
+ import { html } from 'lit-html';
10
+ import {
11
+ MenuShortcutInterface,
12
+ MenuProviderInterface,
13
+ } from '../src/interfaces/menu-interfaces';
2
14
 
3
- // export default parsed;
15
+ export class ItemStub implements MetadataResponse {
16
+ constructor() {
17
+ this.rawResponse = '';
18
+ this.created = 1;
19
+ this.d1 = 'hello';
20
+ this.d2 = 'boop';
21
+ this.dir = 'whee';
22
+ this.files = [];
23
+ this.files_count = 0;
24
+ this.item_last_updated = 2020;
25
+ this.item_size = 111;
26
+ this.metadata = { identifier: 'foo' } as Metadata;
27
+ this.server = 'foo-server';
28
+ this.uniq = 2;
29
+ this.workable_servers = ['abc'];
30
+ }
31
+
32
+ rawResponse: any;
33
+
34
+ created: number;
35
+
36
+ d1: string;
37
+
38
+ d2: string;
39
+
40
+ dir: string;
41
+
42
+ files: File[];
43
+
44
+ files_count: number;
45
+
46
+ item_last_updated: number;
47
+
48
+ item_size: number;
49
+
50
+ metadata: Metadata;
51
+
52
+ server: string;
53
+
54
+ uniq: number;
55
+
56
+ workable_servers: string[];
57
+
58
+ speech_vs_music_asr?: SpeechMusicASREntry[] | undefined;
59
+
60
+ reviews?: Review[] | undefined;
61
+ }
62
+
63
+ export const shortcut = {
64
+ id: 'fullscreen',
65
+ icon: html`<i class="fas fullscreen-test"></i>`,
66
+ } as MenuShortcutInterface;
67
+
68
+ export const menuProvider = {
69
+ ...shortcut,
70
+ label: 'foo',
71
+ menuDetails: html`<div>foo</div>`,
72
+ selected: true,
73
+ followable: false,
74
+ href: 'https://archive.foo',
75
+ item: new ItemStub(),
76
+ baseHost: 'https://archive.foo',
77
+ subPrefix: 'bar',
78
+ updated: () => {},
79
+ } as MenuProviderInterface;