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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/demo/app-root.ts +6 -4
  2. package/dist/demo/app-root.d.ts +0 -1
  3. package/dist/demo/app-root.js +1 -3
  4. package/dist/demo/app-root.js.map +1 -1
  5. package/dist/src/interfaces/nav-controller-interface.d.ts +9 -0
  6. package/dist/src/interfaces/nav-controller-interface.js.map +1 -1
  7. package/dist/src/item-inspector/item-inspector.d.ts +0 -47
  8. package/dist/src/item-inspector/item-inspector.js +253 -271
  9. package/dist/src/item-inspector/item-inspector.js.map +1 -1
  10. package/dist/src/item-navigator.d.ts +14 -7
  11. package/dist/src/item-navigator.js +60 -30
  12. package/dist/src/item-navigator.js.map +1 -1
  13. package/dist/src/no-theater-available.d.ts +9 -0
  14. package/dist/src/no-theater-available.js +79 -0
  15. package/dist/src/no-theater-available.js.map +1 -0
  16. package/dist/test/book-nav-stub.d.ts +17 -0
  17. package/dist/test/book-nav-stub.js +42 -0
  18. package/dist/test/book-nav-stub.js.map +1 -0
  19. package/dist/test/ia-item-navigator.test.d.ts +1 -0
  20. package/dist/test/ia-item-navigator.test.js +146 -114
  21. package/dist/test/ia-item-navigator.test.js.map +1 -1
  22. package/dist/test/ia-stub.d.ts +22 -0
  23. package/dist/test/ia-stub.js +34 -3
  24. package/dist/test/ia-stub.js.map +1 -1
  25. package/dist/test/no-theater-available.test.d.ts +1 -0
  26. package/dist/test/no-theater-available.test.js +27 -0
  27. package/dist/test/no-theater-available.test.js.map +1 -0
  28. package/package.json +3 -2
  29. package/src/interfaces/nav-controller-interface.ts +13 -0
  30. package/src/item-navigator.ts +69 -36
  31. package/src/no-theater-available.ts +87 -0
  32. package/test/book-nav-stub.ts +35 -0
  33. package/test/ia-item-navigator.test.ts +191 -143
  34. package/test/ia-stub.ts +78 -2
  35. package/test/no-theater-available.test.ts +32 -0
  36. package/src/item-inspector/item-inspector.ts +0 -296
@@ -1,129 +1,113 @@
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';
5
+ import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
6
+ import { IntNavController } from '../src/interfaces/nav-controller-interface';
12
7
  import { ItemNavigator } from '../src/item-navigator';
13
8
  import '../src/item-navigator';
14
- // import { IaItemInspector } from '../src/item-inspector/item-inspector';
15
9
 
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
- // }
32
-
33
- // rawResponse: any;
34
-
35
- // created: number;
36
-
37
- // d1: string;
38
-
39
- // d2: string;
40
-
41
- // dir: string;
42
-
43
- // files: File[];
44
-
45
- // files_count: number;
46
-
47
- // item_last_updated: number;
48
-
49
- // item_size: number;
50
-
51
- // metadata: Metadata;
52
-
53
- // server: string;
54
-
55
- // uniq: number;
56
-
57
- // workable_servers: string[];
58
-
59
- // speech_vs_music_asr?: SpeechMusicASREntry[] | undefined;
60
-
61
- // reviews?: Review[] | undefined;
62
- // };
10
+ import '../test/book-nav-stub';
11
+ import { ItemStub, menuProvider, shortcut } from '../test/ia-stub';
12
+ import { IntManageSideMenuEvent } from '../src/interfaces/event-interfaces';
63
13
 
64
14
  afterEach(() => {
65
15
  Sinon.restore();
66
16
  });
67
17
 
68
18
  describe('ItemNavigator', () => {
69
- describe('Loading Behavior', () => {
70
- it('shows the spinning loader', async () => {
19
+ describe('Theaters', () => {
20
+ it('shows <ia-no-theater-available> by default', async () => {
71
21
  const el = await fixture<ItemNavigator>(
72
- html`<ia-item-navigator></ia-item-navigator>`
22
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
73
23
  );
74
- expect(el.shadowRoot?.querySelector('ia-itemnav-loader')).to.be.exist;
24
+ expect(el.shadowRoot?.querySelector('ia-no-theater-available')).to.exist;
25
+ });
26
+
27
+ it('shows <book-navigator> if `this.itemType = "bookreader"`', async () => {
28
+ const el = await fixture<ItemNavigator>(
29
+ html`<ia-item-navigator
30
+ .itemType=${`bookreader`}
31
+ .item=${new ItemStub()}
32
+ ></ia-item-navigator>`
33
+ );
34
+
35
+ await el.updateComplete;
36
+
37
+ el.toggleMenu();
38
+ await el.updateComplete;
39
+
40
+ const bookNavigator = el.shadowRoot?.querySelector(
41
+ 'book-navigator'
42
+ ) as IntNavController;
43
+ await bookNavigator.updateComplete;
44
+
45
+ console.log('132234234324324324');
46
+ // TODO: add BookNavigator type & import via @internetarchive/bookreader
47
+ // For now, let's check that the BookNavigator element and its properties exist w/ stub
48
+ expect(bookNavigator).to.exist;
49
+ expect(bookNavigator?.modal).to.exist;
50
+ expect(bookNavigator?.baseHost).to.exist;
51
+ expect(bookNavigator?.book).to.exist;
52
+ expect(bookNavigator?.signedIn).to.be.null;
53
+ expect(bookNavigator?.sharedObserver).to.exist;
54
+ expect(bookNavigator?.sideMenuOpen).to.exist;
75
55
  });
76
- it('hides reader section if not `loaded`', async () => {
56
+ });
57
+ describe('`el.loaded`', () => {
58
+ it('toggles the spinning loader', async () => {
77
59
  const el = await fixture<ItemNavigator>(
78
60
  html`<ia-item-navigator></ia-item-navigator>`
79
61
  );
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);
62
+ expect(el.loaded).to.be.null; // initial load
63
+ expect(el.shadowRoot?.querySelector('ia-itemnav-loader')).to.exist;
85
64
  });
86
- it('shows reader once `loaded`', async () => {
65
+ it('hides reader section if `!loaded`', async () => {
87
66
  const el = await fixture<ItemNavigator>(
88
67
  html`<ia-item-navigator></ia-item-navigator>`
89
68
  );
90
- el.loaded = true;
91
- await el.updateComplete;
69
+
70
+ expect(
71
+ el.shadowRoot?.querySelector('#reader')?.getAttribute('class')
72
+ ).to.contain('hide');
73
+ });
74
+ it('shows reader when `loaded` ', async () => {
75
+ const el = await fixture<ItemNavigator>(
76
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
77
+ );
92
78
 
93
79
  const mainTheaterSection = el.shadowRoot?.querySelector('#reader');
94
80
  expect(mainTheaterSection?.classList.contains('hide')).to.be.false;
95
81
  expect(el.loaded).to.be.true;
96
82
  // `loaded` property is reflected as DOM attribute
97
83
  expect(el.hasAttribute('loaded')).to.equal(true);
84
+ expect(el.shadowRoot?.querySelector('ia-no-theater-available')).to.exist;
98
85
  });
86
+ it('listens to `@loadingStateUpdated` to update `loaded`', async () => {
87
+ const el = await fixture<ItemNavigator>(
88
+ html`<ia-item-navigator></ia-item-navigator>`
89
+ );
99
90
 
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;
108
-
109
- // expect(el?.item).to.not.be.undefined;
110
-
111
- // const mainTheaterSection = el.shadowRoot?.querySelector('#reader');
112
-
113
- // const contentController = mainTheaterSection?.querySelector('ia-item-inspector');
114
-
115
- // expect(contentController).to.equal(32324);
116
-
117
- // // const loadingEvent = new CustomEvent('loadingStateUpdated', { detail: { loaded: true }}) as IntLoadingStateUpdatedEvent;
118
- // // contentController?.emitLoadingStatusUpdate(true);
91
+ await el.updateComplete;
92
+ const spy = Sinon.spy();
93
+ el.loadingStateUpdated = spy;
94
+ el.loaded = false;
95
+ await el.updateComplete;
96
+ // check base properties
97
+ expect(el.loaded).to.equal(false);
98
+ expect(el.item).to.be.undefined;
119
99
 
120
- // // await contentController?.updateComplete;
121
- // // await el.updateComplete;
100
+ // hydrate item
101
+ el.item = new ItemStub();
102
+ await el.updateComplete;
122
103
 
123
- // });
104
+ // spy fires
105
+ expect(spy.called).to.equal(true);
106
+ expect(spy.callCount).to.equal(1);
107
+ });
124
108
  });
125
109
 
126
- describe('It uses a shared ResizeObserver', () => {
110
+ describe('`el.sharedObserver`', () => {
127
111
  it('can create one', async () => {
128
112
  const el = await fixture<ItemNavigator>(
129
113
  html`<ia-item-navigator></ia-item-navigator>`
@@ -146,7 +130,7 @@ describe('ItemNavigator', () => {
146
130
  });
147
131
  });
148
132
 
149
- describe('It uses a shared modal component', () => {
133
+ describe('`el.modal`', () => {
150
134
  it('can create one', async () => {
151
135
  const el = await fixture<ItemNavigator>(
152
136
  html`<ia-item-navigator></ia-item-navigator>`
@@ -171,59 +155,123 @@ describe('ItemNavigator', () => {
171
155
  });
172
156
  });
173
157
 
174
- // describe('full browser window immersion "fullscreen"', () => {
175
- // it('creates reflected attribute `viewportinfullscreen`', () =>{
176
- // /** to help with external styling adjustmnents */
177
- // });
178
- // });
158
+ describe('full browser window immersion "fullscreen"', () => {
159
+ it('creates reflected attribute `viewportinfullscreen`', async () => {
160
+ /** to help with external styling adjustmnents */
161
+ const el = await fixture<ItemNavigator>(
162
+ html`<ia-item-navigator></ia-item-navigator>`
163
+ );
164
+ expect(el.getAttribute('viewportinfullscreen')).to.be.null;
165
+
166
+ el.viewportInFullscreen = true;
167
+ await el.updateComplete;
168
+
169
+ expect(el.getAttribute('viewportinfullscreen')).to.exist;
170
+ });
171
+ });
179
172
 
180
- // describe('Loads side menu contents', () =>{
181
- // });
173
+ /* Side menu & shortcuts tests */
174
+ describe('el.menuOpened', () => {
175
+ it('toggles side menu open', async () => {
176
+ const el = await fixture<ItemNavigator>(
177
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
178
+ );
182
179
 
183
- // describe('Menu Shortcuts', () => {
184
- // });
180
+ el.menuContents = [menuProvider];
181
+ await el.updateComplete;
185
182
 
186
- // it('passes the a11y audit', async () => {
187
- // const el = await fixture<YourWebComponent>(
188
- // html`<your-webcomponent></your-webcomponent>`
189
- // );
183
+ const nav = el.shadowRoot?.querySelector('nav');
190
184
 
191
- // await expect(el).shadowDom.to.be.accessible();
192
- // });
193
- });
185
+ expect(nav?.querySelector('#menu')).to.exist;
186
+ // side menu starts closed
187
+ expect(el.menuOpened).to.be.false;
188
+ expect(nav?.querySelector('#menu')?.getAttribute('class')).to.contain(
189
+ 'hidden'
190
+ );
191
+
192
+ // let's open menu
193
+ el.toggleMenu();
194
+ await el.updateComplete;
195
+
196
+ expect(el.menuOpened).to.be.true;
197
+ expect(nav?.querySelector('#menu')?.getAttribute('class')).to.not.contain(
198
+ 'hidden'
199
+ );
200
+ });
201
+
202
+ it('opens menu shortcut with `@manageSideMenuEvents`', async () => {
203
+ const el = await fixture<ItemNavigator>(
204
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
205
+ );
206
+ const detail = {
207
+ menuId: 'fullscreen',
208
+ action: 'open',
209
+ };
210
+
211
+ el.menuContents = [menuProvider];
212
+ await el.updateComplete;
213
+ const frame = el.shadowRoot?.querySelector('#frame');
214
+ // default menu open behavior is to side menu open, not overlay
215
+ expect(frame?.getAttribute('class')).to.contain('shift');
216
+
217
+ expect(el.menuOpened).to.be.false;
218
+ expect(el.openMenu).to.be.empty;
219
+ expect(frame?.getAttribute('class')).to.not.contain('open');
220
+
221
+ const event = new CustomEvent('updateSideMenu', {
222
+ detail,
223
+ }) as IntManageSideMenuEvent;
224
+ el.manageSideMenuEvents(event);
225
+ await el.updateComplete;
226
+
227
+ expect(el.shouldRenderMenu).to.be.true;
228
+ expect(el.menuOpened).to.be.true;
229
+ expect(el.openMenu).to.equal(detail.menuId);
230
+
231
+ expect(frame?.getAttribute('class')).to.contain('open');
232
+ });
233
+ });
234
+
235
+ describe('el.menuContents', () => {
236
+ it('draws side menu when populated', async () => {
237
+ const el = await fixture<ItemNavigator>(
238
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
239
+ );
240
+
241
+ el.menuContents = [menuProvider];
242
+ await el.updateComplete;
243
+ expect(el.menuContents.length).to.exist;
244
+ expect(el.shouldRenderMenu).to.be.true;
245
+
246
+ const nav = el.shadowRoot?.querySelector('nav');
247
+ expect(nav).to.exist;
194
248
 
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
- // });
249
+ const menuSlider = nav?.querySelector('ia-menu-slider');
250
+ expect(menuSlider).to.exist;
251
+ expect(menuSlider?.getAttribute('manuallyhandleclose')).to.exist;
252
+ expect(menuSlider?.getAttribute('open')).to.exist;
253
+ });
254
+ });
255
+
256
+ describe('`el.menuShortcuts`', () => {
257
+ it('displays shortcut & toggle side menu button', async () => {
258
+ const el = await fixture<ItemNavigator>(
259
+ html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
260
+ );
261
+
262
+ el.menuContents = [menuProvider];
263
+ el.menuShortcuts = [shortcut];
264
+ await el.updateComplete;
265
+
266
+ const nav = el.shadowRoot?.querySelector('nav');
267
+
268
+ expect(el.menuShortcuts.length).to.exist;
269
+ expect(nav).to.exist;
270
+ expect(nav?.querySelector('.shortcuts')).to.exist;
271
+ expect(
272
+ nav?.querySelector('.shortcuts')?.querySelector('i.fullscreen-test')
273
+ ).to.exist;
274
+ expect(nav?.querySelector('.toggle-menu')).to.exist;
275
+ });
276
+ });
277
+ });
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
+ IntMenuShortcut,
12
+ IntMenuProvider,
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 IntMenuShortcut;
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 IntMenuProvider;
@@ -0,0 +1,32 @@
1
+ import { html, fixture, expect } from '@open-wc/testing';
2
+ import { IANoTheaterAvailable } from '../src/no-theater-available';
3
+ import '../src/no-theater-available';
4
+
5
+ describe('IANoTheaterAvailable', () => {
6
+ it('Fires `loadingStateUpdated` on identifier change', async () => {
7
+ const el = await fixture<IANoTheaterAvailable>(
8
+ html`<ia-no-theater-available
9
+ .identifier=${`foo`}
10
+ ></ia-no-theater-available>`
11
+ );
12
+ let eventFired = false;
13
+ el.addEventListener('loadingStateUpdated', () => {
14
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
15
+ eventFired = true;
16
+ });
17
+ expect(eventFired).to.be.false;
18
+
19
+ el.identifier = 'bar';
20
+ await el.updateComplete;
21
+ expect(eventFired).to.be.true;
22
+ });
23
+ it('Has link to item download page', async () => {
24
+ const el = await fixture<IANoTheaterAvailable>(
25
+ html`<ia-no-theater-available
26
+ .identifier=${`foo`}
27
+ ></ia-no-theater-available>`
28
+ );
29
+ expect(el.downloadUrl).to.equal('/download/foo');
30
+ expect(el?.shadowRoot?.querySelector('a')?.href).to.contain(el.downloadUrl);
31
+ });
32
+ });