@ui5/webcomponents-base 2.10.0 → 2.10.1
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 +12 -0
- package/cypress/specs/ConfigurationChange.cy.tsx +199 -0
- package/cypress/specs/ConfigurationScript.cy.tsx +395 -0
- package/cypress/specs/ConfigurationURL.cy.tsx +378 -56
- package/cypress/specs/ThemeRoot.cy.tsx +180 -0
- package/cypress/specs/ThemeRootAPI.cy.tsx +148 -0
- package/dist/.tsbuildinfobuild +1 -1
- package/dist/InitialConfiguration.js +1 -2
- package/dist/InitialConfiguration.js.map +1 -1
- package/dist/config/ThemeRoot.js +12 -7
- package/dist/config/ThemeRoot.js.map +1 -1
- package/dist/generated/VersionInfo.js +3 -3
- package/dist/generated/VersionInfo.js.map +1 -1
- package/dist/prod/InitialConfiguration.js +1 -1
- package/dist/prod/InitialConfiguration.js.map +3 -3
- package/dist/prod/config/ThemeRoot.js +1 -1
- package/dist/prod/config/ThemeRoot.js.map +3 -3
- package/dist/prod/generated/VersionInfo.js +1 -1
- package/dist/prod/generated/VersionInfo.js.map +1 -1
- package/dist/prod/validateThemeRoot.js +1 -1
- package/dist/prod/validateThemeRoot.js.map +3 -3
- package/dist/validateThemeRoot.js +24 -13
- package/dist/validateThemeRoot.js.map +1 -1
- package/package.json +5 -5
|
@@ -7,6 +7,7 @@ import { getTheme } from "../../src/config/Theme.js";
|
|
|
7
7
|
import { getAnimationMode } from "../../src/config/AnimationMode.js";
|
|
8
8
|
import AnimationMode from "../../src/types/AnimationMode.js";
|
|
9
9
|
import { getThemeRoot } from "../../src/config/ThemeRoot.js";
|
|
10
|
+
import applyTheme from "../../src/theming/applyTheme.js";
|
|
10
11
|
|
|
11
12
|
describe("Some settings can be set via SAP UI URL params", () => {
|
|
12
13
|
before(() => {
|
|
@@ -53,88 +54,409 @@ describe("Some settings can be set via SAP UI URL params", () => {
|
|
|
53
54
|
});
|
|
54
55
|
|
|
55
56
|
describe("Different themeRoot configurations", () => {
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
describe("Allowed theme root", () => {
|
|
58
|
+
before(() => {
|
|
59
|
+
const searchParams = "sap-ui-theme=sap_horizon_hcb@https://example.com";
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
// All allowed theme roots need to be described inside the meta tag.
|
|
62
|
+
cy.window()
|
|
63
|
+
.then($el => {
|
|
64
|
+
const metaTag = document.createElement("meta");
|
|
65
|
+
metaTag.name = "sap-allowed-theme-origins";
|
|
66
|
+
metaTag.content = "https://example.com";
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
$el.document.head.append(metaTag);
|
|
69
|
+
});
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
72
|
+
return searchParams;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
cy.wrap({ resetConfiguration })
|
|
76
|
+
.invoke("resetConfiguration", true);
|
|
77
|
+
|
|
78
|
+
cy.wrap(internals)
|
|
79
|
+
.invoke("search")
|
|
80
|
+
.should("be.equal", searchParams);
|
|
81
|
+
|
|
82
|
+
cy.mount(<TestGeneric />);
|
|
71
83
|
});
|
|
72
84
|
|
|
73
|
-
|
|
74
|
-
.
|
|
85
|
+
afterEach(() => {
|
|
86
|
+
cy.window()
|
|
87
|
+
.then($el => {
|
|
88
|
+
const link = $el.document.head.querySelector("link[sap-ui-webcomponents-theme]");
|
|
89
|
+
link?.remove();
|
|
90
|
+
});
|
|
91
|
+
});
|
|
75
92
|
|
|
76
|
-
|
|
77
|
-
.
|
|
78
|
-
|
|
93
|
+
after(() => {
|
|
94
|
+
cy.window()
|
|
95
|
+
.then($el => {
|
|
96
|
+
const metaTag = $el.document.head.querySelector("[name='sap-allowed-theme-origins']");
|
|
97
|
+
metaTag?.remove();
|
|
98
|
+
});
|
|
99
|
+
});
|
|
79
100
|
|
|
80
|
-
|
|
101
|
+
it("should return raw themeRoot from URL parameter", () => {
|
|
102
|
+
cy.wrap({ getThemeRoot })
|
|
103
|
+
.invoke("getThemeRoot")
|
|
104
|
+
.should("equal", "https://example.com");
|
|
105
|
+
});
|
|
81
106
|
|
|
82
|
-
|
|
83
|
-
.
|
|
84
|
-
|
|
107
|
+
it("should extract theme without themeRoot part", () => {
|
|
108
|
+
cy.wrap({ getTheme })
|
|
109
|
+
.invoke("getTheme")
|
|
110
|
+
.should("equal", "sap_horizon_hcb");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should create link in DOM with validated URL", () => {
|
|
114
|
+
// Apply theme to trigger link creation
|
|
115
|
+
cy.wrap({ applyTheme, getTheme })
|
|
116
|
+
.invoke("getTheme")
|
|
117
|
+
.then(theme => {
|
|
118
|
+
return cy.wrap({ applyTheme }).invoke("applyTheme", theme);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
cy.get("link[sap-ui-webcomponents-theme='sap_horizon_hcb']")
|
|
122
|
+
.should("exist")
|
|
123
|
+
.and("have.attr", "href")
|
|
124
|
+
.and("equal", "https://example.com/UI5/Base/baseLib/sap_horizon_hcb/css_variables.css");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe("Unallowed theme root", () => {
|
|
129
|
+
before(() => {
|
|
130
|
+
const searchParams = "sap-ui-theme=sap_horizon_hcb@https://another-example.com";
|
|
131
|
+
|
|
132
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
133
|
+
return searchParams;
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
cy.wrap({ resetConfiguration })
|
|
137
|
+
.invoke("resetConfiguration", true);
|
|
85
138
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
139
|
+
cy.wrap(internals)
|
|
140
|
+
.invoke("search")
|
|
141
|
+
.should("be.equal", searchParams);
|
|
142
|
+
|
|
143
|
+
cy.mount(<TestGeneric />);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
afterEach(() => {
|
|
147
|
+
cy.window()
|
|
148
|
+
.then($el => {
|
|
149
|
+
const link = $el.document.head.querySelector("link[sap-ui-webcomponents-theme]");
|
|
150
|
+
link?.remove();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("should return raw themeRoot even if not allowed", () => {
|
|
155
|
+
cy.wrap({ getThemeRoot })
|
|
156
|
+
.invoke("getThemeRoot")
|
|
157
|
+
.should("equal", "https://another-example.com");
|
|
158
|
+
});
|
|
90
159
|
|
|
91
|
-
|
|
92
|
-
|
|
160
|
+
it("should not create link in DOM due to validation failure", () => {
|
|
161
|
+
cy.get("link[sap-ui-webcomponents-theme='sap_horizon_hcb']")
|
|
162
|
+
.should("not.exist");
|
|
163
|
+
});
|
|
93
164
|
});
|
|
94
165
|
|
|
95
|
-
|
|
96
|
-
|
|
166
|
+
describe("Relative theme root", () => {
|
|
167
|
+
before(() => {
|
|
168
|
+
const searchParams = "sap-ui-theme=sap_horizon_hcb@./test";
|
|
97
169
|
|
|
98
|
-
|
|
99
|
-
|
|
170
|
+
cy.window()
|
|
171
|
+
.then($el => {
|
|
172
|
+
const metaTag = document.createElement("meta");
|
|
173
|
+
metaTag.name = "sap-allowed-theme-origins";
|
|
174
|
+
metaTag.content = "*";
|
|
175
|
+
$el.document.head.append(metaTag);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
179
|
+
return searchParams;
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
cy.wrap({ resetConfiguration })
|
|
183
|
+
.invoke("resetConfiguration", true);
|
|
184
|
+
|
|
185
|
+
cy.wrap(internals)
|
|
186
|
+
.invoke("search")
|
|
187
|
+
.should("be.equal", searchParams);
|
|
188
|
+
|
|
189
|
+
cy.mount(<TestGeneric />);
|
|
100
190
|
});
|
|
101
191
|
|
|
102
|
-
|
|
103
|
-
.
|
|
192
|
+
afterEach(() => {
|
|
193
|
+
cy.window()
|
|
194
|
+
.then($el => {
|
|
195
|
+
const link = $el.document.head.querySelector("link[sap-ui-webcomponents-theme]");
|
|
196
|
+
link?.remove();
|
|
197
|
+
});
|
|
198
|
+
});
|
|
104
199
|
|
|
105
|
-
|
|
106
|
-
.
|
|
107
|
-
|
|
200
|
+
after(() => {
|
|
201
|
+
cy.window()
|
|
202
|
+
.then($el => {
|
|
203
|
+
const metaTag = $el.document.head.querySelector("[name='sap-allowed-theme-origins']");
|
|
204
|
+
metaTag?.remove();
|
|
205
|
+
});
|
|
206
|
+
});
|
|
108
207
|
|
|
109
|
-
|
|
208
|
+
it("should return raw relative themeRoot", () => {
|
|
209
|
+
cy.wrap({ getThemeRoot })
|
|
210
|
+
.invoke("getThemeRoot")
|
|
211
|
+
.should("equal", "./test");
|
|
212
|
+
});
|
|
110
213
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
.
|
|
214
|
+
it("should create link with resolved URL", () => {
|
|
215
|
+
// Apply theme to trigger link creation
|
|
216
|
+
cy.wrap({ applyTheme, getTheme })
|
|
217
|
+
.invoke("getTheme")
|
|
218
|
+
.then(theme => {
|
|
219
|
+
return cy.wrap({ applyTheme }).invoke("applyTheme", theme);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
cy.get("link[sap-ui-webcomponents-theme='sap_horizon_hcb']")
|
|
223
|
+
.should("exist")
|
|
224
|
+
.and("have.attr", "href")
|
|
225
|
+
.then(href => {
|
|
226
|
+
return href.endsWith("/test/UI5/Base/baseLib/sap_horizon_hcb/css_variables.css");
|
|
227
|
+
})
|
|
228
|
+
.should("be.true");
|
|
229
|
+
});
|
|
114
230
|
});
|
|
115
231
|
|
|
116
|
-
|
|
117
|
-
|
|
232
|
+
describe("Absolute path theme root", () => {
|
|
233
|
+
before(() => {
|
|
234
|
+
const searchParams = "sap-ui-theme=custom_theme@/absolute/path";
|
|
118
235
|
|
|
119
|
-
|
|
120
|
-
|
|
236
|
+
cy.window()
|
|
237
|
+
.then($el => {
|
|
238
|
+
const metaTag = document.createElement("meta");
|
|
239
|
+
metaTag.name = "sap-allowed-theme-origins";
|
|
240
|
+
metaTag.content = "*";
|
|
241
|
+
$el.document.head.append(metaTag);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
245
|
+
return searchParams;
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
cy.wrap({ resetConfiguration })
|
|
249
|
+
.invoke("resetConfiguration", true);
|
|
250
|
+
|
|
251
|
+
cy.wrap(internals)
|
|
252
|
+
.invoke("search")
|
|
253
|
+
.should("be.equal", searchParams);
|
|
254
|
+
|
|
255
|
+
cy.mount(<TestGeneric />);
|
|
121
256
|
});
|
|
122
257
|
|
|
123
|
-
|
|
124
|
-
.
|
|
258
|
+
afterEach(() => {
|
|
259
|
+
cy.window()
|
|
260
|
+
.then($el => {
|
|
261
|
+
const link = $el.document.head.querySelector("link[sap-ui-webcomponents-theme]");
|
|
262
|
+
link?.remove();
|
|
263
|
+
});
|
|
264
|
+
});
|
|
125
265
|
|
|
126
|
-
|
|
127
|
-
.
|
|
128
|
-
|
|
266
|
+
after(() => {
|
|
267
|
+
cy.window()
|
|
268
|
+
.then($el => {
|
|
269
|
+
const metaTag = $el.document.head.querySelector("[name='sap-allowed-theme-origins']");
|
|
270
|
+
metaTag?.remove();
|
|
271
|
+
});
|
|
272
|
+
});
|
|
129
273
|
|
|
130
|
-
|
|
274
|
+
it("should return raw absolute path", () => {
|
|
275
|
+
cy.wrap({ getThemeRoot })
|
|
276
|
+
.invoke("getThemeRoot")
|
|
277
|
+
.should("equal", "/absolute/path");
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
it("should create link with resolved URL", () => {
|
|
281
|
+
// Apply theme to trigger link creation
|
|
282
|
+
cy.wrap({ applyTheme, getTheme })
|
|
283
|
+
.invoke("getTheme")
|
|
284
|
+
.then(theme => {
|
|
285
|
+
return cy.wrap({ applyTheme }).invoke("applyTheme", theme);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
cy.get("link[sap-ui-webcomponents-theme='custom_theme']")
|
|
289
|
+
.should("exist")
|
|
290
|
+
.and("have.attr", "href")
|
|
291
|
+
.then(href => {
|
|
292
|
+
return href.endsWith("/absolute/path/UI5/Base/baseLib/custom_theme/css_variables.css");
|
|
293
|
+
})
|
|
294
|
+
.should("be.true");
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
describe("ThemeRoot with trailing slash", () => {
|
|
299
|
+
before(() => {
|
|
300
|
+
const searchParams = "sap-ui-theme=custom_theme@https://cdn.example.com/themes/";
|
|
301
|
+
|
|
302
|
+
cy.window()
|
|
303
|
+
.then($el => {
|
|
304
|
+
const metaTag = document.createElement("meta");
|
|
305
|
+
metaTag.name = "sap-allowed-theme-origins";
|
|
306
|
+
metaTag.content = "https://cdn.example.com";
|
|
307
|
+
$el.document.head.append(metaTag);
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
311
|
+
return searchParams;
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
cy.wrap({ resetConfiguration })
|
|
315
|
+
.invoke("resetConfiguration", true);
|
|
316
|
+
|
|
317
|
+
cy.wrap(internals)
|
|
318
|
+
.invoke("search")
|
|
319
|
+
.should("be.equal", searchParams);
|
|
320
|
+
|
|
321
|
+
cy.mount(<TestGeneric />);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
afterEach(() => {
|
|
325
|
+
cy.window()
|
|
326
|
+
.then($el => {
|
|
327
|
+
const link = $el.document.head.querySelector("link[sap-ui-webcomponents-theme]");
|
|
328
|
+
link?.remove();
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
after(() => {
|
|
333
|
+
cy.window()
|
|
334
|
+
.then($el => {
|
|
335
|
+
const metaTag = $el.document.head.querySelector("[name='sap-allowed-theme-origins']");
|
|
336
|
+
metaTag?.remove();
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it("should return raw themeRoot with trailing slash", () => {
|
|
341
|
+
cy.wrap({ getThemeRoot })
|
|
342
|
+
.invoke("getThemeRoot")
|
|
343
|
+
.should("equal", "https://cdn.example.com/themes/");
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it("should create link normalizing trailing slash", () => {
|
|
347
|
+
// Apply theme to trigger link creation
|
|
348
|
+
cy.wrap({ applyTheme, getTheme })
|
|
349
|
+
.invoke("getTheme")
|
|
350
|
+
.then(theme => {
|
|
351
|
+
return cy.wrap({ applyTheme }).invoke("applyTheme", theme);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
cy.get("link[sap-ui-webcomponents-theme='custom_theme']")
|
|
355
|
+
.should("exist")
|
|
356
|
+
.and("have.attr", "href")
|
|
357
|
+
.and("equal", "https://cdn.example.com/themes/UI5/Base/baseLib/custom_theme/css_variables.css");
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
describe("Invalid URL format", () => {
|
|
362
|
+
before(() => {
|
|
363
|
+
const searchParams = "sap-ui-theme=custom_theme@not-a-valid-url";
|
|
131
364
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
})
|
|
137
|
-
|
|
365
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
366
|
+
return searchParams;
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
cy.wrap({ resetConfiguration })
|
|
370
|
+
.invoke("resetConfiguration", true);
|
|
371
|
+
|
|
372
|
+
cy.wrap(internals)
|
|
373
|
+
.invoke("search")
|
|
374
|
+
.should("be.equal", searchParams);
|
|
375
|
+
|
|
376
|
+
cy.mount(<TestGeneric />);
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
afterEach(() => {
|
|
380
|
+
cy.window()
|
|
381
|
+
.then($el => {
|
|
382
|
+
const link = $el.document.head.querySelector("link[sap-ui-webcomponents-theme]");
|
|
383
|
+
link?.remove();
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
it("should return raw invalid URL value", () => {
|
|
388
|
+
cy.wrap({ getThemeRoot })
|
|
389
|
+
.invoke("getThemeRoot")
|
|
390
|
+
.should("equal", "not-a-valid-url");
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it("should not create link due to invalid URL", () => {
|
|
394
|
+
cy.get("link[sap-ui-webcomponents-theme='custom_theme']")
|
|
395
|
+
.should("not.exist");
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
describe("Legacy meta tag name support", () => {
|
|
400
|
+
before(() => {
|
|
401
|
+
const searchParams = "sap-ui-theme=custom_theme@https://legacy.example.com";
|
|
402
|
+
|
|
403
|
+
cy.window()
|
|
404
|
+
.then($el => {
|
|
405
|
+
const metaTag = document.createElement("meta");
|
|
406
|
+
metaTag.name = "sap-allowedThemeOrigins"; // Old camelCase format
|
|
407
|
+
metaTag.content = "https://legacy.example.com";
|
|
408
|
+
$el.document.head.append(metaTag);
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
412
|
+
return searchParams;
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
cy.wrap({ resetConfiguration })
|
|
416
|
+
.invoke("resetConfiguration", true);
|
|
417
|
+
|
|
418
|
+
cy.wrap(internals)
|
|
419
|
+
.invoke("search")
|
|
420
|
+
.should("be.equal", searchParams);
|
|
421
|
+
|
|
422
|
+
cy.mount(<TestGeneric />);
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
afterEach(() => {
|
|
426
|
+
cy.window()
|
|
427
|
+
.then($el => {
|
|
428
|
+
const link = $el.document.head.querySelector("link[sap-ui-webcomponents-theme]");
|
|
429
|
+
link?.remove();
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
after(() => {
|
|
434
|
+
cy.window()
|
|
435
|
+
.then($el => {
|
|
436
|
+
const metaTag = $el.document.head.querySelector("[name='sap-allowedThemeOrigins']");
|
|
437
|
+
metaTag?.remove();
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
it("should return raw themeRoot", () => {
|
|
442
|
+
cy.wrap({ getThemeRoot })
|
|
443
|
+
.invoke("getThemeRoot")
|
|
444
|
+
.should("equal", "https://legacy.example.com");
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
it("should support legacy sap-allowedThemeOrigins meta tag", () => {
|
|
448
|
+
// Apply theme to trigger link creation
|
|
449
|
+
cy.wrap({ applyTheme, getTheme })
|
|
450
|
+
.invoke("getTheme")
|
|
451
|
+
.then(theme => {
|
|
452
|
+
return cy.wrap({ applyTheme }).invoke("applyTheme", theme);
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
cy.get("link[sap-ui-webcomponents-theme='custom_theme']")
|
|
456
|
+
.should("exist")
|
|
457
|
+
.and("have.attr", "href")
|
|
458
|
+
.and("equal", "https://legacy.example.com/UI5/Base/baseLib/custom_theme/css_variables.css");
|
|
459
|
+
});
|
|
138
460
|
});
|
|
139
461
|
});
|
|
140
462
|
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { internals } from "../../src/Location.js";
|
|
2
|
+
import TestGeneric from "../../test/test-elements/Generic.js";
|
|
3
|
+
import { resetConfiguration } from "../../src/InitialConfiguration.js";
|
|
4
|
+
import { getTheme } from "../../src/config/Theme.js";
|
|
5
|
+
import { getThemeRoot } from "../../src/config/ThemeRoot.js";
|
|
6
|
+
import applyTheme from "../../src/theming/applyTheme.js";
|
|
7
|
+
|
|
8
|
+
const THEME = "sap_horizon";
|
|
9
|
+
|
|
10
|
+
const addMetaTag = (content: string) => {
|
|
11
|
+
cy.window().then($win => {
|
|
12
|
+
const metaTag = $win.document.createElement("meta");
|
|
13
|
+
metaTag.name = "sap-allowed-theme-origins";
|
|
14
|
+
metaTag.content = content;
|
|
15
|
+
$win.document.head.append(metaTag);
|
|
16
|
+
});
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const removeMetaTag = () => {
|
|
20
|
+
cy.window().then($win => {
|
|
21
|
+
$win.document.head.querySelector("[name='sap-allowed-theme-origins']")?.remove();
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const removeThemeLink = () => {
|
|
26
|
+
cy.window().then($win => {
|
|
27
|
+
$win.document.head.querySelector("link[sap-ui-webcomponents-theme]")?.remove();
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const applyAndCheckLink = (theme: string) => {
|
|
32
|
+
cy.wrap({ applyTheme, getTheme })
|
|
33
|
+
.invoke("getTheme")
|
|
34
|
+
.then(() => {
|
|
35
|
+
return cy.wrap({ applyTheme }).invoke("applyTheme", theme);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// ─── Without meta tag ────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
describe("ThemeRoot via URL param — without meta tag", () => {
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
removeThemeLink();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
[
|
|
47
|
+
{ label: "absolute URL (different origin)", themeRoot: "http://example2.com/themes/", blocked: true },
|
|
48
|
+
{ label: "absolute URL (different protocol)", themeRoot: "https://example.com/themes/", blocked: true },
|
|
49
|
+
{ label: "absolute URL (different port)", themeRoot: "http://example:9090.com/themes/", blocked: true },
|
|
50
|
+
{ label: "absolute URL (same host, no meta tag)", themeRoot: "http://example.com/themes/", blocked: true },
|
|
51
|
+
{ label: "protocol-relative (different origin)", themeRoot: "//example2.com/themes/", blocked: true },
|
|
52
|
+
{ label: "protocol-relative (different port)", themeRoot: "//example:9090.com/themes/", blocked: true },
|
|
53
|
+
{ label: "protocol-relative (same host, no meta tag)", themeRoot: "//example.com/themes/", blocked: true },
|
|
54
|
+
{ label: "root-relative", themeRoot: "/themes/", blocked: false },
|
|
55
|
+
{ label: "relative (current dir)", themeRoot: "./themes/", blocked: false },
|
|
56
|
+
{ label: "relative (parent dir)", themeRoot: "../themes/", blocked: false },
|
|
57
|
+
].forEach(({ label, themeRoot, blocked }) => {
|
|
58
|
+
describe(`${label}: ${themeRoot}`, () => {
|
|
59
|
+
before(() => {
|
|
60
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
61
|
+
return `sap-ui-theme=${THEME}@${themeRoot}`;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
cy.wrap({ resetConfiguration }).invoke("resetConfiguration", true);
|
|
65
|
+
cy.mount(<TestGeneric />);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it(blocked ? "should not create a link element" : "should create a link element (same-origin, no meta tag needed)", () => {
|
|
69
|
+
applyAndCheckLink(THEME);
|
|
70
|
+
if (blocked) {
|
|
71
|
+
cy.get(`link[sap-ui-webcomponents-theme='${THEME}']`).should("not.exist");
|
|
72
|
+
} else {
|
|
73
|
+
cy.get(`link[sap-ui-webcomponents-theme='${THEME}']`)
|
|
74
|
+
.should("exist")
|
|
75
|
+
.and("have.attr", "href")
|
|
76
|
+
.and("include", `UI5/Base/baseLib/${THEME}/css_variables.css`);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// ─── With meta tag ────────────────────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
describe("ThemeRoot via URL param — with meta tag (allowed: http://example.com)", () => {
|
|
86
|
+
afterEach(() => {
|
|
87
|
+
removeThemeLink();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
after(() => {
|
|
91
|
+
removeMetaTag();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
before(() => {
|
|
95
|
+
addMetaTag("http://example.com");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const blocked = [
|
|
99
|
+
{ label: "absolute URL (different origin)", themeRoot: "http://example2.com/themes/" },
|
|
100
|
+
{ label: "absolute URL (different protocol)", themeRoot: "https://example.com/themes/" },
|
|
101
|
+
{ label: "absolute URL (different port)", themeRoot: "http://example:9090.com/themes/" },
|
|
102
|
+
{ label: "protocol-relative (different origin)", themeRoot: "//example2.com/themes/" },
|
|
103
|
+
{ label: "protocol-relative (different port)", themeRoot: "//example:9090.com/themes/" },
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const allowed = [
|
|
107
|
+
{
|
|
108
|
+
label: "absolute URL (matches allowed origin)",
|
|
109
|
+
themeRoot: "http://example.com/themes/",
|
|
110
|
+
expectedHref: "http://example.com/themes/UI5/Base/baseLib/sap_horizon/css_variables.css",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
label: "protocol-relative (resolves to allowed origin)",
|
|
114
|
+
themeRoot: "//example.com/themes/",
|
|
115
|
+
expectedHref: "http://example.com/themes/UI5/Base/baseLib/sap_horizon/css_variables.css",
|
|
116
|
+
},
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
const sameOriginAllowed = [
|
|
120
|
+
{ label: "root-relative", themeRoot: "/themes/" },
|
|
121
|
+
{ label: "relative (current dir)", themeRoot: "./themes/" },
|
|
122
|
+
{ label: "relative (parent dir)", themeRoot: "../themes/" },
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
blocked.forEach(({ label, themeRoot }) => {
|
|
126
|
+
describe(`blocked — ${label}: ${themeRoot}`, () => {
|
|
127
|
+
before(() => {
|
|
128
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
129
|
+
return `sap-ui-theme=${THEME}@${themeRoot}`;
|
|
130
|
+
});
|
|
131
|
+
cy.wrap({ resetConfiguration }).invoke("resetConfiguration", true);
|
|
132
|
+
cy.mount(<TestGeneric />);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it("should not create a link element", () => {
|
|
136
|
+
applyAndCheckLink(THEME);
|
|
137
|
+
cy.get(`link[sap-ui-webcomponents-theme='${THEME}']`).should("not.exist");
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
allowed.forEach(({ label, themeRoot, expectedHref }) => {
|
|
143
|
+
describe(`allowed — ${label}: ${themeRoot}`, () => {
|
|
144
|
+
before(() => {
|
|
145
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
146
|
+
return `sap-ui-theme=${THEME}@${themeRoot}`;
|
|
147
|
+
});
|
|
148
|
+
cy.wrap({ resetConfiguration }).invoke("resetConfiguration", true);
|
|
149
|
+
cy.mount(<TestGeneric />);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("should create a link element with correct href", () => {
|
|
153
|
+
applyAndCheckLink(THEME);
|
|
154
|
+
cy.get(`link[sap-ui-webcomponents-theme='${THEME}']`)
|
|
155
|
+
.should("exist")
|
|
156
|
+
.and("have.attr", "href", expectedHref);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
sameOriginAllowed.forEach(({ label, themeRoot }) => {
|
|
162
|
+
describe(`allowed (same-origin) — ${label}: ${themeRoot}`, () => {
|
|
163
|
+
before(() => {
|
|
164
|
+
cy.stub(internals, "search").callsFake(() => {
|
|
165
|
+
return `sap-ui-theme=${THEME}@${themeRoot}`;
|
|
166
|
+
});
|
|
167
|
+
cy.wrap({ resetConfiguration }).invoke("resetConfiguration", true);
|
|
168
|
+
cy.mount(<TestGeneric />);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("should create a link element", () => {
|
|
172
|
+
applyAndCheckLink(THEME);
|
|
173
|
+
cy.get(`link[sap-ui-webcomponents-theme='${THEME}']`)
|
|
174
|
+
.should("exist")
|
|
175
|
+
.and("have.attr", "href")
|
|
176
|
+
.and("include", `UI5/Base/baseLib/${THEME}/css_variables.css`);
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|