From 22c61f51647f397784f5a66ddfa63031fe96aac8 Mon Sep 17 00:00:00 2001 From: Andreas Kunz Date: Fri, 21 Apr 2023 18:40:12 +0200 Subject: [PATCH 01/15] Adapt to "ts-types-esm" -> "types" renaming --- README.md | 4 ++-- step-by-step.md | 18 ++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 763a127f..5b5998bc 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,10 @@ As the focus is on the TypeScript setup, the app code itself is quite minimal, i | :point_up: Overview of TypeScript-related Entities | |:---------------------------| -| The UI5 type definitions (`*.d.ts` files) are loaded as dev dependency from [npm](https://www.npmjs.com/package/@openui5/ts-types-esm). They are a work in progress, so while they should be working well already, we are still improving them, which might also lead to breaking changes.
+| The UI5 type definitions (`*.d.ts` files) are loaded as dev dependency from [npm](https://www.npmjs.com/package/@types/openui5). They are a work in progress, so while they should be working well already, we are still improving them, which might also lead to breaking changes.
The file [tsconfig.json](tsconfig.json) contains the configuration for the TypeScript compilation, including a reference to the UI5 `*.d.ts` files.
Normally, the UI5 JavaScript files (controllers, Component.js etc.) would reside in the `webapp` folder. Now they are in the [src](src) folder. The TypeScript compilation will create the `webapp` folder and put all output there.
- In addition to the TypeScript compilation, there is also a conversion from the ES6 module and class syntax used in the source files to the classic UI5 module loading and class definition syntax (`sap.ui.define(...)` and `superClass.extend(...)`). This conversion is using the [babel-plugin-transform-modules-ui5](https://github.com/r-murphy/babel-plugin-transform-modules-ui5) project from Ryan Murphy.
+ In addition to the TypeScript compilation, there is also a conversion from the ES6 module and class syntax used in the source files to the classic UI5 module loading and class definition syntax (`sap.ui.define(...)` and `superClass.extend(...)`). This conversion is using the [babel-plugin-transform-modules-ui5](https://github.com/ui5-community/babel-plugin-transform-modules-ui5) project from the UI5 Community (initially developed by Ryan Murphy).
Both, the TypeScript compilation and the ES6 syntax transformation, are executed by Babel, as configured in the file [.babelrc.json](.babelrc.json)
This combined transformation is triggered by both the `build:ts` and `watch:ts` scripts in [package.json](package.json). | diff --git a/step-by-step.md b/step-by-step.md index d6dca711..9d917f8c 100644 --- a/step-by-step.md +++ b/step-by-step.md @@ -74,11 +74,11 @@ Now, let's get the TypeScript compiler and the UI5 type definitions: npm install --save-dev typescript @types/openui5@1.112.0 ``` -When you are developing a SAPUI5 application (i.e. also using control libraries which are not available in OpenUI5), use the `@sapui5/ts-types-esm` types instead of the `@types/openui5` ones. +When you are developing a SAPUI5 application (i.e. also using control libraries which are not available in OpenUI5), use the `@sapui5/types` types instead of the `@types/openui5` ones. -> **Remark:** There are also `@openui5/ts-types-esm` types available - how do they differ from the `@types/openui5` ones?
-The one difference is in versioning: while the types in the `@openui5` namespace are exactly in sync with the respective OpenUI5 patch release, the ones in the `@types` namespace follow the DefinitelyTyped versioning and are only released *once* per minor release of OpenUI5 ([more details here](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/openui5#versioning)), not for every patch. In practice it shouldn't make any difference what you use, but note that in the `@types` namespace there is usually only the `*.*.0` patch release available.
-The other small difference is [described in detail here](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/openui5#jquery-and-qunit-references-and-their-versions). In essence, UI5 declares the jQuery and QUnit types as dependencies to make sure the type definitions are also loaded because types from those libraries are in some places exposed in UI5 APIs. The difference is that for `@types/openui5` the *latest* version of those types is referenced and for `@openui5/ts-types-esm` the *best matching* version is referenced. But in practice also this difference should not be something to worry about. To enforce using a specific version of the jQuery/QUnit types with the `@types/openui5` type definitions, you can always do e.g.: +> **Remark:** There are also `@openui5/types` types available - how do they differ from the `@types/openui5` ones?
+The content is basically the same, one difference is in versioning: while the types in the `@openui5` namespace are exactly in sync with the respective OpenUI5 patch release, the ones in the `@types` namespace follow the DefinitelyTyped versioning and are only released *once* per minor release of OpenUI5 ([more details here](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/openui5#versioning)), not for every patch. In practice it shouldn't make any difference what you use, but note that in the `@types` namespace there is usually only the `*.*.0` patch release available.
+The other small difference is [described in detail here](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/openui5#jquery-and-qunit-references-and-their-versions). In essence, UI5 declares the jQuery and QUnit types as dependencies to make sure the type definitions are also loaded because types from those libraries are in some places exposed in UI5 APIs. The difference is that for `@types/openui5` the *latest* version of those types is referenced and for `@openui5/types` the *best matching* version is referenced. But in practice also this difference should not be something to worry about. To enforce using a specific version of the jQuery/QUnit types with the `@types/openui5` type definitions, you can always do e.g.: > ```sh > npm install --save-dev @types/jquery@3.5.9 @types/qunit@2.5.4 > ``` @@ -120,18 +120,16 @@ So we need to add a `tsconfig.json` configuration file to configure the right la } ``` -> **Note:** when you use the `@sapui5/ts-types-esm` (or `@openui5/ts-types-esm`) types instead, you need to add the following section to tsconfig.json: +> **Note:** when you use the `@sapui5/types` (or `@openui5/types`) types instead, you need to add the following section to tsconfig.json: > > ```json > "typeRoots": [ -> "./node_modules/@types" -> ], -> "types": [ -> "@sapui5/ts-types-esm" +> "./node_modules/@types", +> "./node_modules/@sapui5/types" > ], >``` > -> Why? TypeScript automatically finds all type definition files in a dependency starting with `@types/...` (i.e. all `.d.ts` files in `node_modules/@types/...`). The jQuery d.ts files are there and found, but the SAPUI5 types are only available in a package starting with `@sapui5/...`, hence TypeScript must be explicitly pointed to these types. As this disables the automatic loading of other types from `node_modules/@types/...`, this path must be given as a type root. +> Why? TypeScript automatically finds all type definition files in a dependency starting with `@types/...` (i.e. all `.d.ts` files in `node_modules/@types/...`). The jQuery d.ts files are there and found, but the SAPUI5 types are only available in a package starting with `@sapui5/...`, hence TypeScript must be explicitly pointed to these types. As this disables the automatic loading of other types from `node_modules/@types/...`, this path must also be given as a type root. There are additional settings in this file, e.g. telling the compiler which files to compile (all matching `./webapp/**/*`) and how the modules should be resolved (`"moduleResolution": "node"`). And a couple of compiler options which are not so important right now. They determine how exactly the compiler behaves. The "paths" section informs TypeScript about the mapping of namespaces used in the app. From c5d4fce063ffea9df700d06176d3bf53e4e0f0de Mon Sep 17 00:00:00 2001 From: Peter Muessig Date: Wed, 9 Aug 2023 13:59:20 +0200 Subject: [PATCH 02/15] Update dependencies (incl. UI5 1.116.0 / DT Types 1.116.1) --- package.json | 18 +++++++++--------- ui5-dist.yaml | 2 +- ui5.yaml | 2 +- webapp/Component.ts | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 04204f7d..fa43d060 100644 --- a/package.json +++ b/package.json @@ -17,14 +17,14 @@ "url": "https://github.com/SAP-samples/ui5-typescript-helloworld.git" }, "devDependencies": { - "@types/openui5": "1.112.0", - "@typescript-eslint/eslint-plugin": "^5.57.1", - "@typescript-eslint/parser": "^5.57.1", - "@ui5/cli": "^3.0.6", - "eslint": "^8.37.0", - "typescript": "^5.0.3", - "ui5-middleware-livereload": "^0.8.2", - "ui5-middleware-simpleproxy": "^0.9.5", - "ui5-tooling-transpile": "^0.7.0" + "@types/openui5": "1.116.1", + "@typescript-eslint/eslint-plugin": "^6.3.0", + "@typescript-eslint/parser": "^6.3.0", + "@ui5/cli": "^3.4.0", + "eslint": "^8.46.0", + "typescript": "^5.1.6", + "ui5-middleware-livereload": "^3.0.0", + "ui5-middleware-simpleproxy": "^3.0.0", + "ui5-tooling-transpile": "^3.0.1" } } diff --git a/ui5-dist.yaml b/ui5-dist.yaml index c89aed53..64d22b0c 100644 --- a/ui5-dist.yaml +++ b/ui5-dist.yaml @@ -8,7 +8,7 @@ resources: webapp: dist framework: name: OpenUI5 - version: "1.112.0" + version: "1.116.0" libraries: - name: sap.m - name: sap.ui.core diff --git a/ui5.yaml b/ui5.yaml index df5ceaf3..17739c0c 100644 --- a/ui5.yaml +++ b/ui5.yaml @@ -4,7 +4,7 @@ metadata: type: application framework: name: OpenUI5 - version: "1.112.0" + version: "1.116.0" libraries: - name: sap.m - name: sap.ui.core diff --git a/webapp/Component.ts b/webapp/Component.ts index f233d41b..8da254cb 100644 --- a/webapp/Component.ts +++ b/webapp/Component.ts @@ -1,5 +1,5 @@ import UIComponent from "sap/ui/core/UIComponent"; -import { support } from "sap/ui/Device"; +import Device from "sap/ui/Device"; /** @@ -30,7 +30,7 @@ export default class Component extends UIComponent { // check whether FLP has already set the content density class; do nothing in this case if (document.body.classList.contains("sapUiSizeCozy") || document.body.classList.contains("sapUiSizeCompact")) { this.contentDensityClass = ""; - } else if (!support.touch) { // apply "compact" mode if touch is not supported + } else if (!Device.support.touch) { // apply "compact" mode if touch is not supported this.contentDensityClass = "sapUiSizeCompact"; } else { // "cozy" in case of touch support; default for most sap.m controls, but needed for desktop-first controls like sap.ui.table.Table From 8cbf86f0c63d4c1e8ddcee0144daf7cda3223924 Mon Sep 17 00:00:00 2001 From: Volker Buzek Date: Fri, 1 Sep 2023 10:51:46 +0200 Subject: [PATCH 03/15] chore(deps): wdi5 related --- package.json | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 494a4227..53f8d1e4 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "karma": "karma start", "karma-ci": "karma start karma-ci.conf.js", "karma-ci-cov": "karma start karma-ci-cov.conf.js", - "test": "npm run lint && npm run karma-ci-cov" + "test": "npm run lint && npm run karma-ci-cov", + "wdi5": "wdio run ./webapp/test/e2e/wdio.conf.ts" }, "repository": { "type": "git", @@ -26,6 +27,10 @@ "@typescript-eslint/eslint-plugin": "^6.3.0", "@typescript-eslint/parser": "^6.3.0", "@ui5/cli": "^3.4.0", + "@wdio/cli": "^8", + "@wdio/local-runner": "^8", + "@wdio/mocha-framework": "^8", + "@wdio/spec-reporter": "^8", "eslint": "^8.46.0", "karma": "^6.4.2", "karma-chrome-launcher": "^3.2.0", @@ -33,8 +38,9 @@ "karma-ui5": "^3.0.3", "karma-ui5-transpile": "^3.0.1", "rimraf": "^5.0.1", - "typescript": "^5.1.6", + "ts-node": "^10.9.1", "ui5-middleware-livereload": "^3.0.0", - "ui5-tooling-transpile": "^3.0.1" + "ui5-tooling-transpile": "^3.0.1", + "wdio-ui5-service": "^2" } } From 02e2a490c184124c56f69aae660b9f5e0204c436 Mon Sep 17 00:00:00 2001 From: Volker Buzek Date: Fri, 1 Sep 2023 10:55:19 +0200 Subject: [PATCH 04/15] chore(eslint): extend with wdi5 ts flavor --- .eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 9d72951d..05d82373 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -11,7 +11,7 @@ ], "parser": "@typescript-eslint/parser", "parserOptions": { - "project": ["./tsconfig.json"], + "project": ["./tsconfig.json", "./webapp/test/e2e/tsconfig.json"], "sourceType": "module" }, "plugins": [ From 075d60403369455b796e36974061d161962a8d52 Mon Sep 17 00:00:00 2001 From: Volker Buzek Date: Fri, 1 Sep 2023 10:55:37 +0200 Subject: [PATCH 05/15] feat(wdi5): add mvp artifacts --- webapp/test/e2e/sample.test.ts | 24 +++ webapp/test/e2e/tsconfig.json | 7 + webapp/test/e2e/wdio.conf.ts | 337 +++++++++++++++++++++++++++++++++ 3 files changed, 368 insertions(+) create mode 100644 webapp/test/e2e/sample.test.ts create mode 100644 webapp/test/e2e/tsconfig.json create mode 100644 webapp/test/e2e/wdio.conf.ts diff --git a/webapp/test/e2e/sample.test.ts b/webapp/test/e2e/sample.test.ts new file mode 100644 index 00000000..fd9809af --- /dev/null +++ b/webapp/test/e2e/sample.test.ts @@ -0,0 +1,24 @@ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +import { wdi5 } from "wdio-ui5-service" + +describe("samples", () => { + it("should log", () => { + const logger = wdi5.getLogger() + logger.log("hello world!") + }) + + // intentionally skipping this as you have to adjust things to your UI5 app :) + it.skip("should retrieve a UI5 control", async () => { + const appLocator = { + selector: { + controlType: "sap.m.App", + viewName: "ui5.typescript.helloworld.view.App" + } + } + + const app = await browser.asControl(appLocator) + expect(app).toBeDefined() + }) +}) diff --git a/webapp/test/e2e/tsconfig.json b/webapp/test/e2e/tsconfig.json new file mode 100644 index 00000000..c129222f --- /dev/null +++ b/webapp/test/e2e/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "types": ["node", "@openui5/types", "@wdio/globals/types", "@wdio/mocha-framework", "wdio-ui5-service/esm"], + "target": "es2019" + } +} diff --git a/webapp/test/e2e/wdio.conf.ts b/webapp/test/e2e/wdio.conf.ts new file mode 100644 index 00000000..4b172aaf --- /dev/null +++ b/webapp/test/e2e/wdio.conf.ts @@ -0,0 +1,337 @@ +import { wdi5Config } from "wdio-ui5-service" + +export const config: wdi5Config = { + // ==================== + // wdi5 Configuration + // ==================== + // + // wdi5: { + // screenshotPath: require("path").join("some", "dir", "for", "screenshots"),c // [optional] {string}, default: "" + // screenshotsDisabled: false, // [optional] {boolean}, default: false; if set to true, screenshots won't be taken and not written to file system + // logLevel: "error", // [optional] error | verbose | silent, default: "error" + // skipInjectUI5OnStart: false, // [optional] {boolean}, default: false; true when UI5 is not on the start page, you need to later call .injectUI5() manually + // waitForUI5Timeout: 15000 // [optional] {number}, default: 15000; maximum waiting time in milliseconds while checking for UI5 availability + // btpWorkZoneEnablement: false // [optional] {boolean}, default: false; whether to instruct wdi5 to inject itself in both the SAP Build Workzone, standard edition, shell and app + // }, + // + // ==================== + // Runner Configuration + // ==================== + // + // + // ===================== + // ts-node Configurations + // ===================== + // + // You can write tests using TypeScript to get autocompletion and type safety. + // You will need typescript and ts-node installed as devDependencies. + // WebdriverIO will automatically detect if these dependencies are installed + // and will compile your config and tests for you. + // If you need to configure how ts-node runs please use the + // environment variables for ts-node or use wdio config's autoCompileOpts section. + // + + autoCompileOpts: { + autoCompile: true + // see https://github.com/TypeStrong/ts-node#cli-and-programmatic-options + // for all available options + // tsNodeOpts: { + // transpileOnly: true, + // project: "./test/tsconfig.json" + // } + // tsconfig-paths is only used if "tsConfigPathsOpts" are provided, if you + // do please make sure "tsconfig-paths" is installed as dependency + // tsConfigPathsOpts: { + // baseUrl: './' + // } + }, + // + // ================== + // Specify Test Files + // ================== + // Define which test specs should run. The pattern is relative to the directory + // from which `wdio` was called. + // + // The specs are defined as an array of spec files (optionally using wildcards + // that will be expanded). The test for each spec file will be run in a separate + // worker process. In order to have a group of spec files run in the same worker + // process simply enclose them in an array within the specs array. + // + // If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script), + // then the current working directory is where your `package.json` resides, so `wdio` + // will be called from there. + // + specs: ["./**/*.test.ts"], + // Patterns to exclude. + exclude: [ + // 'path/to/excluded/files' + ], + // + // ============ + // Capabilities + // ============ + // Define your capabilities here. WebdriverIO can run multiple capabilities at the same + // time. Depending on the number of capabilities, WebdriverIO launches several test + // sessions. Within your capabilities you can overwrite the spec and exclude options in + // order to group specific specs to a specific capability. + // + // First, you can define how many instances should be started at the same time. Let's + // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have + // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec + // files and you set maxInstances to 10, all spec files will get tested at the same time + // and 30 processes will get spawned. The property handles how many capabilities + // from the same test should run tests. + // + maxInstances: 10, + // + // If you have trouble getting all important capabilities together, check out the + // Sauce Labs platform configurator - a great tool to configure your capabilities: + // https://saucelabs.com/platform/platform-configurator + // + capabilities: [ + { + // maxInstances can get overwritten per capability. So if you have an in-house Selenium + // grid with only 5 firefox instances available you can make sure that not more than + // 5 instances get started at a time. + maxInstances: 5, + browserName: "chrome", + "goog:chromeOptions": { + args: + process.argv.indexOf("--headless") > -1 + ? ["--headless"] + : process.argv.indexOf("--debug") > -1 + ? ["window-size=1440,800", "--auto-open-devtools-for-tabs"] + : ["window-size=1440,800"] + }, + acceptInsecureCerts: true + // If outputDir is provided WebdriverIO can capture driver session logs + // it is possible to configure which logTypes to include/exclude. + // excludeDriverLogs: ['*'], // pass '*' to exclude all driver session logs + // excludeDriverLogs: ['bugreport', 'server'], + } + ], + // + // =================== + // Test Configurations + // =================== + // Define all options that are relevant for the WebdriverIO instance here + // + // Level of logging verbosity: trace | debug | info | warn | error | silent + logLevel: "error", + // + // Set specific log levels per logger + // loggers: + // - webdriver, webdriverio + // - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service + // - @wdio/mocha-framework, @wdio/jasmine-framework + // - @wdio/local-runner + // - @wdio/sumologic-reporter + // - @wdio/cli, @wdio/config, @wdio/utils + // Level of logging verbosity: trace | debug | info | warn | error | silent + // logLevels: { + // webdriver: 'info', + // '@wdio/appium-service': 'info' + // }, + // + // If you only want to run your tests until a specific amount of tests have failed use + // bail (default is 0 - don't bail, run all tests). + bail: 0, + // + // Set a base URL in order to shorten url command calls. If your `url` parameter starts + // with `/`, the base url gets prepended, not including the path portion of your baseUrl. + // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url + // gets prepended directly. + baseUrl: "http://localhost:8080/index.html", + // + // Default timeout for all waitFor* commands. + waitforTimeout: 10000, + // + // Default timeout in milliseconds for request + // if browser driver or grid doesn't send response + connectionRetryTimeout: process.argv.indexOf("--debug") > -1 ? 1200000 : 120000, + // + // Default request retries count + connectionRetryCount: 3, + // + // Test runner services + // Services take over a specific job you don't want to take care of. They enhance + // your test setup with almost no effort. Unlike plugins, they don't add new + // commands. Instead, they hook themselves up into the test process. + services: ["ui5"], + + // Framework you want to run your specs with. + // The following are supported: Mocha, Jasmine, and Cucumber + // see also: https://webdriver.io/docs/frameworks + // + // Make sure you have the wdio adapter package for the specific framework installed + // before running any tests. + framework: "mocha", + // + // The number of times to retry the entire specfile when it fails as a whole + // specFileRetries: 1, + // + // Delay in seconds between the spec file retry attempts + // specFileRetriesDelay: 0, + // + // Whether or not retried specfiles should be retried immediately or deferred to the end of the queue + // specFileRetriesDeferred: false, + // + // Test reporter for stdout. + // The only one supported by default is 'dot' + // see also: https://webdriver.io/docs/dot-reporter + reporters: ["spec"], + + // + // Options to be passed to Mocha. + // See the full list at http://mochajs.org/ + mochaOpts: { + ui: "bdd", + timeout: process.argv.indexOf("--debug") > -1 ? 600000 : 60000 + } + // + // ===== + // Hooks + // ===== + // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance + // it and to build services around it. You can either apply a single function or an array of + // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got + // resolved to continue. + /** + * Gets executed once before all workers get launched. + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + */ + // onPrepare: function (config, capabilities) { + // }, + /** + * Gets executed before a worker process is spawned and can be used to initialise specific service + * for that worker as well as modify runtime environments in an async fashion. + * @param {String} cid capability id (e.g 0-0) + * @param {[type]} caps object containing capabilities for session that will be spawn in the worker + * @param {[type]} specs specs to be run in the worker process + * @param {[type]} args object that will be merged with the main configuration once worker is initialized + * @param {[type]} execArgv list of string arguments passed to the worker process + */ + // onWorkerStart: function (cid, caps, specs, args, execArgv) { + // }, + /** + * Gets executed just after a worker process has exited. + * @param {String} cid capability id (e.g 0-0) + * @param {Number} exitCode 0 - success, 1 - fail + * @param {[type]} specs specs to be run in the worker process + * @param {Number} retries number of retries used + */ + // onWorkerEnd: function (cid, exitCode, specs, retries) { + // }, + /** + * Gets executed just before initialising the webdriver session and test framework. It allows you + * to manipulate configurations depending on the capability or spec. + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that are to be run + * @param {String} cid worker id (e.g. 0-0) + */ + // beforeSession: function (config, capabilities, specs, cid) { + // }, + /** + * Gets executed before test execution begins. At this point you can access to all global + * variables like `browser`. It is the perfect place to define custom commands. + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that are to be run + * @param {Object} browser instance of created browser/device session + */ + // before: function (capabilities, specs) { + // }, + /** + * Runs before a WebdriverIO command gets executed. + * @param {String} commandName hook command name + * @param {Array} args arguments that command would receive + */ + // beforeCommand: function (commandName, args) { + // }, + /** + * Hook that gets executed before the suite starts + * @param {Object} suite suite details + */ + // beforeSuite: function (suite) { + // }, + /** + * Function to be executed before a test (in Mocha/Jasmine) starts. + */ + // beforeTest: function (test, context) { + // }, + /** + * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling + * beforeEach in Mocha) + */ + // beforeHook: function (test, context) { + // }, + /** + * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling + * afterEach in Mocha) + */ + // afterHook: function (test, context, { error, result, duration, passed, retries }) { + // }, + /** + * Function to be executed after a test (in Mocha/Jasmine only) + * @param {Object} test test object + * @param {Object} context scope object the test was executed with + * @param {Error} result.error error object in case the test fails, otherwise `undefined` + * @param {Any} result.result return object of test function + * @param {Number} result.duration duration of test + * @param {Boolean} result.passed true if test has passed, otherwise false + * @param {Object} result.retries informations to spec related retries, e.g. `{ attempts: 0, limit: 0 }` + */ + // afterTest: function(test, context, { error, result, duration, passed, retries }) { + // }, + + /** + * Hook that gets executed after the suite has ended + * @param {Object} suite suite details + */ + // afterSuite: function (suite) { + // }, + /** + * Runs after a WebdriverIO command gets executed + * @param {String} commandName hook command name + * @param {Array} args arguments that command would receive + * @param {Number} result 0 - command success, 1 - command error + * @param {Object} error error object if any + */ + // afterCommand: function (commandName, args, result, error) { + // }, + /** + * Gets executed after all tests are done. You still have access to all global variables from + * the test. + * @param {Number} result 0 - test pass, 1 - test fail + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that ran + */ + // after: function (result, capabilities, specs) { + // }, + /** + * Gets executed right after terminating the webdriver session. + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that ran + */ + // afterSession: function (config, capabilities, specs) { + // }, + /** + * Gets executed after all workers got shut down and the process is about to exit. An error + * thrown in the onComplete hook will result in the test run failing. + * @param {Object} exitCode 0 - success, 1 - fail + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {} results object containing test results + */ + // onComplete: function(exitCode, config, capabilities, results) { + // }, + /** + * Gets executed when a refresh happens. + * @param {String} oldSessionId session ID of the old session + * @param {String} newSessionId session ID of the new session + */ + // onReload: function(oldSessionId, newSessionId) { + // } +} From 8d7a79dedec89a69386e87f495af0d037a8c1506 Mon Sep 17 00:00:00 2001 From: Volker Buzek Date: Fri, 1 Sep 2023 11:06:52 +0200 Subject: [PATCH 06/15] chore(deps): bump --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 53f8d1e4..4a500276 100644 --- a/package.json +++ b/package.json @@ -24,23 +24,23 @@ }, "devDependencies": { "@types/openui5": "1.116.1", - "@typescript-eslint/eslint-plugin": "^6.3.0", - "@typescript-eslint/parser": "^6.3.0", - "@ui5/cli": "^3.4.0", + "@typescript-eslint/eslint-plugin": "^6.5.0", + "@typescript-eslint/parser": "^6.5.0", + "@ui5/cli": "^3.5.0", "@wdio/cli": "^8", "@wdio/local-runner": "^8", "@wdio/mocha-framework": "^8", "@wdio/spec-reporter": "^8", - "eslint": "^8.46.0", + "eslint": "^8.48.0", "karma": "^6.4.2", "karma-chrome-launcher": "^3.2.0", "karma-coverage": "^2.2.1", "karma-ui5": "^3.0.3", - "karma-ui5-transpile": "^3.0.1", + "karma-ui5-transpile": "^3.2.0", "rimraf": "^5.0.1", "ts-node": "^10.9.1", "ui5-middleware-livereload": "^3.0.0", - "ui5-tooling-transpile": "^3.0.1", + "ui5-tooling-transpile": "^3.2.0", "wdio-ui5-service": "^2" } } From 6149c8bb61d7faa3e155217eb23a220b5af42070 Mon Sep 17 00:00:00 2001 From: Volker Buzek Date: Mon, 18 Sep 2023 10:18:52 +0200 Subject: [PATCH 07/15] chore(deps): bump --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 4a500276..0f5538b5 100644 --- a/package.json +++ b/package.json @@ -24,23 +24,23 @@ }, "devDependencies": { "@types/openui5": "1.116.1", - "@typescript-eslint/eslint-plugin": "^6.5.0", - "@typescript-eslint/parser": "^6.5.0", - "@ui5/cli": "^3.5.0", + "@typescript-eslint/eslint-plugin": "^6.7.0", + "@typescript-eslint/parser": "^6.7.0", + "@ui5/cli": "^3.6.0", "@wdio/cli": "^8", "@wdio/local-runner": "^8", "@wdio/mocha-framework": "^8", "@wdio/spec-reporter": "^8", - "eslint": "^8.48.0", + "eslint": "^8.49.0", "karma": "^6.4.2", "karma-chrome-launcher": "^3.2.0", "karma-coverage": "^2.2.1", "karma-ui5": "^3.0.3", - "karma-ui5-transpile": "^3.2.0", + "karma-ui5-transpile": "^3.2.3", "rimraf": "^5.0.1", "ts-node": "^10.9.1", "ui5-middleware-livereload": "^3.0.0", - "ui5-tooling-transpile": "^3.2.0", + "ui5-tooling-transpile": "^3.2.3", "wdio-ui5-service": "^2" } } From b69cfbc8d67b200e28b1c388739255d3d5ddd622 Mon Sep 17 00:00:00 2001 From: Volker Buzek Date: Mon, 18 Sep 2023 10:50:38 +0200 Subject: [PATCH 08/15] feat: wdi5 test ~ opa5 test journey --- webapp/test/e2e/dialog.test.ts | 17 +++++++++++++++++ webapp/test/e2e/pages/AppPage.ts | 31 +++++++++++++++++++++++++++++++ webapp/test/e2e/pages/locators.ts | 25 +++++++++++++++++++++++++ webapp/test/e2e/sample.test.ts | 24 ------------------------ 4 files changed, 73 insertions(+), 24 deletions(-) create mode 100644 webapp/test/e2e/dialog.test.ts create mode 100644 webapp/test/e2e/pages/AppPage.ts create mode 100644 webapp/test/e2e/pages/locators.ts delete mode 100644 webapp/test/e2e/sample.test.ts diff --git a/webapp/test/e2e/dialog.test.ts b/webapp/test/e2e/dialog.test.ts new file mode 100644 index 00000000..c12c1948 --- /dev/null +++ b/webapp/test/e2e/dialog.test.ts @@ -0,0 +1,17 @@ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +import AppPage from "./pages/AppPage" + +describe("Hello!", () => { + it("Should open the Hello dialog", async () => { + await AppPage.iPressTheSayHelloWithDialogButton() + const dialogVisible = await AppPage.iShouldSeeTheHelloDialog() + expect(dialogVisible).toBeTruthy() + }) + + it("Should close the Hello dialog", async () => { + await AppPage.iPressTheOkButtonInTheDialog() + const dialogNotVisible = await AppPage.iShouldNotSeeTheHelloDialog() + expect(dialogNotVisible).toBeTruthy() + }) +}) diff --git a/webapp/test/e2e/pages/AppPage.ts b/webapp/test/e2e/pages/AppPage.ts new file mode 100644 index 00000000..a956b837 --- /dev/null +++ b/webapp/test/e2e/pages/AppPage.ts @@ -0,0 +1,31 @@ +/* eslint-disable @typescript-eslint/no-unsafe-return */ +/* eslint-disable @typescript-eslint/no-unsafe-call */ +/* eslint-disable @typescript-eslint/no-unsafe-member-access */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ +import Button from "sap/m/Button" +import MessageBox from "sap/m/MessageBox" + +import { buttonLocator, dialogLocator, OKButtonLocator } from "./locators" + +class AppPage { + async iPressTheSayHelloWithDialogButton() { + const button = await browser.asControl