Skip to content

Commit

Permalink
feat: support sap.ui.require for QUnit testsuites or annotated modules
Browse files Browse the repository at this point in the history
QUnit testsuites using `QUnit.config.autostart = false` and `QUnit.start()`
are automatically detected to use `sap.ui.require` instead of `sap.ui.define`.
Modules can be also marked to use `sap.ui.require` by using the annotation
`/* @sapUiRequire */` in the program.
  • Loading branch information
petermuessig committed Jul 15, 2024
1 parent afd2f7c commit ac0078b
Show file tree
Hide file tree
Showing 10 changed files with 333 additions and 12 deletions.
56 changes: 55 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ A more detailed feature list includes:

### Converting ES modules (import/export) into sap.ui.define or sap.ui.require

The plugin will wrap any code having import/export statements in an sap.ui.define. If there is no import/export, it won't be wrapped.
The plugin will wrap any code having import/export statements in `sap.ui.define`. If there is no import/export, it won't be wrapped.

#### Static Import

Expand Down Expand Up @@ -341,6 +341,60 @@ sap.ui.define(["./a"], A => {
Also refer to the `neverUseStrict` option below.
### Top-Level Scripts (e.g. QUnit Testsuites)
By default, modules are converted to UI5 AMD-like modules using `sap.ui.define`. In some cases, it is needed to include modules via script tags, such as for QUnit testsuites. Therefore, the Babel plugin supports converting modules into scripts using `sap.ui.require` instead of AMD-like modules using `sap.ui.define`. These modules then can be used as *top-level* scripts which can be included via `<script>` tags in HTML pages.
To mark a module as being converted into such a `sap.ui.require` script, you can either annotate it via the comment: `/* @sapUiRequire */` or in case of QUnit testsuites the Babel plugin autodetects them when it finds the expression `QUnit.config.autostart = false` directly in the program body and `QUnit.start()` nested in the program code.
Example for autodetection:
```js
// https://api.qunitjs.com/config/autostart/
QUnit.config.autostart = false;

// import all your QUnit tests here
void Promise.all([import("unit/controller/App.qunit")]).then(() => {
QUnit.start();
});
```
will be converted to:
```js
"sap.ui.require([], function () {
"use strict";
function __ui5_require_async(path) { /* ... */ }
QUnit.config.autostart = false;
void Promise.all([__ui5_require_async("unit/controller/App.qunit")]).then(() => {
QUnit.start();
});
});
```
Example using the annotation:
```js
/* @sapUiRequire */
import Control from "sap/ui/core/Control";
Control.extend("my.Control", {});
```
will be converted to:
```js
"sap.ui.require(["sap/ui/core/Control"], function (Control) {
"use strict";

Control.extend("my.Control", {});
});
```
> :warning: Although, `sap.ui.define` and `sap.ui.require` look similar from API perspective both have a different behavior. To understand these differences please read the section *Using sap.ui.require instead of sap.ui.define on the top level* in the [Troubleshooting for Loading Modules](https://ui5.sap.com/#/topic/4363b3fe3561414ca1b030afc8cd30ce).
### Converting ES classes into Control.extend(..) syntax
By default, the plugin converts ES classes to `Control.extend(..)` syntax if the class extends from a class which has been imported.
Expand Down
149 changes: 149 additions & 0 deletions packages/plugin/__test__/__snapshots__/test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,154 @@ exports[`preset-env preset-env-usage.js 1`] = `
});"
`;
exports[`sap-ui-require othermodule.js 1`] = `
"sap.ui.require(["sap/ui/core/Control"], function (Control) {
"use strict";
Control.extend("my.Control", {});
});"
`;
exports[`sap-ui-require testsuite.qunit.js 1`] = `
"sap.ui.require([], function () {
"use strict";
function __ui5_require_async(path) {
return new Promise(function (resolve, reject) {
sap.ui.require([path], function (module) {
if (!(module && module.__esModule)) {
module = module === null || !(typeof module === "object" && path.endsWith("/library")) ? {
default: module
} : module;
Object.defineProperty(module, "__esModule", {
value: true
});
}
resolve(module);
}, function (err) {
reject(err);
});
});
}
QUnit.config.autostart = false;
void Promise.all([__ui5_require_async("unit/controller/App.qunit")]).then(() => {
QUnit.start();
});
});"
`;
exports[`sap-ui-require testsuite-annotation.qunit.js 1`] = `
"sap.ui.require([], function () {
"use strict";
function __ui5_require_async(path) {
return new Promise(function (resolve, reject) {
sap.ui.require([path], function (module) {
if (!(module && module.__esModule)) {
module = module === null || !(typeof module === "object" && path.endsWith("/library")) ? {
default: module
} : module;
Object.defineProperty(module, "__esModule", {
value: true
});
}
resolve(module);
}, function (err) {
reject(err);
});
});
}
QUnit.config.autostart = false;
void Promise.all([__ui5_require_async("unit/controller/App.qunit")]).then(() => {
QUnit["start"]();
});
});"
`;
exports[`sap-ui-require testsuite-autodetect.qunit.js 1`] = `
"sap.ui.require([], function () {
"use strict";
function __ui5_require_async(path) {
return new Promise(function (resolve, reject) {
sap.ui.require([path], function (module) {
if (!(module && module.__esModule)) {
module = module === null || !(typeof module === "object" && path.endsWith("/library")) ? {
default: module
} : module;
Object.defineProperty(module, "__esModule", {
value: true
});
}
resolve(module);
}, function (err) {
reject(err);
});
});
}
QUnit.config.autostart = false;
void Promise.all([__ui5_require_async("unit/controller/App.qunit")]).then(() => {
QUnit.start();
});
});"
`;
exports[`sap-ui-require testsuite-defect-1.qunit.js 1`] = `
"sap.ui.define([], function () {
"use strict";
function __ui5_require_async(path) {
return new Promise(function (resolve, reject) {
sap.ui.require([path], function (module) {
if (!(module && module.__esModule)) {
module = module === null || !(typeof module === "object" && path.endsWith("/library")) ? {
default: module
} : module;
Object.defineProperty(module, "__esModule", {
value: true
});
}
resolve(module);
}, function (err) {
reject(err);
});
});
}
QUnit.config._autostart = false;
void Promise.all([__ui5_require_async("unit/controller/App.qunit")]).then(() => {
QUnit.start();
});
});"
`;
exports[`sap-ui-require testsuite-defect-2.qunit.js 1`] = `
"sap.ui.define([], function () {
"use strict";
function __ui5_require_async(path) {
return new Promise(function (resolve, reject) {
sap.ui.require([path], function (module) {
if (!(module && module.__esModule)) {
module = module === null || !(typeof module === "object" && path.endsWith("/library")) ? {
default: module
} : module;
Object.defineProperty(module, "__esModule", {
value: true
});
}
resolve(module);
}, function (err) {
reject(err);
});
});
}
QUnit.config.autostart = false;
void Promise.all([__ui5_require_async("unit/controller/App.qunit")]).then(() => {
QUnit._start();
});
});"
`;
exports[`typescript ts-class-anonymous.ts 1`] = `
"sap.ui.define(["sap/Class"], function (SAPClass) {
"use strict";
Expand Down Expand Up @@ -1680,6 +1828,7 @@ exports[`typescript ts-class-controller-extension-extended.ts 1`] = `
return MyExtendedController;
});"
`;
exports[`typescript ts-class-controller-extension-extended-error-1.ts 1`] = `
"ControllerExtension.use() must be called with exactly one argument but has 0
7 | */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* @sapUiRequire */

import Control from "sap/ui/core/Control";

Control.extend("my.Control", {});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* @sapUiRequire */

// https://api.qunitjs.com/config/autostart/
QUnit.config.autostart = false;

// import all your QUnit tests here
void Promise.all([import("unit/controller/App.qunit")]).then(() => {
QUnit["start"]();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// https://api.qunitjs.com/config/autostart/
QUnit.config.autostart = false;

// import all your QUnit tests here
void Promise.all([import("unit/controller/App.qunit")]).then(() => {
QUnit.start();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// https://api.qunitjs.com/config/autostart/
QUnit.config._autostart = false;

// import all your QUnit tests here
void Promise.all([import("unit/controller/App.qunit")]).then(() => {
QUnit.start();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// https://api.qunitjs.com/config/autostart/
QUnit.config.autostart = false;

// import all your QUnit tests here
void Promise.all([import("unit/controller/App.qunit")]).then(() => {
QUnit._start();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* @sapUiRequire */

// https://api.qunitjs.com/config/autostart/
QUnit.config.autostart = false;

// import all your QUnit tests here
void Promise.all([import("unit/controller/App.qunit")]).then(() => {
QUnit.start();
});
Loading

0 comments on commit ac0078b

Please sign in to comment.