Repository: SAP/open-ux-tools
Pull request #3233: fix: Incorrect types package put during adaptation project generation
Author: login: nikmace
Created: 2025-05-08T10:49:47Z | Merged: 2025-05-30T07:00:50Z

Fix for #3198.
- Adds check for `snapshot` & `snapshot-untested` when trying to decide which types package should be used because semver does not recognize both of these versions (it does recognize "1.120.0-snapshot" for example).


Diff:
diff --git a/.changeset/curvy-news-approve.md b/.changeset/curvy-news-approve.md
new file mode 100644
index 00000000000..d2aaed6af77
--- /dev/null
+++ b/.changeset/curvy-news-approve.md
@@ -0,0 +1,6 @@
+---
+'@sap-ux/adp-tooling': patch
+'@sap-ux/ui5-config': patch
+---
+
+fix: Incorrect types package put during adaptation project generation
diff --git a/packages/adp-tooling/src/types.ts b/packages/adp-tooling/src/types.ts
index 55096cf14ff..ded4f78265e 100644
--- a/packages/adp-tooling/src/types.ts
+++ b/packages/adp-tooling/src/types.ts
@@ -150,6 +150,11 @@ export interface VersionDetail {
     lts: boolean;
 }
 
+export interface TypesConfig {
+    typesPackage: string;
+    typesVersion: string;
+}
+
 export interface ResourceModel {
     key: string;
     path: string;
diff --git a/packages/adp-tooling/src/writer/project-utils.ts b/packages/adp-tooling/src/writer/project-utils.ts
index ecb6f59b271..7646624b0fe 100644
--- a/packages/adp-tooling/src/writer/project-utils.ts
+++ b/packages/adp-tooling/src/writer/project-utils.ts
@@ -2,7 +2,7 @@ import { join } from 'path';
 import { readFileSync } from 'fs';
 import { v4 as uuidv4 } from 'uuid';
 import type { Editor } from 'mem-fs-editor';
-import type { CloudApp, AdpWriterConfig, CustomConfig } from '../types';
+import type { CloudApp, AdpWriterConfig, CustomConfig, TypesConfig } from '../types';
 import {
     enhanceUI5DeployYaml,
     enhanceUI5Yaml,
@@ -14,7 +14,7 @@ import {
 
 import type { Package } from '@sap-ux/project-access';
 import type { OperationsType } from '@sap-ux/axios-extension';
-import { UI5Config, getEsmTypesVersion, getTypesPackage } from '@sap-ux/ui5-config';
+import { UI5Config, UI5_DEFAULT, getEsmTypesVersion, getTypesPackage, getTypesVersion } from '@sap-ux/ui5-config';
 
 /**
  * Retrieves the package name and version from the package.json file located two levels up the directory tree.
@@ -34,6 +34,34 @@ export function getPackageJSONInfo(): Package {
     }
 }
 
+/**
+ * Determines the correct TypeScript definitions package and version based on a given UI5 version.
+ *
+ * If the version includes `"snapshot"`, it returns a predefined default types package and version.
+ * Otherwise, it selects the appropriate package and computes the corresponding version using either
+ * `getTypesVersion` or `getEsmTypesVersion`.
+ *
+ * @param {string} [ui5Version] - The version of UI5 (e.g., `"1.108.0"` or `"snapshot"`).
+ * @returns {TypesConfig} - The package name and version string for the UI5 types.
+ */
+export function getTypes(ui5Version?: string): TypesConfig {
+    if (ui5Version?.includes('snapshot')) {
+        return {
+            typesPackage: UI5_DEFAULT.TYPES_PACKAGE_NAME,
+            typesVersion: `~${UI5_DEFAULT.TYPES_VERSION_BEST}`
+        };
+    }
+
+    const typesPackage = getTypesPackage(ui5Version);
+    const isTypesPackage = typesPackage === UI5_DEFAULT.TYPES_PACKAGE_NAME;
+    const typesVersion = isTypesPackage ? getTypesVersion(ui5Version) : getEsmTypesVersion(ui5Version);
+
+    return {
+        typesPackage,
+        typesVersion
+    };
+}
+
 /**
  * Constructs a custom configuration object for the Adaptation Project (ADP).
  *
@@ -71,10 +99,11 @@ export function writeTemplateToFolder(
     data: AdpWriterConfig,
     fs: Editor
 ): void {
+    const ui5Version = data.ui5?.version;
     const tmplPath = join(baseTmplPath, 'project', '**/*.*');
     const tsConfigPath = join(baseTmplPath, 'typescript', 'tsconfig.json');
-    const typesVersion = getEsmTypesVersion(data.ui5?.version);
-    const typesPackage = getTypesPackage(typesVersion);
+
+    const { typesPackage, typesVersion } = getTypes(ui5Version);
 
     try {
         fs.copyTpl(tmplPath, projectPath, { ...data, typesPackage, typesVersion }, undefined, {
diff --git a/packages/adp-tooling/test/unit/writer/project-utils.test.ts b/packages/adp-tooling/test/unit/writer/project-utils.test.ts
index 23972cd5f2c..3c36050133f 100644
--- a/packages/adp-tooling/test/unit/writer/project-utils.test.ts
+++ b/packages/adp-tooling/test/unit/writer/project-utils.test.ts
@@ -2,12 +2,15 @@ import path, { join } from 'path';
 import { readFileSync } from 'fs';
 import type { Editor } from 'mem-fs-editor';
 
+import { getTypesPackage, getTypesVersion, getEsmTypesVersion, UI5_DEFAULT } from '@sap-ux/ui5-config';
+
 import type { AdpWriterConfig } from '../../../src';
 import {
     writeTemplateToFolder,
     writeUI5Yaml,
     writeUI5DeployYaml,
-    getPackageJSONInfo
+    getPackageJSONInfo,
+    getTypes
 } from '../../../src/writer/project-utils';
 
 jest.mock('fs', () => ({
@@ -18,7 +21,17 @@ jest.mock('fs', () => ({
     readFileSync: jest.fn()
 }));
 
+jest.mock('@sap-ux/ui5-config', () => ({
+    ...jest.requireActual('@sap-ux/ui5-config'),
+    getTypesPackage: jest.fn(),
+    getEsmTypesVersion: jest.fn(),
+    getTypesVersion: jest.fn()
+}));
+
 const readFileSyncMock = readFileSync as jest.Mock;
+const mockedGetTypesPackage = getTypesPackage as jest.Mock;
+const mockedGetTypesVersion = getTypesVersion as jest.Mock;
+const mockedGetEsmTypesVersion = getEsmTypesVersion as jest.Mock;
 
 describe('Project Utils', () => {
     const data: AdpWriterConfig = {
@@ -68,9 +81,67 @@ describe('Project Utils', () => {
         });
     });
 
+    describe('getTypes', () => {
+        beforeEach(() => {
+            jest.clearAllMocks();
+        });
+
+        it('should return default types for snapshot version', () => {
+            const result = getTypes('1.137.0-snapshot');
+
+            expect(result).toEqual({
+                typesPackage: UI5_DEFAULT.TYPES_PACKAGE_NAME,
+                typesVersion: `~${UI5_DEFAULT.TYPES_VERSION_BEST}`
+            });
+        });
+
+        it('should return classic types package and version when applicable', () => {
+            mockedGetTypesPackage.mockReturnValue(UI5_DEFAULT.TYPES_PACKAGE_NAME);
+            mockedGetTypesVersion.mockReturnValue('1.108.0');
+
+            const result = getTypes('1.108.0');
+
+            expect(mockedGetTypesPackage).toHaveBeenCalledWith('1.108.0');
+            expect(mockedGetTypesVersion).toHaveBeenCalledWith('1.108.0');
+            expect(result).toEqual({
+                typesPackage: UI5_DEFAULT.TYPES_PACKAGE_NAME,
+                typesVersion: '1.108.0'
+            });
+        });
+
+        it('should return esm types package and version if not default', () => {
+            mockedGetTypesPackage.mockReturnValue('@sapui5/esm-types');
+            mockedGetEsmTypesVersion.mockReturnValue('1.112.1');
+
+            const result = getTypes('1.112.1');
+
+            expect(mockedGetTypesPackage).toHaveBeenCalledWith('1.112.1');
+            expect(mockedGetEsmTypesVersion).toHaveBeenCalledWith('1.112.1');
+            expect(result).toEqual({
+                typesPackage: '@sapui5/esm-types',
+                typesVersion: '1.112.1'
+            });
+        });
+
+        it('should handle undefined version gracefully', () => {
+            mockedGetTypesPackage.mockReturnValue(UI5_DEFAULT.TYPES_PACKAGE_NAME);
+            mockedGetTypesVersion.mockReturnValue('1.136.0');
+
+            const result = getTypes(undefined);
+
+            expect(result).toEqual({
+                typesPackage: UI5_DEFAULT.TYPES_PACKAGE_NAME,
+                typesVersion: '1.136.0'
+            });
+        });
+    });
+
     describe('writeTemplateToFolder', () => {
         beforeEach(() => {
             jest.clearAllMocks();
+
+            mockedGetTypesPackage.mockReturnValue(UI5_DEFAULT.TYPES_PACKAGE_NAME);
+            mockedGetTypesVersion.mockReturnValue('~1.136.0');
         });
 
         const templatePath = '../../../templates';
@@ -87,7 +158,7 @@ describe('Project Utils', () => {
             expect(writeFilesSpy.mock.calls[0][2]).toEqual({
                 ...data,
                 typesPackage: '@sapui5/types',
-                typesVersion: '~1.133.0'
+                typesVersion: '~1.136.0'
             });
         });
 
@@ -100,7 +171,7 @@ describe('Project Utils', () => {
             expect(writeFilesSpy.mock.calls[0][2]).toEqual({
                 ...newData,
                 typesPackage: '@sapui5/types',
-                typesVersion: '~1.133.0'
+                typesVersion: '~1.136.0'
             });
         });
 
diff --git a/packages/ui5-config/src/defaults.ts b/packages/ui5-config/src/defaults.ts
index 57f49b2eac5..4428a27a369 100644
--- a/packages/ui5-config/src/defaults.ts
+++ b/packages/ui5-config/src/defaults.ts
@@ -8,7 +8,7 @@ export const enum UI5_DEFAULT {
     OPENUI5_CDN = 'https://sdk.openui5.org',
     TYPES_VERSION_SINCE = '1.76.0', // eslint-disable-line @typescript-eslint/no-duplicate-enum-values
     ESM_TYPES_VERSION_SINCE = '1.94.0',
-    TYPES_VERSION_BEST = '1.108.0',
+    TYPES_VERSION_BEST = '1.136.0',
     NEW_TYPES_PACKAGE_SINCE = '1.113.0',
     MANIFEST_VERSION = '1.12.0',
     BASE_COMPONENT = 'sap/ui/core/UIComponent',
diff --git a/packages/ui5-config/test/utils.test.ts b/packages/ui5-config/test/utils.test.ts
index 933988c4713..3d3366fc963 100644
--- a/packages/ui5-config/test/utils.test.ts
+++ b/packages/ui5-config/test/utils.test.ts
@@ -83,29 +83,33 @@ describe('getEsmTypesVersion, getTypesVersion, getTypesPackage', () => {
         ['1.109.1', '~1.109.0'],
         ['1.80-snapshot', '~1.80.0'],
         ['1.102-snapshot', '~1.102.0'],
-        ['1.109-snapshot', '~1.109.0']
+        ['1.109-snapshot', '~1.109.0'],
+        ['1.136.0-snapshot', typesVersionBest]
     ];
     const getTypesPackageTestData: [any, string][] = [
         [UI5_DEFAULT.MIN_UI5_VERSION, UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1.70.0', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1.71.1', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
-        ['metadata', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
-        [undefined, UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
+        ['metadata', UI5_DEFAULT.TYPES_PACKAGE_NAME],
+        [undefined, UI5_DEFAULT.TYPES_PACKAGE_NAME],
         // Following versions dont exist
         ['1.72.0', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1.73.0', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1.74.0', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1.75.0', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1.83.0', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
-        [UI5_DEFAULT.TYPES_VERSION_BEST, UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
+        [UI5_DEFAULT.TYPES_VERSION_BEST, UI5_DEFAULT.TYPES_PACKAGE_NAME],
         ['1.109.0', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1.80-snapshot', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1.102-snapshot', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         ['1.109-snapshot', UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME],
         // Following versions should use the new package
         ['1.113.0', UI5_DEFAULT.TYPES_PACKAGE_NAME],
-        ['1.114.0', UI5_DEFAULT.TYPES_PACKAGE_NAME]
+        ['1.114.0', UI5_DEFAULT.TYPES_PACKAGE_NAME],
+        ['snapshot', UI5_DEFAULT.TYPES_PACKAGE_NAME],
+        ['snapshot-untested', UI5_DEFAULT.TYPES_PACKAGE_NAME],
+        ['1.136-snapshot', UI5_DEFAULT.TYPES_PACKAGE_NAME]
     ];
 
     // Tests validation of versions against known versions https://www.npmjs.com/package/@sapui5/ts-types-esm


Reviews:
user: login: nikmace
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T13:33:05Z
user: login: devinea
body: Changes are clear and covered by tests. 
changeset ✅ 
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-05-13T16:03:00Z
user: login: mmilko01
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T08:09:18Z
user: login: nikmace
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T08:11:57Z
user: login: devinea
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-15T13:38:47Z
user: login: mmilko01
body: Changeset OK
Excellent test coverage
Comments addressed
Did not test manually
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-28T11:54:10Z
user: login: devinea
body: Code changes are clear and covered by tests
Changeset ✅ 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-28T13:58:43Z

Review comments:
diff_hunk: @@ -66,6 +66,10 @@ export function getTypesVersion(minUI5Version?: string) {
  * @returns string representing the types package name.
  */
 export function getTypesPackage(ui5Version?: string) {
+    if (ui5Version?.toLowerCase() === 'snapshot' || ui5Version?.toLowerCase() === 'snapshot-untested') {
+        return UI5_DEFAULT.TYPES_PACKAGE_NAME;
+    }
+
     const version = semVer.coerce(ui5Version) ?? semVer.coerce(UI5_DEFAULT.TYPES_VERSION_BEST);
path: packages/ui5-config/src/utils.ts
user: login: nikmace
body: `semver.coerce` does not recognize versions like `snapshot` and `snapshot-untested`.
But it does recognize versions like `1.136.0-snapshot` and parse them to `1.136.0`.

_Another proposal to the one in the PR's changed code_:
**getTypesPackage**: We could check if the version includes a `snapshot` word; if it does, it will default to the TYPES_PACKAGE_NAME - `@sapui5/types` package. 
**getTypesVersion**: We don't have to check explicitly whether the version is `snapshot` because semver will return null and we will get TYPES_VERSION_BEST - 1.108.0.

If we do this change the tests will fail for versions like `1.102-snapshot`, which default to `UI5_DEFAULT.TS_TYPES_ESM_PACKAGE_NAME`. 

As far as I know, such `-snapshot` versions are only available internally and are removed after the version gets released. Therefore, testing UI5 versions lower than 1.113 with `-snapshot` does not make sense, and these tests should be removed from [utils.test.ts]. If you think we should catch such version with `.includes('snapshot')`, then I suggest we remove UI5 versions lower than 1.113 with `-snapshot` and put higher versions with `-snapshot`.

I am also not sure about the use case for this functionality in Fiori Tools, maybe I don't understand something here. What do you think about this @devinea? 
created_at: 2025-05-08T13:33:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -66,6 +66,10 @@ export function getTypesVersion(minUI5Version?: string) {
  * @returns string representing the types package name.
  */
 export function getTypesPackage(ui5Version?: string) {
+    if (ui5Version?.toLowerCase() === 'snapshot' || ui5Version?.toLowerCase() === 'snapshot-untested') {
path: packages/ui5-config/src/utils.ts
user: login: mmilko01
body: Do you think that changing this condition to check whether the version contains `snapshot` would be better? For internal versions we have several different identifiers as `nightly`, `nightly1136`, `monthly`, etc. We usually don't use those in adaptation project, but it might be case we need to use them in the future. 
My proposal is to change the conditions as:
```
ui5Version?.toLowerCase().contains('snapshot')
```
created_at: 2025-05-14T08:02:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -66,6 +66,10 @@ export function getTypesVersion(minUI5Version?: string) {
  * @returns string representing the types package name.
  */
 export function getTypesPackage(ui5Version?: string) {
+    if (ui5Version?.toLowerCase() === 'snapshot' || ui5Version?.toLowerCase() === 'snapshot-untested') {
+        return UI5_DEFAULT.TYPES_PACKAGE_NAME;
+    }
+
     const version = semVer.coerce(ui5Version) ?? semVer.coerce(UI5_DEFAULT.TYPES_VERSION_BEST);
path: packages/ui5-config/src/utils.ts
user: login: nikmace
body: I've proposed the same solution here @mmilko01. 
created_at: 2025-05-14T08:11:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -66,6 +66,10 @@ export function getTypesVersion(minUI5Version?: string) {
  * @returns string representing the types package name.
  */
 export function getTypesPackage(ui5Version?: string) {
+    if (ui5Version?.toLowerCase() === 'snapshot' || ui5Version?.toLowerCase() === 'snapshot-untested') {
path: packages/ui5-config/src/utils.ts
user: login: devinea
body: Yeah that should be ok. There are some snapshots for not the latest ui5 versions (maintenance snapshots if I recall) which may need to be considered. 
created_at: 2025-05-15T13:23:27Z
author_association: MEMBER

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-05-08T10:49:50Z
body: ###  🦋  Changeset detected

Latest commit: 6998316b10e5ee71b65cf3e202709d481e864466

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 53 packages</summary>

  | Name                                        | Type  |
| ------------------------------------------- | ----- |
| @sap-ux/adp-tooling                         | Patch |
| @sap-ux/ui5-config                          | Patch |
| @sap-ux/adp-flp-config-sub-generator        | Patch |
| @sap-ux/create                              | Patch |
| @sap-ux/flp-config-inquirer                 | Patch |
| @sap-ux/generator-adp                       | Patch |
| @sap-ux/preview-middleware                  | Patch |
| @sap-ux/abap-deploy-config-inquirer         | Patch |
| @sap-ux/abap-deploy-config-sub-generator    | Patch |
| @sap-ux/abap-deploy-config-writer           | Patch |
| @sap-ux/app-config-writer                   | Patch |
| @sap-ux/cards-editor-config-writer          | Patch |
| @sap-ux/cf-deploy-config-writer             | Patch |
| @sap-ux/deploy-config-sub-generator         | Patch |
| @sap-ux/deploy-tooling                      | Patch |
| @sap-ux/environment-check                   | Patch |
| @sap-ux/fiori-elements-writer               | Patch |
| @sap-ux/fiori-freestyle-writer              | Patch |
| @sap-ux/launch-config                       | Patch |
| @sap-ux/mockserver-config-writer            | Patch |
| @sap-ux/odata-service-writer                | Patch |
| @sap-ux/project-access                      | Patch |
| @sap-ux/repo-app-import-sub-generator       | Patch |
| @sap-ux/telemetry                           | Patch |
| @sap-ux/ui5-application-writer              | Patch |
| @sap-ux/ui5-library-reference-writer        | Patch |
| @sap-ux/ui5-library-writer                  | Patch |
| @sap-ux/ui5-proxy-middleware                | Patch |
| @sap-ux/flp-config-sub-generator            | Patch |
| @sap-ux/fiori-app-sub-generator             | Patch |
| @sap-ux/ui-service-inquirer                 | Patch |
| @sap-ux/cf-deploy-config-sub-generator      | Patch |
| @sap-ux/odata-service-inquirer              | Patch |
| @sap-ux/generator-simple-fe                 | Patch |
| @sap-ux/annotation-generator                | Patch |
| @sap-ux/cap-config-writer                   | Patch |
| @sap-ux/cards-editor-middleware             | Patch |
| @sap-ux/fe-fpm-writer                       | Patch |
| @sap-ux/fiori-annotation-api                | Patch |
| @sap-ux/fiori-generator-shared              | Patch |
| @sap-ux/project-input-validator             | Patch |
| @sap-ux/project-integrity                   | Patch |
| @sap-ux/ui5-application-inquirer            | Patch |
| @sap-ux/ui5-library-reference-inquirer      | Patch |
| @sap-ux/ui5-library-reference-sub-generator | Patch |
| @sap-ux/ui5-test-writer                     | Patch |
| @sap-ux/inquirer-common                     | Patch |
| @sap-ux/ui-service-sub-generator            | Patch |
| @sap-ux/ui5-library-sub-generator           | Patch |
| @sap-ux/fe-fpm-cli                          | Patch |
| @sap-ux/deploy-config-generator-shared      | Patch |
| @sap-ux/ui5-library-inquirer                | Patch |
| @sap-ux/cf-deploy-config-inquirer           | Patch |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/SAP/open-ux-tools/new/fix/3198/incorrect-types-package?filename=.changeset/two-fans-remain.md&value=---%0A%22%40sap-ux%2Fadp-tooling%22%3A%20patch%0A%22%40sap-ux%2Fui5-config%22%3A%20patch%0A---%0A%0Afix%3A%20Incorrect%20types%20package%20put%20during%20adaptation%20project%20generation%0A)


author_association: NONE
user: login: sonarqubecloud[bot]
created_at: 2025-05-30T06:57:18Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=SAP_open-ux-tools&pullRequest=3233) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=SAP_open-ux-tools&pullRequest=3233&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=SAP_open-ux-tools&pullRequest=3233&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=SAP_open-ux-tools&pullRequest=3233&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=SAP_open-ux-tools&pullRequest=3233&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=SAP_open-ux-tools&pullRequest=3233&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=SAP_open-ux-tools&pullRequest=3233)


author_association: NONE