Skip to content

Commit 67b54a5

Browse files
authored
feat: Use Test Starter (#42)
This change introduces the test starter as a replacement for the traditional test suite + test page setup. The feature is only available for application projects starting with UI5 1.124, so the existing test setup is kept for older projects.
1 parent f54ea82 commit 67b54a5

File tree

15 files changed

+222
-26
lines changed

15 files changed

+222
-26
lines changed

generators/app/index.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ import { glob } from "glob";
99
import packageJson from "package-json";
1010
import semver from "semver";
1111
import upath from "upath";
12+
import path from "path";
1213

1314
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
1415

16+
const webappTestDir = path.normalize("webapp/test/");
17+
const webappTestDir_lt1_124 = path.normalize("webapp/test-lt1_124/");
18+
1519
export default class extends Generator {
1620
static displayName = "Create a new UI5 application with TypeScript";
1721
static nestedGenerators = ["wdi5"]; // add wdi5 support
@@ -142,6 +146,7 @@ export default class extends Generator {
142146
this.config.set("gte1_98_0", semver.gte(props.frameworkVersion, "1.98.0"));
143147
this.config.set("gte1_104_0", semver.gte(props.frameworkVersion, "1.104.0"));
144148
this.config.set("gte1_115_0", semver.gte(props.frameworkVersion, "1.115.0"));
149+
this.config.set("lt1_124_0", semver.lt(props.frameworkVersion, "1.124.0"));
145150
});
146151
}
147152

@@ -155,8 +160,21 @@ export default class extends Generator {
155160
nodir: true
156161
})
157162
.forEach((file) => {
163+
let sTargetFile = file;
164+
165+
// Use different "test" folder for older versions
166+
if (file.startsWith(webappTestDir_lt1_124)) {
167+
if (this.config.get("lt1_124_0")) {
168+
sTargetFile = file.replace(webappTestDir_lt1_124, webappTestDir);
169+
} else {
170+
return;
171+
}
172+
} else if (file.startsWith(webappTestDir) && this.config.get("lt1_124_0")) {
173+
return;
174+
}
175+
158176
const sOrigin = this.templatePath(file);
159-
let sTarget = this.destinationPath(file.replace(/^_/, "").replace(/\/_/, "/"));
177+
let sTarget = this.destinationPath(sTargetFile.replace(/^_/, "").replace(/\/_/, "/"));
160178

161179
this.fs.copyTpl(sOrigin, sTarget, oConfig);
162180
});
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import opaTest from "sap/ui/test/opaQunit";
2+
import MainPage from "./pages/MainPage";
3+
4+
const onTheMainPage = new MainPage();
5+
6+
QUnit.module("Sample Hello Journey");
7+
8+
opaTest("Should open the Hello dialog", function () {
9+
// Arrangements
10+
onTheMainPage.iStartMyUIComponent({
11+
componentConfig: {
12+
name: "<%= appId %>"
13+
}
14+
});
15+
16+
// Actions
17+
onTheMainPage.iPressTheSayHelloWithDialogButton();
18+
19+
// Assertions
20+
onTheMainPage.iShouldSeeTheHelloDialog();
21+
22+
// Actions
23+
onTheMainPage.iPressTheOkButtonInTheDialog();
24+
25+
// Assertions
26+
onTheMainPage.iShouldNotSeeTheHelloDialog();
27+
28+
// Cleanup
29+
onTheMainPage.iTeardownMyApp();
30+
});
31+
32+
opaTest("Should close the Hello dialog", function () {
33+
// Arrangements
34+
onTheMainPage.iStartMyUIComponent({
35+
componentConfig: {
36+
name: "<%= appId %>"
37+
}
38+
});
39+
40+
// Actions
41+
onTheMainPage.iPressTheSayHelloWithDialogButton();
42+
onTheMainPage.iPressTheOkButtonInTheDialog();
43+
44+
// Assertions
45+
onTheMainPage.iShouldNotSeeTheHelloDialog();
46+
47+
// Cleanup
48+
onTheMainPage.iTeardownMyApp();
49+
});

generators/app/templates/webapp/test/integration/opaTests.qunit.html renamed to generators/app/templates/webapp/test-lt1_124/integration/opaTests.qunit.html

File renamed without changes.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* @sapUiRequire */
2+
// https://api.qunitjs.com/config/autostart/
3+
QUnit.config.autostart = false;
4+
5+
// import all your OPA journeys here
6+
void Promise.all([import("integration/HelloJourney")]).then(() => {
7+
QUnit.start();
8+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import Opa5 from "sap/ui/test/Opa5";
2+
import Press from "sap/ui/test/actions/Press";
3+
4+
const viewName = "<%= appId %>.view.Main";
5+
6+
export default class MainPage extends Opa5 {
7+
// Actions
8+
iPressTheSayHelloWithDialogButton() {
9+
this.waitFor({
10+
id: "helloButton",
11+
viewName,
12+
actions: new Press(),
13+
errorMessage: "Did not find the 'Say Hello With Dialog' button on the Main view"
14+
});
15+
}
16+
17+
iPressTheOkButtonInTheDialog() {
18+
this.waitFor({
19+
controlType: "sap.m.Button",
20+
searchOpenDialogs: true,
21+
viewName,
22+
actions: new Press(),
23+
errorMessage: "Did not find the 'OK' button in the Dialog"
24+
});
25+
}
26+
27+
// Assertions
28+
iShouldSeeTheHelloDialog() {
29+
this.waitFor({
30+
controlType: "sap.m.Dialog",
31+
success: function () {
32+
// we set the view busy, so we need to query the parent of the app
33+
Opa5.assert.ok(true, "The dialog is open");
34+
},
35+
errorMessage: "Did not find the dialog control"
36+
});
37+
}
38+
39+
iShouldNotSeeTheHelloDialog() {
40+
this.waitFor({
41+
controlType: "sap.m.App", // dummy, I just want a check function, where I can search the DOM. Probably there is a better way for a NEGATIVE test (NO dialog).
42+
check: function () {
43+
return document.querySelectorAll(".sapMDialog").length === 0;
44+
},
45+
success: function () {
46+
Opa5.assert.ok(true, "No dialog is open");
47+
}
48+
});
49+
}
50+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta http-equiv="Cache-control" content="no-cache, no-store, must-revalidate" />
5+
<meta http-equiv="Pragma" content="no-cache" />
6+
<meta http-equiv="expires" content="0" />
7+
<meta charset="utf-8" />
8+
<title>QUnit test suite for the UI5 Application: <%= namespace %></title>
9+
<script src="../resources/sap/ui/qunit/qunit-redirect.js"></script>
10+
<script src="testsuite.qunit.js" data-sap-ui-testsuite></script>
11+
</head>
12+
<body></body>
13+
</html>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* eslint-disable */
2+
// @ts-nocheck
3+
window.suite = function () {
4+
const suite = new parent.jsUnitTestSuite();
5+
const sContextPath = location.pathname.match(/(.*\/)(?:[^/]+)/)?.[1];
6+
suite.addTestPage(sContextPath + "unit/unitTests.qunit.html");
7+
suite.addTestPage(sContextPath + "integration/opaTests.qunit.html");
8+
return suite;
9+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Main from "<%= appURI %>/controller/Main.controller";
2+
3+
QUnit.module("Sample Main controller test");
4+
5+
QUnit.test("The Main controller class has a sayHello method", function (assert) {
6+
// as a very basic test example just check the presence of the "sayHello" method
7+
assert.strictEqual(typeof Main.prototype.sayHello, "function");
8+
});

generators/app/templates/webapp/test/unit/unitTests.qunit.html renamed to generators/app/templates/webapp/test-lt1_124/unit/unitTests.qunit.html

File renamed without changes.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* @sapUiRequire */
2+
// https://api.qunitjs.com/config/autostart/
3+
QUnit.config.autostart = false;
4+
5+
// import all your QUnit tests here
6+
void Promise.all([import("unit/controller/Main.qunit")]).then(() => {
7+
QUnit.start();
8+
});

0 commit comments

Comments
 (0)