@triptease/tt-navbar 0.0.34 → 0.0.36
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.
- package/dist/src/NavbarController.d.ts +9 -0
- package/dist/src/NavbarController.js +29 -0
- package/dist/src/NavbarController.js.map +1 -0
- package/dist/src/TtNavbar.d.ts +1 -0
- package/dist/src/TtNavbar.js +34 -25
- package/dist/src/TtNavbar.js.map +1 -1
- package/dist/test/tt-navbar.test.js +58 -11
- package/dist/test/tt-navbar.test.js.map +1 -1
- package/dist/web/NavbarController.js +37 -0
- package/dist/web/NavbarController.js.map +7 -0
- package/dist/web/Routes.js +1 -1
- package/dist/web/TtNavbar.js +59 -24
- package/dist/web/TtNavbar.js.map +3 -3
- package/dist/web/global.d.js +4 -0
- package/dist/web/global.d.js.map +7 -0
- package/dist/web/index.js +59 -24
- package/dist/web/index.js.map +3 -3
- package/dist/web/styles.js +1 -1
- package/dist/web/triptease-logo.js +1 -1
- package/dist/web/tt-navbar.js +59 -24
- package/dist/web/tt-navbar.js.map +3 -3
- package/dist/web/urlMappings.js +1 -1
- package/package.json +2 -1
- package/src/NavbarController.ts +40 -0
- package/src/TtNavbar.ts +43 -28
- package/src/global.d.ts +16 -0
- package/test/tt-navbar.test.ts +144 -47
package/dist/web/urlMappings.js
CHANGED
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Webcomponent tt-navbar following open-wc recommendations",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "tt-navbar",
|
|
6
|
-
"version": "0.0.
|
|
6
|
+
"version": "0.0.36",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "dist/src/index.js",
|
|
9
9
|
"module": "dist/src/index.js",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"storybook:build": "tsc && npm run analyze -- --exclude dist && storybook build"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@clerk/clerk-js": "^5.102.1",
|
|
30
31
|
"@triptease/icons": "^1.1.1",
|
|
31
32
|
"@triptease/tt-combobox": "^5.3.0",
|
|
32
33
|
"lit": "^3.1.4"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
|
|
3
|
+
export class NavbarController implements ReactiveController {
|
|
4
|
+
host: ReactiveControllerHost;
|
|
5
|
+
|
|
6
|
+
private _isOpen = true;
|
|
7
|
+
|
|
8
|
+
constructor(host: ReactiveControllerHost) {
|
|
9
|
+
(this.host = host).addController(this);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get isOpen() {
|
|
13
|
+
return this._isOpen;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
hostConnected() {
|
|
17
|
+
if (window.Clerk) {
|
|
18
|
+
const userSetting =
|
|
19
|
+
window.Clerk.user?.unsafeMetadata?.preferences?.ui?.navigationOpen;
|
|
20
|
+
|
|
21
|
+
if (userSetting !== undefined) {
|
|
22
|
+
this._isOpen = userSetting;
|
|
23
|
+
this.host.requestUpdate();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async toggle() {
|
|
29
|
+
const newState = !this._isOpen;
|
|
30
|
+
this._isOpen = newState;
|
|
31
|
+
|
|
32
|
+
if (window.Clerk) {
|
|
33
|
+
await window.Clerk.user?.update({
|
|
34
|
+
unsafeMetadata: { preferences: { ui: { navigationOpen: newState } } },
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this.host.requestUpdate();
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/TtNavbar.ts
CHANGED
|
@@ -12,13 +12,14 @@ import {
|
|
|
12
12
|
logout,
|
|
13
13
|
sidebarCollapsed,
|
|
14
14
|
user,
|
|
15
|
-
wallet
|
|
15
|
+
wallet,
|
|
16
16
|
} from '@triptease/icons';
|
|
17
17
|
import '@triptease/tt-combobox';
|
|
18
18
|
import { styles } from './styles.js';
|
|
19
19
|
import { tripteaseLogo } from './triptease-logo.js';
|
|
20
20
|
import { urlMappings } from './urlMappings.js';
|
|
21
21
|
import { Routes } from './Routes.js';
|
|
22
|
+
import { NavbarController } from './NavbarController.js';
|
|
22
23
|
|
|
23
24
|
const jsonArrayConverter = (value: string | null) => {
|
|
24
25
|
if (!value) return [];
|
|
@@ -51,7 +52,7 @@ export class TtNavbar extends LitElement {
|
|
|
51
52
|
clients: { clientKey: string; displayName: string }[] = [];
|
|
52
53
|
|
|
53
54
|
@property({ type: Object })
|
|
54
|
-
onClientChange: ((clientKeySelected: string) => void
|
|
55
|
+
onClientChange: ((clientKeySelected: string) => void) | undefined;
|
|
55
56
|
|
|
56
57
|
@queryAll('details')
|
|
57
58
|
protected allDetailsElements!: Array<HTMLDetailsElement>;
|
|
@@ -62,19 +63,26 @@ export class TtNavbar extends LitElement {
|
|
|
62
63
|
@state()
|
|
63
64
|
private sidebarOpen = true;
|
|
64
65
|
|
|
66
|
+
private navbarController = new NavbarController(this);
|
|
67
|
+
|
|
65
68
|
protected firstUpdated() {
|
|
66
69
|
this.setActiveState();
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
public connectedCallback() {
|
|
70
|
-
|
|
73
|
+
// Listen for browser back/forward navigation
|
|
71
74
|
window.addEventListener('popstate', this.setActiveState);
|
|
75
|
+
|
|
76
|
+
// Listen for Tetris programmatic navigation
|
|
77
|
+
window.addEventListener('tetris:navigate', this.setActiveState);
|
|
78
|
+
|
|
72
79
|
super.connectedCallback();
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
public disconnectedCallback() {
|
|
76
|
-
|
|
77
83
|
window.removeEventListener('popstate', this.setActiveState);
|
|
84
|
+
window.removeEventListener('tetris:navigate', this.setActiveState);
|
|
85
|
+
|
|
78
86
|
super.disconnectedCallback();
|
|
79
87
|
}
|
|
80
88
|
|
|
@@ -164,7 +172,7 @@ export class TtNavbar extends LitElement {
|
|
|
164
172
|
|
|
165
173
|
private toggleSidebar = () => {
|
|
166
174
|
this.closeAllDetails();
|
|
167
|
-
this.
|
|
175
|
+
this.navbarController.toggle();
|
|
168
176
|
};
|
|
169
177
|
|
|
170
178
|
private handleToggle = (e: ToggleEvent) => {
|
|
@@ -172,8 +180,8 @@ export class TtNavbar extends LitElement {
|
|
|
172
180
|
const target = e.currentTarget as HTMLDetailsElement;
|
|
173
181
|
|
|
174
182
|
if (newState === 'open') {
|
|
175
|
-
if (!this.
|
|
176
|
-
this.
|
|
183
|
+
if (!this.navbarController.isOpen) {
|
|
184
|
+
this.navbarController.toggle();
|
|
177
185
|
}
|
|
178
186
|
|
|
179
187
|
this.closeAllDetails(target);
|
|
@@ -207,8 +215,8 @@ export class TtNavbar extends LitElement {
|
|
|
207
215
|
|
|
208
216
|
render() {
|
|
209
217
|
return html`
|
|
210
|
-
<nav id=${this.id} class="${this.
|
|
211
|
-
<div class="sidebar-header ${this.
|
|
218
|
+
<nav id=${this.id} class="${this.navbarController.isOpen ? '' : 'sidebar-closed'}">
|
|
219
|
+
<div class="sidebar-header ${this.navbarController.isOpen ? '' : 'sidebar-closed'}">
|
|
212
220
|
<div class="logo">
|
|
213
221
|
${unsafeSVG(tripteaseLogo)}
|
|
214
222
|
</div>
|
|
@@ -221,7 +229,7 @@ export class TtNavbar extends LitElement {
|
|
|
221
229
|
</button>
|
|
222
230
|
</div>
|
|
223
231
|
|
|
224
|
-
<div class="nav-items ${this.
|
|
232
|
+
<div class="nav-items ${this.navbarController.isOpen ? '' : 'sidebar-closed'}">
|
|
225
233
|
<a
|
|
226
234
|
class="nav-item"
|
|
227
235
|
href=${this.buildUrl('/')}
|
|
@@ -335,7 +343,7 @@ export class TtNavbar extends LitElement {
|
|
|
335
343
|
</div>
|
|
336
344
|
</details>
|
|
337
345
|
</div>
|
|
338
|
-
<div class="tertiary-nav ${this.
|
|
346
|
+
<div class="tertiary-nav ${this.navbarController.isOpen ? '' : 'sidebar-closed'}">
|
|
339
347
|
<div id="external-links" class="nav-items">
|
|
340
348
|
<a
|
|
341
349
|
class="nav-item external-link"
|
|
@@ -368,23 +376,30 @@ export class TtNavbar extends LitElement {
|
|
|
368
376
|
</div>
|
|
369
377
|
<div class='nav-items'>
|
|
370
378
|
<div id="client-selector">
|
|
371
|
-
${
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
379
|
+
${
|
|
380
|
+
this.clients.length > 1
|
|
381
|
+
? html`
|
|
382
|
+
<tt-combobox
|
|
383
|
+
.openUpward=${true}
|
|
384
|
+
.value=${this.clientKey ? [this.clientKey] : []}
|
|
385
|
+
@change=${this.handleClientChange}
|
|
386
|
+
>
|
|
387
|
+
${this.clients.map(
|
|
388
|
+
client => html`
|
|
389
|
+
<option slot="option" value=${client.clientKey}>
|
|
390
|
+
${client.displayName}
|
|
391
|
+
</option>
|
|
392
|
+
`,
|
|
393
|
+
)}
|
|
394
|
+
</tt-combobox>
|
|
395
|
+
`
|
|
396
|
+
: html`
|
|
397
|
+
<div class="single-client-name">
|
|
398
|
+
${this.clients.find(m => m.clientKey === this.clientKey)
|
|
399
|
+
?.displayName}
|
|
400
|
+
</div>
|
|
401
|
+
`
|
|
402
|
+
}
|
|
388
403
|
</div>
|
|
389
404
|
<a
|
|
390
405
|
id="logout-link"
|
package/src/global.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Clerk } from '@clerk/clerk-js';
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
Clerk?: typeof Clerk;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface UserUnsafeMetadata {
|
|
9
|
+
preferences: {
|
|
10
|
+
ui?: {
|
|
11
|
+
navigationVersion?: 2;
|
|
12
|
+
navigationOpen?: boolean;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
package/test/tt-navbar.test.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { Clerk } from '@clerk/clerk-js';
|
|
1
2
|
import '../src/tt-navbar.js';
|
|
2
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
elementUpdated,
|
|
5
|
+
expect,
|
|
6
|
+
fixture,
|
|
7
|
+
nextFrame,
|
|
8
|
+
waitUntil,
|
|
9
|
+
} from '@open-wc/testing';
|
|
3
10
|
import { TtNavbar } from '../src/index.js';
|
|
4
11
|
import { Routes } from '../src/Routes.js';
|
|
5
12
|
|
|
@@ -15,12 +22,16 @@ const getLinkByHref = (links: NodeListOf<HTMLAnchorElement>, href: string) => {
|
|
|
15
22
|
};
|
|
16
23
|
|
|
17
24
|
const selectComboboxOption = async (combobox: Element, value: string) => {
|
|
18
|
-
const input = combobox.shadowRoot!.querySelector(
|
|
25
|
+
const input = combobox.shadowRoot!.querySelector(
|
|
26
|
+
'[role="combobox"]',
|
|
27
|
+
) as HTMLInputElement;
|
|
19
28
|
input.click();
|
|
20
29
|
|
|
21
30
|
await elementUpdated(combobox);
|
|
22
31
|
|
|
23
|
-
const option = combobox.shadowRoot!.querySelector(
|
|
32
|
+
const option = combobox.shadowRoot!.querySelector(
|
|
33
|
+
`[role="option"][data-value="${value}"]`,
|
|
34
|
+
) as HTMLLIElement;
|
|
24
35
|
option.click();
|
|
25
36
|
};
|
|
26
37
|
|
|
@@ -29,15 +40,15 @@ const isVisuallyHidden = (element: Element) => {
|
|
|
29
40
|
|
|
30
41
|
return Boolean(
|
|
31
42
|
style.position === 'absolute' &&
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
style.width === '1px' &&
|
|
44
|
+
style.height === '1px' &&
|
|
45
|
+
style.margin === '-1px' &&
|
|
46
|
+
style.padding === '0px' &&
|
|
47
|
+
style.borderWidth === '0px' &&
|
|
48
|
+
style.overflow === 'hidden' &&
|
|
49
|
+
style.clip === 'rect(0px, 0px, 0px, 0px)' &&
|
|
50
|
+
style.clipPath === 'inset(50%)' &&
|
|
51
|
+
style.whiteSpace === 'nowrap',
|
|
41
52
|
);
|
|
42
53
|
};
|
|
43
54
|
|
|
@@ -53,7 +64,7 @@ describe('TtNavbar', () => {
|
|
|
53
64
|
});
|
|
54
65
|
it('should render with the default links', async () => {
|
|
55
66
|
const navbar = await fixture<TtNavbar>(
|
|
56
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
67
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
57
68
|
);
|
|
58
69
|
const links = navbar.shadowRoot?.querySelectorAll('a');
|
|
59
70
|
|
|
@@ -80,7 +91,7 @@ describe('TtNavbar', () => {
|
|
|
80
91
|
it('should render platform URLs against the base URL when it is defined', async () => {
|
|
81
92
|
const platformUrl = 'https://app.triptease.io';
|
|
82
93
|
const navbar = await fixture<TtNavbar>(
|
|
83
|
-
`<tt-navbar client-key=${CLIENT_KEY} platform-url="${platformUrl}"></tt-navbar
|
|
94
|
+
`<tt-navbar client-key=${CLIENT_KEY} platform-url="${platformUrl}"></tt-navbar>`,
|
|
84
95
|
);
|
|
85
96
|
const links = navbar.shadowRoot?.querySelectorAll('a');
|
|
86
97
|
|
|
@@ -88,7 +99,8 @@ describe('TtNavbar', () => {
|
|
|
88
99
|
expect(getLinkByHref(links, `${platformUrl}/`)).to.exist;
|
|
89
100
|
expect(getLinkByHref(links, 'https://app.campaign-manager.triptease.io'))
|
|
90
101
|
.to.exist; // This shouldn't change
|
|
91
|
-
expect(getLinkByHref(links, `${platformUrl}/${CLIENT_KEY}/channels`)).to
|
|
102
|
+
expect(getLinkByHref(links, `${platformUrl}/${CLIENT_KEY}/channels`)).to
|
|
103
|
+
.exist;
|
|
92
104
|
}
|
|
93
105
|
});
|
|
94
106
|
|
|
@@ -101,7 +113,7 @@ describe('TtNavbar', () => {
|
|
|
101
113
|
};
|
|
102
114
|
|
|
103
115
|
const navbar = await fixture<TtNavbar>(
|
|
104
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
116
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
105
117
|
);
|
|
106
118
|
navbar.navigate = onNavigate;
|
|
107
119
|
await navbar.updateComplete;
|
|
@@ -111,22 +123,24 @@ describe('TtNavbar', () => {
|
|
|
111
123
|
|
|
112
124
|
await waitUntil(
|
|
113
125
|
() => expect(navigateEventCount).to.equal(13),
|
|
114
|
-
'navigate event did not fire'
|
|
126
|
+
'navigate event did not fire',
|
|
115
127
|
);
|
|
116
128
|
});
|
|
117
129
|
|
|
118
130
|
it('should render a combobox when multiple clients are provided', async () => {
|
|
119
131
|
const navbar = await fixture<TtNavbar>(
|
|
120
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
132
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
121
133
|
);
|
|
122
134
|
navbar.clients = [
|
|
123
135
|
{ clientKey: CLIENT_KEY, displayName: 'Client One' },
|
|
124
|
-
{ clientKey: 'abc123', displayName: 'Client Two' }
|
|
136
|
+
{ clientKey: 'abc123', displayName: 'Client Two' },
|
|
125
137
|
];
|
|
126
138
|
await navbar.updateComplete;
|
|
127
139
|
|
|
128
140
|
const combobox = navbar.shadowRoot?.querySelector('tt-combobox');
|
|
129
|
-
const singleClientName = navbar.shadowRoot?.querySelector(
|
|
141
|
+
const singleClientName = navbar.shadowRoot?.querySelector(
|
|
142
|
+
'.single-client-name',
|
|
143
|
+
);
|
|
130
144
|
|
|
131
145
|
expect(combobox).to.exist;
|
|
132
146
|
expect(singleClientName).to.not.exist;
|
|
@@ -135,14 +149,14 @@ describe('TtNavbar', () => {
|
|
|
135
149
|
|
|
136
150
|
it('should render the client name when only one client is provided', async () => {
|
|
137
151
|
const navbar = await fixture<TtNavbar>(
|
|
138
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
152
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
139
153
|
);
|
|
140
|
-
navbar.clients = [
|
|
141
|
-
{ clientKey: CLIENT_KEY, displayName: 'Single Client' }
|
|
142
|
-
];
|
|
154
|
+
navbar.clients = [{ clientKey: CLIENT_KEY, displayName: 'Single Client' }];
|
|
143
155
|
await navbar.updateComplete;
|
|
144
156
|
|
|
145
|
-
const singleClientName = navbar.shadowRoot?.querySelector(
|
|
157
|
+
const singleClientName = navbar.shadowRoot?.querySelector(
|
|
158
|
+
'.single-client-name',
|
|
159
|
+
);
|
|
146
160
|
const combobox = navbar.shadowRoot?.querySelector('tt-combobox');
|
|
147
161
|
|
|
148
162
|
expect(singleClientName).to.exist;
|
|
@@ -152,7 +166,7 @@ describe('TtNavbar', () => {
|
|
|
152
166
|
|
|
153
167
|
it('should render the logout link', async () => {
|
|
154
168
|
const navbar = await fixture<TtNavbar>(
|
|
155
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
169
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
156
170
|
);
|
|
157
171
|
|
|
158
172
|
const links = navbar.shadowRoot?.querySelectorAll('a');
|
|
@@ -163,7 +177,7 @@ describe('TtNavbar', () => {
|
|
|
163
177
|
|
|
164
178
|
it('should close other details when one is being opened', async () => {
|
|
165
179
|
const navbar = await fixture<TtNavbar>(
|
|
166
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
180
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
167
181
|
);
|
|
168
182
|
|
|
169
183
|
const allDetails = navbar.shadowRoot!.querySelectorAll('summary');
|
|
@@ -189,11 +203,11 @@ describe('TtNavbar', () => {
|
|
|
189
203
|
|
|
190
204
|
it('should collapse the navbar when toggle clicked', async () => {
|
|
191
205
|
const navbar = await fixture<TtNavbar>(
|
|
192
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
206
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
193
207
|
);
|
|
194
208
|
|
|
195
209
|
const navbarToggleBtn = navbar.shadowRoot!.querySelector(
|
|
196
|
-
'#navbar-toggle-btn'
|
|
210
|
+
'#navbar-toggle-btn',
|
|
197
211
|
) as HTMLButtonElement;
|
|
198
212
|
|
|
199
213
|
navbarToggleBtn.click();
|
|
@@ -223,7 +237,7 @@ describe('TtNavbar', () => {
|
|
|
223
237
|
for (const element of [
|
|
224
238
|
...rootLinksHiddenElements,
|
|
225
239
|
...summaryHiddenElements,
|
|
226
|
-
logoutLink
|
|
240
|
+
logoutLink!,
|
|
227
241
|
]) {
|
|
228
242
|
expect(isVisuallyHidden(element)).to.be.true;
|
|
229
243
|
}
|
|
@@ -233,16 +247,16 @@ describe('TtNavbar', () => {
|
|
|
233
247
|
'market-insights',
|
|
234
248
|
'settings',
|
|
235
249
|
'account',
|
|
236
|
-
'billing-routes'
|
|
250
|
+
'billing-routes',
|
|
237
251
|
];
|
|
238
252
|
collapsibleIds.forEach(id => {
|
|
239
253
|
it(`should open the nav bar when the ${id} collapsible is clicked`, async () => {
|
|
240
254
|
const navbar = await fixture<TtNavbar>(
|
|
241
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
255
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
242
256
|
);
|
|
243
257
|
|
|
244
258
|
const navbarToggleBtn = navbar.shadowRoot!.querySelector(
|
|
245
|
-
'#navbar-toggle-btn'
|
|
259
|
+
'#navbar-toggle-btn',
|
|
246
260
|
) as HTMLButtonElement;
|
|
247
261
|
|
|
248
262
|
navbarToggleBtn.click();
|
|
@@ -259,7 +273,7 @@ describe('TtNavbar', () => {
|
|
|
259
273
|
element!.click();
|
|
260
274
|
|
|
261
275
|
await waitUntil(() => logo?.checkVisibility(), 'navbar should be open', {
|
|
262
|
-
timeout: 500
|
|
276
|
+
timeout: 500,
|
|
263
277
|
});
|
|
264
278
|
});
|
|
265
279
|
});
|
|
@@ -272,7 +286,7 @@ describe('TtNavbar', () => {
|
|
|
272
286
|
[`/parity/${CLIENT_KEY}/foo`, 'Parity'],
|
|
273
287
|
[`/meta/${CLIENT_KEY}/performance`, 'Channels'],
|
|
274
288
|
[`/chat/insights/${CLIENT_KEY}`, 'Channels'],
|
|
275
|
-
[`/${CLIENT_KEY}/email`, 'Channels']
|
|
289
|
+
[`/${CLIENT_KEY}/email`, 'Channels'],
|
|
276
290
|
];
|
|
277
291
|
|
|
278
292
|
URLs.forEach(([route, text]) => {
|
|
@@ -281,7 +295,7 @@ describe('TtNavbar', () => {
|
|
|
281
295
|
history.pushState({}, '', route); // 👈 mock URL
|
|
282
296
|
|
|
283
297
|
const navbar = await fixture<TtNavbar>(
|
|
284
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
298
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
285
299
|
);
|
|
286
300
|
|
|
287
301
|
const anchor = navbar.shadowRoot!.querySelector('a[aria-current="page"]');
|
|
@@ -296,7 +310,7 @@ describe('TtNavbar', () => {
|
|
|
296
310
|
const campaignManagerUrl = 'http://localhost:8000';
|
|
297
311
|
|
|
298
312
|
const navbar = await fixture<TtNavbar>(
|
|
299
|
-
`<tt-navbar client-key=${CLIENT_KEY} platform-url=${platformUrl} campaign-manager-url=${campaignManagerUrl} active-route="${Routes.CampaignManager}"></tt-navbar
|
|
313
|
+
`<tt-navbar client-key=${CLIENT_KEY} platform-url=${platformUrl} campaign-manager-url=${campaignManagerUrl} active-route="${Routes.CampaignManager}"></tt-navbar>`,
|
|
300
314
|
);
|
|
301
315
|
const anchor = navbar.shadowRoot!.querySelector('a[aria-current="page"]');
|
|
302
316
|
expect(anchor).to.exist;
|
|
@@ -310,11 +324,11 @@ describe('TtNavbar', () => {
|
|
|
310
324
|
};
|
|
311
325
|
|
|
312
326
|
const navbar = await fixture<TtNavbar>(
|
|
313
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
327
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
314
328
|
);
|
|
315
329
|
navbar.clients = [
|
|
316
330
|
{ clientKey: CLIENT_KEY, displayName: 'Client One' },
|
|
317
|
-
{ clientKey: 'abc123', displayName: 'Client Two' }
|
|
331
|
+
{ clientKey: 'abc123', displayName: 'Client Two' },
|
|
318
332
|
];
|
|
319
333
|
navbar.onClientChange = onClientChange;
|
|
320
334
|
|
|
@@ -330,20 +344,23 @@ describe('TtNavbar', () => {
|
|
|
330
344
|
|
|
331
345
|
it('should set the --nav-bar-width css variable when collapsed', async () => {
|
|
332
346
|
const navbar = await fixture<TtNavbar>(
|
|
333
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
347
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
334
348
|
);
|
|
335
349
|
|
|
336
|
-
await expect(
|
|
350
|
+
await expect(
|
|
351
|
+
getComputedStyle(navbar).getPropertyValue('--nav-bar-width').trim(),
|
|
352
|
+
).to.equal('260px');
|
|
337
353
|
|
|
338
354
|
const navbarToggleBtn = navbar.shadowRoot!.querySelector(
|
|
339
|
-
'#navbar-toggle-btn'
|
|
355
|
+
'#navbar-toggle-btn',
|
|
340
356
|
) as HTMLButtonElement;
|
|
341
357
|
|
|
342
358
|
navbarToggleBtn.click();
|
|
343
359
|
await elementUpdated(navbar);
|
|
344
360
|
|
|
345
|
-
await expect(
|
|
346
|
-
|
|
361
|
+
await expect(
|
|
362
|
+
getComputedStyle(navbar).getPropertyValue('--nav-bar-width').trim(),
|
|
363
|
+
).to.equal('fit-content');
|
|
347
364
|
});
|
|
348
365
|
|
|
349
366
|
it('should expand the details when the current page is within that section', async () => {
|
|
@@ -351,12 +368,92 @@ describe('TtNavbar', () => {
|
|
|
351
368
|
history.pushState({}, '', `/parity/${CLIENT_KEY}`);
|
|
352
369
|
|
|
353
370
|
const navbar = await fixture<TtNavbar>(
|
|
354
|
-
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar
|
|
371
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
355
372
|
);
|
|
356
373
|
|
|
357
|
-
const marketInsightsDetails = navbar.shadowRoot!.querySelector(
|
|
374
|
+
const marketInsightsDetails = navbar.shadowRoot!.querySelector(
|
|
375
|
+
'#market-insights',
|
|
376
|
+
) as HTMLDetailsElement;
|
|
358
377
|
|
|
359
378
|
expect(marketInsightsDetails).to.exist;
|
|
360
379
|
expect(marketInsightsDetails.open).to.be.true;
|
|
361
|
-
})
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
it('should set the active route when receives `tetris:navigate` event', async () => {
|
|
383
|
+
const navbar = await fixture<TtNavbar>(
|
|
384
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
385
|
+
);
|
|
386
|
+
// eslint-disable-next-line no-restricted-globals
|
|
387
|
+
history.pushState({}, '', `/account/billing-management/${CLIENT_KEY}`);
|
|
388
|
+
|
|
389
|
+
// Dispatch the event to change to Channels route
|
|
390
|
+
const navigateEvent = new CustomEvent('tetris:navigate', {});
|
|
391
|
+
window.dispatchEvent(navigateEvent);
|
|
392
|
+
|
|
393
|
+
await elementUpdated(navbar);
|
|
394
|
+
const anchor = navbar.shadowRoot!.querySelector('a[aria-current="page"]');
|
|
395
|
+
|
|
396
|
+
expect(anchor).to.exist;
|
|
397
|
+
expect(anchor!.textContent).to.include('Booking reconciliation');
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('should default to open when Clerk is not available', async () => {
|
|
401
|
+
const navbar = await fixture<TtNavbar>(
|
|
402
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
const logo = navbar.shadowRoot!.querySelector('.logo');
|
|
406
|
+
|
|
407
|
+
expect(window.Clerk).to.be.undefined;
|
|
408
|
+
expect(logo).to.exist;
|
|
409
|
+
expect(logo!.checkVisibility()).to.be.true;
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
it('should default to state stored in Clerk when set', async () => {
|
|
413
|
+
window.Clerk = {
|
|
414
|
+
user: {
|
|
415
|
+
unsafeMetadata: { preferences: { ui: { navigationOpen: false } } },
|
|
416
|
+
},
|
|
417
|
+
} as Clerk;
|
|
418
|
+
|
|
419
|
+
const navbar = await fixture<TtNavbar>(
|
|
420
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
const logo = navbar.shadowRoot!.querySelector('.logo');
|
|
424
|
+
|
|
425
|
+
expect(logo).to.exist;
|
|
426
|
+
expect(logo!.checkVisibility()).to.be.false;
|
|
427
|
+
|
|
428
|
+
window.Clerk = undefined; // Cleanup
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('should update Clerk state when toggling if Clerk is available', async () => {
|
|
432
|
+
let timesCalled = 0;
|
|
433
|
+
|
|
434
|
+
const mockUpdate = () => {
|
|
435
|
+
timesCalled += 1;
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
window.Clerk = {
|
|
439
|
+
user: {
|
|
440
|
+
update: mockUpdate,
|
|
441
|
+
unsafeMetadata: { preferences: { ui: { navigationOpen: false } } },
|
|
442
|
+
},
|
|
443
|
+
} as unknown as Clerk;
|
|
444
|
+
|
|
445
|
+
const navbar = await fixture<TtNavbar>(
|
|
446
|
+
`<tt-navbar client-key=${CLIENT_KEY}></tt-navbar>`,
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
const navbarToggleBtn = navbar.shadowRoot!.querySelector(
|
|
450
|
+
'#navbar-toggle-btn',
|
|
451
|
+
) as HTMLButtonElement;
|
|
452
|
+
|
|
453
|
+
navbarToggleBtn.click();
|
|
454
|
+
|
|
455
|
+
await expect(timesCalled).to.equal(1);
|
|
456
|
+
|
|
457
|
+
window.Clerk = undefined; // Cleanup
|
|
458
|
+
});
|
|
362
459
|
});
|