@akinon/pz-theme 2.0.168-rc.0 → 2.0.168
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/CHANGELOG.md +7 -53
- package/package.json +4 -4
- package/src/__tests__/editor-locale-bridge.test.tsx +1 -32
- package/src/blocks/__tests__/account-menu-items.test.tsx +329 -0
- package/src/blocks/__tests__/text-block.test.tsx +6 -34
- package/src/blocks/account-menu-block.tsx +178 -56
- package/src/blocks/order-detail-block.tsx +95 -113
- package/src/blocks/text-block.tsx +2 -6
- package/src/custom/README.md +219 -100
- package/src/custom/__tests__/use-theme-setting.test.tsx +0 -97
- package/src/custom/collect.ts +9 -4
- package/src/custom/property-types.ts +15 -15
- package/src/custom/use-theme-setting.ts +5 -21
- package/src/editor-locale-bridge.tsx +11 -39
- package/src/theme-placeholder-wrapper.tsx +0 -3
- package/src/blocks/__tests__/order-line-actions.test.tsx +0 -54
- package/src/blocks/order-line-actions.ts +0 -45
- package/src/utils/__tests__/sanitize-rich-text.test.ts +0 -80
- package/src/utils/sanitize-rich-text.ts +0 -215
package/CHANGELOG.md
CHANGED
|
@@ -1,58 +1,12 @@
|
|
|
1
1
|
# @akinon/pz-theme
|
|
2
2
|
|
|
3
|
-
## 2.0.168
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
- 17a598dae: ZERO-5296: report the storefront default language to the editor
|
|
11
|
-
- 3b05a407d: ZERO-5232: allow richtext settings on custom blocks
|
|
12
|
-
- Updated dependencies [86187b1c2]
|
|
13
|
-
- Updated dependencies [08390a87]
|
|
14
|
-
- Updated dependencies [0cf9ea239]
|
|
15
|
-
- Updated dependencies [324f97d55]
|
|
16
|
-
- Updated dependencies [4c3465ae]
|
|
17
|
-
- Updated dependencies [51ea06888]
|
|
18
|
-
- Updated dependencies
|
|
19
|
-
- Updated dependencies [549da545]
|
|
20
|
-
- Updated dependencies [2fea41430]
|
|
21
|
-
- Updated dependencies [b55acb768]
|
|
22
|
-
- Updated dependencies [760258c1c]
|
|
23
|
-
- Updated dependencies [143be2b9d]
|
|
24
|
-
- Updated dependencies [7889b08fe]
|
|
25
|
-
- Updated dependencies [9f8cd3bc5]
|
|
26
|
-
- Updated dependencies [d635d345]
|
|
27
|
-
- Updated dependencies [bfafa3f49]
|
|
28
|
-
- Updated dependencies [d860c917]
|
|
29
|
-
- Updated dependencies [ac6cada1c]
|
|
30
|
-
- Updated dependencies [e90c0e02]
|
|
31
|
-
- Updated dependencies [dc7f9ca5]
|
|
32
|
-
- Updated dependencies [57d7eb305]
|
|
33
|
-
- Updated dependencies [0145dc3f]
|
|
34
|
-
- Updated dependencies [d99a6a7d5]
|
|
35
|
-
- Updated dependencies [92086b29]
|
|
36
|
-
- Updated dependencies [227b74086]
|
|
37
|
-
- Updated dependencies [9db81a714]
|
|
38
|
-
- Updated dependencies [e3c2bab2]
|
|
39
|
-
- Updated dependencies [591e345e1]
|
|
40
|
-
- Updated dependencies [4de5303c5]
|
|
41
|
-
- Updated dependencies [95b139dc1]
|
|
42
|
-
- Updated dependencies [1d00f2d06]
|
|
43
|
-
- Updated dependencies [4ac7b2a1e]
|
|
44
|
-
- Updated dependencies [4998a9631]
|
|
45
|
-
- Updated dependencies [804d2bd6c]
|
|
46
|
-
- Updated dependencies [3909d3224]
|
|
47
|
-
- Updated dependencies [6a3d8a631]
|
|
48
|
-
- Updated dependencies [e18836b20]
|
|
49
|
-
- Updated dependencies [b1111d7b1]
|
|
50
|
-
- Updated dependencies [1595d458e]
|
|
51
|
-
- Updated dependencies [dca128112]
|
|
52
|
-
- Updated dependencies [9a7b0937]
|
|
53
|
-
- Updated dependencies [8853822c]
|
|
54
|
-
- @akinon/next@2.0.168-rc.0
|
|
55
|
-
- @akinon/theme-contract@2.0.168-rc.0
|
|
3
|
+
## 2.0.168
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c5aaa9b3: ZERO-5475: Let the account menu block render a designer-edited item list with a selected rule per item, and scroll sideways when horizontal
|
|
8
|
+
- @akinon/next@2.0.168
|
|
9
|
+
- @akinon/theme-contract@2.0.168
|
|
56
10
|
|
|
57
11
|
## 2.0.167
|
|
58
12
|
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/pz-theme",
|
|
3
3
|
"description": "Theme package for Project Zero Next — ThemePlaceholder system and theme editor infrastructure",
|
|
4
|
-
"version": "2.0.168
|
|
4
|
+
"version": "2.0.168",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "jest"
|
|
9
9
|
},
|
|
10
10
|
"peerDependencies": {
|
|
11
|
-
"@akinon/next": "2.0.168
|
|
11
|
+
"@akinon/next": "2.0.168",
|
|
12
12
|
"react": "^18.0.0 || ^19.0.0",
|
|
13
13
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@akinon/theme-contract": "2.0.168
|
|
16
|
+
"@akinon/theme-contract": "2.0.168",
|
|
17
17
|
"clsx": "2.1.1",
|
|
18
18
|
"lottie-web": "^5.13.0",
|
|
19
19
|
"react-multi-carousel": "2.8.4",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"zod": "4.4.1"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@akinon/next": "2.0.168
|
|
24
|
+
"@akinon/next": "2.0.168",
|
|
25
25
|
"@testing-library/jest-dom": "5.16.4",
|
|
26
26
|
"@testing-library/react": "16.3.2",
|
|
27
27
|
"@testing-library/user-event": "14.1.1",
|
|
@@ -28,7 +28,6 @@ const SETTINGS_LOCALES = [
|
|
|
28
28
|
const mockLocalization = {
|
|
29
29
|
locale: 'tr',
|
|
30
30
|
locales: SETTINGS_LOCALES as Array<Record<string, unknown>>,
|
|
31
|
-
defaultLocaleValue: 'tr',
|
|
32
31
|
setLocale: jest.fn()
|
|
33
32
|
};
|
|
34
33
|
|
|
@@ -107,7 +106,6 @@ beforeEach(() => {
|
|
|
107
106
|
postMessage.mockClear();
|
|
108
107
|
mockLocalization.locale = 'tr';
|
|
109
108
|
mockLocalization.locales = SETTINGS_LOCALES;
|
|
110
|
-
mockLocalization.defaultLocaleValue = 'tr';
|
|
111
109
|
mockLocalization.setLocale = jest.fn();
|
|
112
110
|
delete (window as { __iframeReadySent?: boolean }).__iframeReadySent;
|
|
113
111
|
});
|
|
@@ -146,8 +144,7 @@ describe('inside the editor', () => {
|
|
|
146
144
|
{ value: 'en', label: 'English' },
|
|
147
145
|
{ value: 'tr', label: 'Türkçe' },
|
|
148
146
|
{ value: 'de', label: 'de' }
|
|
149
|
-
]
|
|
150
|
-
defaultLocale: 'tr'
|
|
147
|
+
]
|
|
151
148
|
}
|
|
152
149
|
})
|
|
153
150
|
]);
|
|
@@ -157,34 +154,6 @@ describe('inside the editor', () => {
|
|
|
157
154
|
expect(targetOrigin).toBe(EDITOR_ORIGIN);
|
|
158
155
|
});
|
|
159
156
|
|
|
160
|
-
it('posts the languages before the document reports ready', () => {
|
|
161
|
-
// The editor holds every per-language write until IFRAME_READY and takes
|
|
162
|
-
// "ready without languages" to mean they are never coming, so the order
|
|
163
|
-
// of the two frames is part of the contract.
|
|
164
|
-
render(placeholder('header'));
|
|
165
|
-
|
|
166
|
-
const types = postMessage.mock.calls.map(([message]) => message?.type);
|
|
167
|
-
expect(types).toContain('LOCALE_UPDATE');
|
|
168
|
-
expect(types).toContain('IFRAME_READY');
|
|
169
|
-
expect(types.indexOf('LOCALE_UPDATE')).toBeLessThan(
|
|
170
|
-
types.indexOf('IFRAME_READY')
|
|
171
|
-
);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it("posts the brand's default language, whichever it is", () => {
|
|
175
|
-
// The editor's per-language text controls take the plain-string form to
|
|
176
|
-
// mean this language; left to guess, the editor assumed English.
|
|
177
|
-
mockLocalization.defaultLocaleValue = 'de';
|
|
178
|
-
|
|
179
|
-
render(<EditorLocaleBridge />);
|
|
180
|
-
|
|
181
|
-
expect(localeFrames()).toEqual([
|
|
182
|
-
expect.objectContaining({
|
|
183
|
-
data: expect.objectContaining({ locale: 'tr', defaultLocale: 'de' })
|
|
184
|
-
})
|
|
185
|
-
]);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
157
|
it("follows the editor's switch exactly once, with several placeholders mounted", () => {
|
|
189
158
|
render(
|
|
190
159
|
<>
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZERO-5475: the account menu's items are a list the designer edits — added
|
|
3
|
+
* with +, removed with −, reordered — instead of five fixed keys.
|
|
4
|
+
*
|
|
5
|
+
* Every composition saved before the list existed has no `menuItems` and must
|
|
6
|
+
* render exactly as it did. Each entry can carry its own selected rule and
|
|
7
|
+
* further pages that keep it selected, and a horizontal menu can scroll
|
|
8
|
+
* sideways instead of wrapping.
|
|
9
|
+
*/
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import { render } from '@testing-library/react';
|
|
12
|
+
|
|
13
|
+
let mockPathname = '/account';
|
|
14
|
+
|
|
15
|
+
jest.mock('next/navigation', () => ({
|
|
16
|
+
useRouter: () => ({ push: jest.fn(), replace: jest.fn() }),
|
|
17
|
+
usePathname: () => mockPathname,
|
|
18
|
+
useSearchParams: () => new URLSearchParams('')
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
// Turkish is the hidden default, English lives under /en.
|
|
22
|
+
const TURKISH = {
|
|
23
|
+
locale: 'tr',
|
|
24
|
+
defaultLocaleValue: 'tr',
|
|
25
|
+
localeUrlStrategy: 'hide-default-locale'
|
|
26
|
+
};
|
|
27
|
+
let mockLocalization: Record<string, unknown> = { ...TURKISH };
|
|
28
|
+
|
|
29
|
+
jest.mock('@akinon/next/hooks', () => ({
|
|
30
|
+
__esModule: true,
|
|
31
|
+
useLocalization: () => ({ t: (path: string) => path, ...mockLocalization })
|
|
32
|
+
}));
|
|
33
|
+
|
|
34
|
+
jest.mock('@akinon/next/utils', () => ({
|
|
35
|
+
__esModule: true,
|
|
36
|
+
...jest.requireActual('@akinon/next/utils'),
|
|
37
|
+
urlLocaleMatcherRegex: /^\/(en)(?=\/|$)/
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
// jest maps every `@akinon/next/data/client/*` to one module, so this mock
|
|
41
|
+
// stands in for `user` as well: the account menu needs its logout mutation.
|
|
42
|
+
jest.mock('@akinon/next/data/client/misc', () => ({
|
|
43
|
+
useLogoutMutation: () => [jest.fn(), { isLoading: false }]
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
import AccountMenuBlock from '../account-menu-block';
|
|
47
|
+
|
|
48
|
+
const mkBlock = (properties: Record<string, unknown> = {}) =>
|
|
49
|
+
({
|
|
50
|
+
id: 'account-menu-1',
|
|
51
|
+
type: 'account-menu',
|
|
52
|
+
label: 'account-menu',
|
|
53
|
+
order: 0,
|
|
54
|
+
hidden: false,
|
|
55
|
+
value: '',
|
|
56
|
+
properties,
|
|
57
|
+
styles: {},
|
|
58
|
+
blocks: []
|
|
59
|
+
} as never);
|
|
60
|
+
|
|
61
|
+
const blockProps = {
|
|
62
|
+
placeholderId: 'account-menu',
|
|
63
|
+
sectionId: 'account-menu-main',
|
|
64
|
+
currentBreakpoint: 'desktop',
|
|
65
|
+
isDesigner: false
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const renderMenu = (
|
|
69
|
+
properties: Record<string, unknown>,
|
|
70
|
+
overrides: Partial<typeof blockProps> = {}
|
|
71
|
+
) =>
|
|
72
|
+
render(
|
|
73
|
+
<AccountMenuBlock
|
|
74
|
+
block={mkBlock(properties)}
|
|
75
|
+
{...blockProps}
|
|
76
|
+
{...overrides}
|
|
77
|
+
/>
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const links = (root: ParentNode) =>
|
|
81
|
+
Array.from(root.querySelectorAll('a')).map((a) => ({
|
|
82
|
+
label: a.textContent,
|
|
83
|
+
href: a.getAttribute('href'),
|
|
84
|
+
key: a.getAttribute('data-account-menu-item')
|
|
85
|
+
}));
|
|
86
|
+
|
|
87
|
+
const selectedLabels = (root: ParentNode) =>
|
|
88
|
+
Array.from(root.querySelectorAll('a[aria-current="page"]')).map(
|
|
89
|
+
(a) => a.textContent
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
// Gant's tab strip, the menu this list was built for.
|
|
93
|
+
const GANT_TABS = [
|
|
94
|
+
{ id: 'dashboard', label: 'Hesabım', href: '/account', match: 'exact' },
|
|
95
|
+
{
|
|
96
|
+
id: 'orders',
|
|
97
|
+
label: 'Siparişlerim',
|
|
98
|
+
href: '/users/orders',
|
|
99
|
+
match: 'startsWith',
|
|
100
|
+
activePaths: '/account/orders'
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
id: 'favourites',
|
|
104
|
+
label: 'Favorilerim',
|
|
105
|
+
href: '/account/favourite-products/',
|
|
106
|
+
match: 'startsWith'
|
|
107
|
+
},
|
|
108
|
+
{ id: 'loyalty', label: 'MyGANT', href: '/account/loyalty' },
|
|
109
|
+
{
|
|
110
|
+
id: 'personal',
|
|
111
|
+
label: 'Kişisel Bilgiler',
|
|
112
|
+
href: '/account/profile',
|
|
113
|
+
activePaths:
|
|
114
|
+
'/account/address, /account/change-email,\n/account/change-password'
|
|
115
|
+
},
|
|
116
|
+
{ id: 'coupons', label: 'Kuponlarım', href: '/account/coupons' }
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
beforeEach(() => {
|
|
120
|
+
mockLocalization = { ...TURKISH };
|
|
121
|
+
mockPathname = '/account';
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('account menu without an item list', () => {
|
|
125
|
+
it('renders the five fixed entries a published composition has always had', () => {
|
|
126
|
+
const { container } = renderMenu({});
|
|
127
|
+
|
|
128
|
+
expect(links(container)).toEqual([
|
|
129
|
+
{ label: 'Orders', href: '/account/orders', key: 'orders' },
|
|
130
|
+
{ label: 'Addresses', href: '/account/address', key: 'addresses' },
|
|
131
|
+
{ label: 'Profile', href: '/account/profile', key: 'profile' },
|
|
132
|
+
{
|
|
133
|
+
label: 'Favourites',
|
|
134
|
+
href: '/account/favourite-products',
|
|
135
|
+
key: 'favourites'
|
|
136
|
+
},
|
|
137
|
+
{ label: 'Coupons', href: '/account/coupons', key: 'coupons' }
|
|
138
|
+
]);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('still follows itemOrder and the per-key labels and links', () => {
|
|
142
|
+
const { container } = renderMenu({
|
|
143
|
+
itemOrder: 'coupons, orders',
|
|
144
|
+
ordersLabel: 'Siparişlerim',
|
|
145
|
+
ordersHref: '/users/orders'
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
expect(links(container)).toEqual([
|
|
149
|
+
{ label: 'Coupons', href: '/account/coupons', key: 'coupons' },
|
|
150
|
+
{ label: 'Siparişlerim', href: '/users/orders', key: 'orders' }
|
|
151
|
+
]);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// A drop in the editor seeds `{desktop: undefined}` for a property without
|
|
155
|
+
// a default; the panel shows the five fixed entries for it, so must the page.
|
|
156
|
+
it.each([
|
|
157
|
+
['the bucket a drop seeds', { desktop: undefined }],
|
|
158
|
+
['that bucket once saved', {}],
|
|
159
|
+
['a blank value', '']
|
|
160
|
+
])('keeps the fixed entries for %s', (_case, menuItems) => {
|
|
161
|
+
const { container } = renderMenu({ menuItems });
|
|
162
|
+
|
|
163
|
+
expect(links(container).map((link) => link.key)).toEqual([
|
|
164
|
+
'orders',
|
|
165
|
+
'addresses',
|
|
166
|
+
'profile',
|
|
167
|
+
'favourites',
|
|
168
|
+
'coupons'
|
|
169
|
+
]);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('account menu with an item list', () => {
|
|
174
|
+
it('renders the listed entries in their order, ignoring the fixed keys', () => {
|
|
175
|
+
const { container } = renderMenu({
|
|
176
|
+
itemOrder: 'orders,addresses',
|
|
177
|
+
menuItems: GANT_TABS
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
expect(
|
|
181
|
+
links(container).map(({ label, href, key }) => [label, href, key])
|
|
182
|
+
).toEqual([
|
|
183
|
+
['Hesabım', '/account', 'dashboard'],
|
|
184
|
+
['Siparişlerim', '/users/orders', 'orders'],
|
|
185
|
+
['Favorilerim', '/account/favourite-products/', 'favourites'],
|
|
186
|
+
['MyGANT', '/account/loyalty', 'loyalty'],
|
|
187
|
+
['Kişisel Bilgiler', '/account/profile', 'personal'],
|
|
188
|
+
['Kuponlarım', '/account/coupons', 'coupons']
|
|
189
|
+
]);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('skips an entry that has no label or no link yet', () => {
|
|
193
|
+
const { container } = renderMenu({
|
|
194
|
+
menuItems: [
|
|
195
|
+
{ id: 'a', label: 'Hesabım', href: '/account' },
|
|
196
|
+
{ id: 'b', label: '', href: '/account/orders' },
|
|
197
|
+
{ id: 'c', label: 'Kuponlarım', href: ' ' },
|
|
198
|
+
null
|
|
199
|
+
]
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
expect(links(container).map((link) => link.label)).toEqual(['Hesabım']);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('shows no entry once every one was removed', () => {
|
|
206
|
+
const { container } = renderMenu({ menuItems: [], showLogout: true });
|
|
207
|
+
|
|
208
|
+
expect(links(container)).toEqual([]);
|
|
209
|
+
expect(
|
|
210
|
+
container.querySelector('[data-account-menu-item="logout"]')
|
|
211
|
+
).not.toBeNull();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('leaves the storefront empty when the list and logout are both off', () => {
|
|
215
|
+
const { container } = renderMenu({ menuItems: [], showLogout: false });
|
|
216
|
+
|
|
217
|
+
expect(container.innerHTML).toBe('');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('tells apart two entries that share an id', () => {
|
|
221
|
+
const { container } = renderMenu({
|
|
222
|
+
menuItems: [
|
|
223
|
+
{ id: 'tab', label: 'One', href: '/account/one' },
|
|
224
|
+
{ id: 'tab', label: 'Two', href: '/account/two' }
|
|
225
|
+
]
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
expect(links(container).map((link) => link.key)).toEqual(['tab', 'tab-2']);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('reads a list authored per breakpoint', () => {
|
|
232
|
+
const { container } = renderMenu(
|
|
233
|
+
{
|
|
234
|
+
menuItems: {
|
|
235
|
+
desktop: GANT_TABS,
|
|
236
|
+
mobile: GANT_TABS.slice(0, 2)
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
{ currentBreakpoint: 'mobile' }
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
expect(links(container).map((link) => link.label)).toEqual([
|
|
243
|
+
'Hesabım',
|
|
244
|
+
'Siparişlerim'
|
|
245
|
+
]);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe('selected entry', () => {
|
|
250
|
+
it.each([
|
|
251
|
+
['/account', ['Hesabım']],
|
|
252
|
+
['/users/orders', ['Siparişlerim']],
|
|
253
|
+
['/account/orders/1234', ['Siparişlerim']],
|
|
254
|
+
['/account/favourite-products', ['Favorilerim']],
|
|
255
|
+
['/account/profile', ['Kişisel Bilgiler']],
|
|
256
|
+
['/account/change-password', ['Kişisel Bilgiler']],
|
|
257
|
+
['/account/change-email', ['Kişisel Bilgiler']],
|
|
258
|
+
['/account/address', ['Kişisel Bilgiler']],
|
|
259
|
+
['/account/coupons', ['Kuponlarım']]
|
|
260
|
+
])('on %s it is %j', (pathname, expected) => {
|
|
261
|
+
mockPathname = pathname;
|
|
262
|
+
const { container } = renderMenu({ menuItems: GANT_TABS });
|
|
263
|
+
|
|
264
|
+
expect(selectedLabels(container)).toEqual(expected);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('lets an entry without its own rule inherit the block setting', () => {
|
|
268
|
+
mockPathname = '/account/loyalty/history';
|
|
269
|
+
|
|
270
|
+
const exact = renderMenu({ menuItems: GANT_TABS });
|
|
271
|
+
expect(selectedLabels(exact.container)).toEqual([]);
|
|
272
|
+
exact.unmount();
|
|
273
|
+
|
|
274
|
+
const section = renderMenu({
|
|
275
|
+
menuItems: GANT_TABS,
|
|
276
|
+
activeMatch: 'startsWith'
|
|
277
|
+
});
|
|
278
|
+
// Hesabım says "only this page" itself, so the section rule leaves it out.
|
|
279
|
+
expect(selectedLabels(section.container)).toEqual(['MyGANT']);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('matches the further pages in the localized form the links render', () => {
|
|
283
|
+
mockLocalization = { ...TURKISH, locale: 'en' };
|
|
284
|
+
mockPathname = '/en/account/address';
|
|
285
|
+
const { container } = renderMenu({ menuItems: GANT_TABS });
|
|
286
|
+
|
|
287
|
+
expect(selectedLabels(container)).toEqual(['Kişisel Bilgiler']);
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
describe('horizontal overflow', () => {
|
|
292
|
+
const nav = (root: ParentNode) =>
|
|
293
|
+
root.querySelector('[data-account-menu]') as HTMLElement;
|
|
294
|
+
|
|
295
|
+
it('wraps by default, as a horizontal menu always has', () => {
|
|
296
|
+
const { container } = renderMenu({ orientation: 'horizontal' });
|
|
297
|
+
|
|
298
|
+
expect(nav(container).style.flexWrap).toBe('wrap');
|
|
299
|
+
expect(
|
|
300
|
+
nav(container).getAttribute('data-account-menu-overflow')
|
|
301
|
+
).toBeNull();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('stays on one line and scrolls sideways when set to scroll', () => {
|
|
305
|
+
const { container } = renderMenu({
|
|
306
|
+
orientation: 'horizontal',
|
|
307
|
+
overflow: 'scroll',
|
|
308
|
+
menuItems: GANT_TABS
|
|
309
|
+
});
|
|
310
|
+
const menu = nav(container);
|
|
311
|
+
|
|
312
|
+
expect(menu.getAttribute('data-account-menu-overflow')).toBe('scroll');
|
|
313
|
+
expect(menu.style.flexWrap).toBe('nowrap');
|
|
314
|
+
expect(menu.style.overflowX).toBe('auto');
|
|
315
|
+
expect(menu.style.whiteSpace).toBe('nowrap');
|
|
316
|
+
expect((container.querySelector('a') as HTMLElement).style.flexShrink).toBe(
|
|
317
|
+
'0'
|
|
318
|
+
);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it('ignores the setting on a vertical menu', () => {
|
|
322
|
+
const { container } = renderMenu({ overflow: 'scroll' });
|
|
323
|
+
const menu = nav(container);
|
|
324
|
+
|
|
325
|
+
expect(menu.style.flexDirection).toBe('column');
|
|
326
|
+
expect(menu.style.overflowX).toBe('');
|
|
327
|
+
expect(menu.getAttribute('data-account-menu-overflow')).toBeNull();
|
|
328
|
+
});
|
|
329
|
+
});
|
|
@@ -2,31 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
3
|
import TextBlock from '../text-block';
|
|
4
4
|
|
|
5
|
-
// The
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
const mockLocalization = { locale: 'en-us', defaultLocaleValue: 'en-us' };
|
|
9
|
-
|
|
10
|
-
jest.mock('@akinon/next/hooks', () => ({
|
|
11
|
-
__esModule: true,
|
|
12
|
-
useLocalization: () => ({
|
|
13
|
-
t: (path: string) => path,
|
|
14
|
-
setLocale: () => {},
|
|
15
|
-
setCurrency: () => {},
|
|
16
|
-
locale: mockLocalization.locale,
|
|
17
|
-
currency: 'USD',
|
|
18
|
-
locales: [{ value: 'en-us' }, { value: 'tr-tr' }],
|
|
19
|
-
currencies: ['USD'],
|
|
20
|
-
defaultLocaleValue: mockLocalization.defaultLocaleValue,
|
|
21
|
-
defaultCurrencyCode: 'USD',
|
|
22
|
-
localeUrlStrategy: 'hide-default-locale'
|
|
23
|
-
})
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
mockLocalization.locale = 'en-us';
|
|
28
|
-
mockLocalization.defaultLocaleValue = 'en-us';
|
|
29
|
-
});
|
|
5
|
+
// The mocked useLocalization (jest/__mocks__/akinon-next-hooks.js) returns
|
|
6
|
+
// locale: 'en-us'. process.env.NEXT_PUBLIC_DEFAULT_LOCALE is unset in the
|
|
7
|
+
// jest env, so the component's defaultLocale falls back to 'en'.
|
|
30
8
|
|
|
31
9
|
const renderBlock = (value: unknown, styles?: Record<string, unknown>) => {
|
|
32
10
|
const block: any = { id: 'b1', type: 'text', value, styles };
|
|
@@ -56,16 +34,10 @@ describe('TextBlock value-shape resolution', () => {
|
|
|
56
34
|
);
|
|
57
35
|
});
|
|
58
36
|
|
|
59
|
-
it(
|
|
60
|
-
|
|
61
|
-
// the block used to show: its default was read from an env variable
|
|
62
|
-
// that falls back to English, not from the storefront (ZERO-5296).
|
|
63
|
-
mockLocalization.locale = 'de-de';
|
|
64
|
-
mockLocalization.defaultLocaleValue = 'tr-tr';
|
|
65
|
-
|
|
66
|
-
const { container } = renderBlock({ en: 'EN', 'tr-tr': 'TR' });
|
|
37
|
+
it('falls back to defaultLocale ("en") when active locale is absent', () => {
|
|
38
|
+
const { container } = renderBlock({ en: 'EN', fr: 'FR' });
|
|
67
39
|
expect((container.querySelector('div') as HTMLDivElement).innerHTML).toBe(
|
|
68
|
-
'
|
|
40
|
+
'EN'
|
|
69
41
|
);
|
|
70
42
|
});
|
|
71
43
|
|