@sap-ux/preview-middleware 1.0.49 → 1.1.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/README.md +7 -6
- package/dist/base/flp.d.ts +3 -0
- package/dist/base/flp.js +52 -16
- package/dist/base/test.js +6 -3
- package/dist/types/index.d.ts +8 -0
- package/package.json +5 -5
- package/templates/test/{qunit.js → qunit-init.ejs} +9 -2
- package/templates/test/testsuite.qunit-init.ejs +13 -0
- package/templates/test/testsuite.qunit.js +0 -8
package/README.md
CHANGED
|
@@ -66,12 +66,13 @@ Array of additional application configurations:
|
|
|
66
66
|
| `rta.endpoints.developerMode` | `boolean` | optional | `false` | Flag to enable the runtime adaptation developer mode (only supported for adaptation projects) |
|
|
67
67
|
|
|
68
68
|
### [`test`](#configuration-option-test)
|
|
69
|
-
| Option
|
|
70
|
-
|
|
71
|
-
| `framework`
|
|
72
|
-
| `path`
|
|
73
|
-
| `init`
|
|
74
|
-
| `pattern`
|
|
69
|
+
| Option | Value Type | Requirement Type | Default Value | Description |
|
|
70
|
+
|-------------------|------------|------------------|----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
71
|
+
| `framework` | `string` | mandatory | `undefined` | Currently `OPA5`, `QUnit` (only QUnit 2.3.2 provided as third-party module using [OpenUI5](https://github.com/SAP/openui5/blob/master/THIRDPARTY.txt)/SAPUI5) and `Testsuite` are supported. `Testsuite` will generate a testsuite for all configured frameworks that can be be used with a test runner (such as karma) |
|
|
72
|
+
| `path` | `string` | optional | `(calculated)` | The mount point to be used for test suite. By default, `/test/opaTests.qunit.html` is used for `OPA5`, `/test/unitTests.qunit.html` is used for `QUnit`, and `/test/testsuite.qunit.html` is used for `Testsuite` |
|
|
73
|
+
| `init` | `string` | optional | `undefined` | The mount point to be used for custom test runner script |
|
|
74
|
+
| `pattern` | `string` | optional | `(calculated)` | Optional glob pattern to find the tests. By default, `/test/**/*Journey{,.gen}.{js,ts}` is used for `OPA5` and `/test/**/*Test.{js,ts}` is used for `QUnit` (not applicable for `Testsuite`) |
|
|
75
|
+
| `isolateJourneys` | `boolean` | optional | `false` | Only applicable for `OPA5`. When `true` and a `Testsuite` is configured, each journey is added as a separate test page with a `?journey=` URL parameter. The OPA5 init script respects this parameter and loads only the specified journey, enabling isolated test runs per journey. |
|
|
75
76
|
|
|
76
77
|
|
|
77
78
|
## [Usage](#usage)
|
package/dist/base/flp.d.ts
CHANGED
|
@@ -246,6 +246,8 @@ export declare class FlpSandbox {
|
|
|
246
246
|
* @param config the test configuration
|
|
247
247
|
* @param initTemplate the test runner template
|
|
248
248
|
* @param testPaths the paths to the test files
|
|
249
|
+
* @param opa5Path optional relative path from testsuite to OPA5 HTML page
|
|
250
|
+
* @param journeyNamesForIsolation optional list of journey module paths for isolated runs
|
|
249
251
|
* @private
|
|
250
252
|
*/
|
|
251
253
|
private testSuiteJsGetHandler;
|
|
@@ -253,6 +255,7 @@ export declare class FlpSandbox {
|
|
|
253
255
|
* If it is part of TestConfig, create a test suite for the test configurations.
|
|
254
256
|
*
|
|
255
257
|
* @param configs test configurations
|
|
258
|
+
* @param id application id from manifest
|
|
256
259
|
* @private
|
|
257
260
|
*/
|
|
258
261
|
private createTestSuite;
|
package/dist/base/flp.js
CHANGED
|
@@ -20,6 +20,15 @@ import { getIntegrationCard } from './utils/cards.js';
|
|
|
20
20
|
import { createPropertiesI18nEntries } from '@sap-ux/i18n';
|
|
21
21
|
import { AdaptationProjectType } from '@sap-ux/axios-extension';
|
|
22
22
|
const DEFAULT_LIVERELOAD_PORT = 35729;
|
|
23
|
+
/**
|
|
24
|
+
* Convert an application id to its namespace by replacing dots with slashes.
|
|
25
|
+
*
|
|
26
|
+
* @param id application id from manifest (e.g. 'test.fe.v2.app')
|
|
27
|
+
* @returns namespace string (e.g. 'test/fe/v2/app')
|
|
28
|
+
*/
|
|
29
|
+
function toNamespace(id) {
|
|
30
|
+
return id.replaceAll('.', '/');
|
|
31
|
+
}
|
|
23
32
|
/**
|
|
24
33
|
* Class handling preview of a sandbox FLP.
|
|
25
34
|
*/
|
|
@@ -106,7 +115,7 @@ export class FlpSandbox {
|
|
|
106
115
|
}
|
|
107
116
|
if (this.test) {
|
|
108
117
|
this.addTestRoutes(this.test.filter((config) => config.framework !== 'Testsuite'), id);
|
|
109
|
-
this.createTestSuite(this.test);
|
|
118
|
+
await this.createTestSuite(this.test, id);
|
|
110
119
|
}
|
|
111
120
|
if (this.flpConfig.enhancedHomePage) {
|
|
112
121
|
this.addCDMRoute();
|
|
@@ -648,9 +657,11 @@ export class FlpSandbox {
|
|
|
648
657
|
* @param config the test configuration
|
|
649
658
|
* @param initTemplate the test runner template
|
|
650
659
|
* @param testPaths the paths to the test files
|
|
660
|
+
* @param opa5Path optional relative path from testsuite to OPA5 HTML page
|
|
661
|
+
* @param journeyNamesForIsolation optional list of journey module paths for isolated runs
|
|
651
662
|
* @private
|
|
652
663
|
*/
|
|
653
|
-
async testSuiteJsGetHandler(res, next, config, initTemplate, testPaths) {
|
|
664
|
+
async testSuiteJsGetHandler(res, next, config, initTemplate, testPaths, opa5Path, journeyNamesForIsolation) {
|
|
654
665
|
const files = await this.project.byGlob(config.init.replace('.js', '.[jt]s'));
|
|
655
666
|
if (files?.length > 0) {
|
|
656
667
|
this.logger.warn(`Script returned at ${config.path} is loaded from the file system.`);
|
|
@@ -658,9 +669,9 @@ export class FlpSandbox {
|
|
|
658
669
|
}
|
|
659
670
|
else {
|
|
660
671
|
this.logger.debug(`Serving test route: ${config.init}`);
|
|
661
|
-
const templateConfig =
|
|
662
|
-
testPaths:
|
|
663
|
-
|
|
672
|
+
const templateConfig = opa5Path && journeyNamesForIsolation?.length
|
|
673
|
+
? { testPaths, opa5Path, journeyNames: journeyNamesForIsolation }
|
|
674
|
+
: { testPaths };
|
|
664
675
|
const js = render(initTemplate, templateConfig);
|
|
665
676
|
this.sendResponse(res, 'application/javascript', 200, js);
|
|
666
677
|
}
|
|
@@ -669,9 +680,10 @@ export class FlpSandbox {
|
|
|
669
680
|
* If it is part of TestConfig, create a test suite for the test configurations.
|
|
670
681
|
*
|
|
671
682
|
* @param configs test configurations
|
|
683
|
+
* @param id application id from manifest
|
|
672
684
|
* @private
|
|
673
685
|
*/
|
|
674
|
-
createTestSuite(configs) {
|
|
686
|
+
async createTestSuite(configs, id) {
|
|
675
687
|
const testsuiteConfig = configs.find((config) => config.framework === 'Testsuite');
|
|
676
688
|
if (!testsuiteConfig) {
|
|
677
689
|
//silent skip: create a testsuite only if it is explicitly part of the test configuration
|
|
@@ -691,18 +703,36 @@ export class FlpSandbox {
|
|
|
691
703
|
this.logger.debug(`Skip serving testsuite init script in favor of provided script: ${testsuiteConfig.init}`);
|
|
692
704
|
return;
|
|
693
705
|
}
|
|
706
|
+
const ns = toNamespace(id);
|
|
707
|
+
const qunitConfig = configs.find((c) => c.framework === 'QUnit');
|
|
708
|
+
const opa5Config = configs.find((c) => c.framework === 'OPA5');
|
|
709
|
+
const mergedOpa5Config = opa5Config ? mergeTestConfigDefaults(opa5Config) : undefined;
|
|
694
710
|
const testPaths = [];
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
711
|
+
let opa5Path;
|
|
712
|
+
let journeyNamesForIsolation;
|
|
713
|
+
if (qunitConfig) {
|
|
714
|
+
testPaths.push(posix.relative(posix.dirname(config.path), mergeTestConfigDefaults(qunitConfig).path));
|
|
715
|
+
}
|
|
716
|
+
if (mergedOpa5Config) {
|
|
717
|
+
if (mergedOpa5Config.isolateJourneys) {
|
|
718
|
+
try {
|
|
719
|
+
const journeyFiles = await this.project.byGlob(mergedOpa5Config.pattern);
|
|
720
|
+
journeyNamesForIsolation = generateImportList(ns, journeyFiles);
|
|
721
|
+
opa5Path = posix.relative(posix.dirname(config.path), mergedOpa5Config.path);
|
|
722
|
+
}
|
|
723
|
+
catch (e) {
|
|
724
|
+
this.logger.error(`Failed to discover journey files: ${e.message}. OPA5 page will be added to testsuite without isolated journeys.`);
|
|
725
|
+
testPaths.push(posix.relative(posix.dirname(config.path), mergedOpa5Config.path));
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
else {
|
|
729
|
+
testPaths.push(posix.relative(posix.dirname(config.path), mergedOpa5Config.path));
|
|
698
730
|
}
|
|
699
|
-
const mergedConfig = mergeTestConfigDefaults(testConfig);
|
|
700
|
-
testPaths.push(posix.relative(posix.dirname(config.path), mergedConfig.path));
|
|
701
731
|
}
|
|
702
|
-
const initTemplate = readFileSync(join(__dirname, '../../templates/test/testsuite.qunit.
|
|
732
|
+
const initTemplate = readFileSync(join(__dirname, '../../templates/test/testsuite.qunit-init.ejs'), 'utf-8');
|
|
703
733
|
this.logger.debug(`Add route for ${config.init}`);
|
|
704
734
|
this.router.get(config.init, async (_req, res, next) => {
|
|
705
|
-
await this.testSuiteJsGetHandler(res, next, config, initTemplate, testPaths);
|
|
735
|
+
await this.testSuiteJsGetHandler(res, next, config, initTemplate, testPaths, opa5Path, journeyNamesForIsolation);
|
|
706
736
|
});
|
|
707
737
|
}
|
|
708
738
|
/**
|
|
@@ -763,7 +793,13 @@ export class FlpSandbox {
|
|
|
763
793
|
}
|
|
764
794
|
else {
|
|
765
795
|
const testFiles = await this.project.byGlob(config.pattern);
|
|
766
|
-
|
|
796
|
+
if (testFiles.length === 0) {
|
|
797
|
+
this.logger.warn(`No test files found for pattern '${config.pattern}'.`);
|
|
798
|
+
}
|
|
799
|
+
const templateConfig = {
|
|
800
|
+
tests: generateImportList(ns, testFiles),
|
|
801
|
+
isolateJourneys: config.isolateJourneys === true
|
|
802
|
+
};
|
|
767
803
|
const js = render(initTemplate, templateConfig);
|
|
768
804
|
this.sendResponse(res, 'application/javascript', 200, js);
|
|
769
805
|
}
|
|
@@ -775,7 +811,7 @@ export class FlpSandbox {
|
|
|
775
811
|
* @param id application id from manifest
|
|
776
812
|
*/
|
|
777
813
|
addTestRoutes(configs, id) {
|
|
778
|
-
const ns = id
|
|
814
|
+
const ns = toNamespace(id);
|
|
779
815
|
const htmlTemplate = readFileSync(join(__dirname, '../../templates/test/qunit.ejs'), 'utf-8');
|
|
780
816
|
for (const testConfig of configs) {
|
|
781
817
|
const config = mergeTestConfigDefaults(testConfig);
|
|
@@ -789,7 +825,7 @@ export class FlpSandbox {
|
|
|
789
825
|
continue;
|
|
790
826
|
}
|
|
791
827
|
// add route for the init file
|
|
792
|
-
const initTemplate = readFileSync(join(__dirname, '../../templates/test/qunit.
|
|
828
|
+
const initTemplate = readFileSync(join(__dirname, '../../templates/test/qunit-init.ejs'), 'utf-8');
|
|
793
829
|
this.logger.debug(`Add route for ${config.init}`);
|
|
794
830
|
this.router.get(config.init, async (_req, res, next) => {
|
|
795
831
|
await this.testRunnerJsGetHandler(res, next, config, initTemplate, ns);
|
package/dist/base/test.js
CHANGED
|
@@ -3,19 +3,22 @@ const DEFAULTS = {
|
|
|
3
3
|
path: '/test/unitTests.qunit.html',
|
|
4
4
|
init: '/test/unitTests.qunit.js',
|
|
5
5
|
pattern: '/test/**/*Test.{js,ts}',
|
|
6
|
-
framework: 'QUnit'
|
|
6
|
+
framework: 'QUnit',
|
|
7
|
+
isolateJourneys: false
|
|
7
8
|
},
|
|
8
9
|
opa5: {
|
|
9
10
|
path: '/test/opaTests.qunit.html',
|
|
10
11
|
init: '/test/opaTests.qunit.js',
|
|
11
12
|
pattern: '/test/**/*Journey{,.gen}.{js,ts}',
|
|
12
|
-
framework: 'OPA5'
|
|
13
|
+
framework: 'OPA5',
|
|
14
|
+
isolateJourneys: false
|
|
13
15
|
},
|
|
14
16
|
testsuite: {
|
|
15
17
|
path: '/test/testsuite.qunit.html',
|
|
16
18
|
init: '/test/testsuite.qunit.js',
|
|
17
19
|
pattern: '',
|
|
18
|
-
framework: 'Testsuite'
|
|
20
|
+
framework: 'Testsuite',
|
|
21
|
+
isolateJourneys: false
|
|
19
22
|
}
|
|
20
23
|
};
|
|
21
24
|
/**
|
package/dist/types/index.d.ts
CHANGED
|
@@ -80,6 +80,11 @@ export interface TestConfig {
|
|
|
80
80
|
* Pattern to match the test files
|
|
81
81
|
*/
|
|
82
82
|
pattern?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Optional: when true, each OPA5 journey runs in its own isolated test page.
|
|
85
|
+
* Only meaningful when framework is 'OPA5'.
|
|
86
|
+
*/
|
|
87
|
+
isolateJourneys?: boolean;
|
|
83
88
|
}
|
|
84
89
|
/**
|
|
85
90
|
* Test configuration that has been enriched with the defaults in case of missing values.
|
|
@@ -94,18 +99,21 @@ export type TestConfigDefaults = {
|
|
|
94
99
|
init: '/test/unitTests.qunit.js';
|
|
95
100
|
pattern: '/test/**/*Test.{js,ts}';
|
|
96
101
|
framework: 'QUnit';
|
|
102
|
+
isolateJourneys: false;
|
|
97
103
|
};
|
|
98
104
|
opa5: {
|
|
99
105
|
path: '/test/opaTests.qunit.html';
|
|
100
106
|
init: '/test/opaTests.qunit.js';
|
|
101
107
|
pattern: '/test/**/*Journey{,.gen}.{js,ts}';
|
|
102
108
|
framework: 'OPA5';
|
|
109
|
+
isolateJourneys: false;
|
|
103
110
|
};
|
|
104
111
|
testsuite: {
|
|
105
112
|
path: '/test/testsuite.qunit.html';
|
|
106
113
|
init: '/test/testsuite.qunit.js';
|
|
107
114
|
pattern: '';
|
|
108
115
|
framework: 'Testsuite';
|
|
116
|
+
isolateJourneys: false;
|
|
109
117
|
};
|
|
110
118
|
};
|
|
111
119
|
export type CardGeneratorConfig = {
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"bugs": {
|
|
11
11
|
"url": "https://github.com/SAP/open-ux-tools/issues?q=is%3Aopen+is%3Aissue+label%3Abug+label%3Apreview-middleware"
|
|
12
12
|
},
|
|
13
|
-
"version": "1.
|
|
13
|
+
"version": "1.1.1",
|
|
14
14
|
"license": "Apache-2.0",
|
|
15
15
|
"author": "@SAP/ux-tools-team",
|
|
16
16
|
"main": "dist/index.js",
|
|
@@ -28,12 +28,12 @@
|
|
|
28
28
|
"mem-fs-editor": "9.4.0",
|
|
29
29
|
"qrcode": "1.5.4",
|
|
30
30
|
"@sap/bas-sdk": "3.13.10",
|
|
31
|
-
"@sap-ux/adp-tooling": "1.0.
|
|
31
|
+
"@sap-ux/adp-tooling": "1.0.40",
|
|
32
32
|
"@sap-ux/btp-utils": "2.0.6",
|
|
33
|
-
"@sap-ux/control-property-editor-sources": "npm:@sap-ux/control-property-editor@1.0.10",
|
|
34
33
|
"@sap-ux/feature-toggle": "1.0.5",
|
|
35
34
|
"@sap-ux/logger": "1.0.3",
|
|
36
|
-
"@sap-ux/
|
|
35
|
+
"@sap-ux/control-property-editor-sources": "npm:@sap-ux/control-property-editor@1.0.10",
|
|
36
|
+
"@sap-ux/project-access": "2.1.10",
|
|
37
37
|
"@sap-ux/system-access": "1.0.10",
|
|
38
38
|
"@sap-ux/i18n": "1.0.2"
|
|
39
39
|
},
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"nock": "14.0.16",
|
|
55
55
|
"npm-run-all2": "9.0.2",
|
|
56
56
|
"supertest": "7.2.2",
|
|
57
|
-
"@private/preview-middleware-client": "npm:@sap-ux-private/preview-middleware-client@1.
|
|
57
|
+
"@private/preview-middleware-client": "npm:@sap-ux-private/preview-middleware-client@1.1.1",
|
|
58
58
|
"@sap-ux-private/playwright": "1.0.6",
|
|
59
59
|
"@sap-ux/axios-extension": "2.0.8",
|
|
60
60
|
"@sap-ux/store": "2.0.6",
|
|
@@ -17,13 +17,20 @@ sap.ui.loader.config({
|
|
|
17
17
|
|
|
18
18
|
window.QUnit = Object.assign({}, window.QUnit, { config: { autostart: false } });
|
|
19
19
|
|
|
20
|
+
<% if (locals.isolateJourneys) { -%>
|
|
21
|
+
const knownJourneys = <%- JSON.stringify(tests) %>;
|
|
22
|
+
const journeyParam = new URLSearchParams(window.location.search).get("journey");
|
|
23
|
+
const modulesToRequire = (journeyParam && knownJourneys.includes(journeyParam)) ? [journeyParam] : knownJourneys;
|
|
24
|
+
<% } else { -%>
|
|
25
|
+
const modulesToRequire = <%- JSON.stringify(tests) %>;
|
|
26
|
+
<% } -%>
|
|
20
27
|
sap.ui.require([
|
|
21
28
|
"sap/ui/thirdparty/qunit-2",
|
|
22
29
|
"sap/ui/qunit/qunit-junit",
|
|
23
30
|
"sap/ui/qunit/qunit-coverage"
|
|
24
31
|
], function (QUnit) {
|
|
25
32
|
'use strict';
|
|
26
|
-
sap.ui.require(
|
|
33
|
+
sap.ui.require(modulesToRequire, function() {
|
|
27
34
|
QUnit.start();
|
|
28
35
|
});
|
|
29
|
-
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
window.suite = function () {
|
|
2
|
+
const oSuite = new parent.jsUnitTestSuite();
|
|
3
|
+
var sContextPath = location.pathname.substring(0, location.pathname.lastIndexOf("/") + 1);
|
|
4
|
+
<% for (const path of locals.testPaths) { -%>
|
|
5
|
+
oSuite.addTestPage(sContextPath + "<%- path %>");
|
|
6
|
+
<% } -%>
|
|
7
|
+
<% if (locals.opa5Path && locals.journeyNames && locals.journeyNames.length > 0) { -%>
|
|
8
|
+
<% for (const name of locals.journeyNames) { -%>
|
|
9
|
+
oSuite.addTestPage(sContextPath + "<%- locals.opa5Path %>?journey=<%- name %>");
|
|
10
|
+
<% } -%>
|
|
11
|
+
<% } -%>
|
|
12
|
+
return oSuite;
|
|
13
|
+
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
window.suite = function () {
|
|
2
|
-
const oSuite = new parent.jsUnitTestSuite();
|
|
3
|
-
var sContextPath = location.pathname.substring(0, location.pathname.lastIndexOf("/") + 1);
|
|
4
|
-
<% for (const path of locals.testPaths) { %>
|
|
5
|
-
oSuite.addTestPage(sContextPath + "<%- path %>");
|
|
6
|
-
<% } %>
|
|
7
|
-
return oSuite;
|
|
8
|
-
}
|