From 619457f540eb00145f4d8f89f6be409d75301215 Mon Sep 17 00:00:00 2001 From: Max Reichmann <91143102+maxreichmann@users.noreply.github.com> Date: Fri, 8 Nov 2024 14:59:22 +0100 Subject: [PATCH] feat(Test Starter): Detect deprecations in 'theme' property of test configuration (#387) JIRA: CPOUI5FOUNDATION-844 --- src/linter/ui5Types/SourceFileLinter.ts | 54 ++++++++ .../rules/NoDeprecatedApi/testsuite.qunit.js | 34 +++++ .../rules/NoDeprecatedApi/testsuite.qunit.ts | 36 ++++++ .../rules/NoDeprecatedApi/testsuite2.qunit.js | 34 +++++ .../rules/snapshots/NoDeprecatedApi.ts.md | 120 ++++++++++++++++++ .../rules/snapshots/NoDeprecatedApi.ts.snap | Bin 15986 -> 16324 bytes 6 files changed, 278 insertions(+) create mode 100644 test/fixtures/linter/rules/NoDeprecatedApi/testsuite.qunit.js create mode 100644 test/fixtures/linter/rules/NoDeprecatedApi/testsuite.qunit.ts create mode 100644 test/fixtures/linter/rules/NoDeprecatedApi/testsuite2.qunit.js diff --git a/src/linter/ui5Types/SourceFileLinter.ts b/src/linter/ui5Types/SourceFileLinter.ts index bed777ef4..c13553be8 100644 --- a/src/linter/ui5Types/SourceFileLinter.ts +++ b/src/linter/ui5Types/SourceFileLinter.ts @@ -38,6 +38,19 @@ function isSourceFileOfTypeScriptLib(sourceFile: ts.SourceFile) { return sourceFile.fileName.startsWith("/types/typescript/lib/"); } +/** + * Removes surrounding quote characters ("'`) from a string if they exist. + * @param {string} str + * @returns {string} + * @example removeQuotes("\"myString\"") -> "myString" + * @example removeQuotes("\'myString\'") -> "myString" + * @example removeQuotes("\`myString\`") -> "myString" + */ +function removeQuotes(str: string | undefined): string { + if (!str) return ""; + return str.replace(/^['"`]|['"`]$/g, ""); +} + export default class SourceFileLinter { #resourcePath: ResourcePath; #sourceFile: ts.SourceFile; @@ -147,6 +160,8 @@ export default class SourceFileLinter { ts.forEachChild(node, visitMetadataNodes); } else if (this.isUi5ClassDeclaration(node, "sap/ui/core/Control")) { this.analyzeControlRendererDeclaration(node); + } else if (ts.isPropertyAssignment(node) && removeQuotes(node.name.getText()) === "theme") { + this.analyzeTestsuiteThemeProperty(node); } // Traverse the whole AST from top to bottom @@ -1196,4 +1211,43 @@ export default class SourceFileLinter { return !declarations.some((declaration) => isSourceFileOfTypeScriptLib(declaration.getSourceFile())) && declarations.some((declaration) => checkFunction(declaration.getSourceFile())); } + + analyzeTestsuiteThemeProperty(node: ts.PropertyAssignment) { + // In a Test Starter testsuite file, + // themes can be defined as default (1.) or for test configs individually (2.). + + // (1.) and (2.) are checks for these two possible structures, + // which use surrounding property names to determine the context. + + // We cannot use the best practice file name "testsuite.qunit.js/ts", + // to determine if a file is a Test Starter testsuite file, + // because the file name can be arbitrary. + // Therefore, we need checks (1.) and (2.) and set a flag to true afterwards. + let isTestStarterStructure = false; + + const oneLayerUp = node.parent.parent; + const twoLayersUp = oneLayerUp?.parent.parent; + const threeLayersUp = twoLayersUp?.parent.parent; + // Check if "theme" property is inside "ui5: {...}" object + if (oneLayerUp && ts.isObjectLiteralElement(oneLayerUp) && + removeQuotes(oneLayerUp.name?.getText()) === "ui5") { + if (ts.isObjectLiteralElement(twoLayersUp) && + removeQuotes(twoLayersUp.name?.getText()) === "defaults") { + // (1.) set flag to true if "theme" property is in "defaults: {...}" context + isTestStarterStructure = true; + } else if (ts.isObjectLiteralElement(twoLayersUp) && + ts.isObjectLiteralElement(threeLayersUp) && + removeQuotes(threeLayersUp.name?.getText()) === "tests") { + // (2.) set flag to true if "theme" property is in "tests: {...}" context + isTestStarterStructure = true; + } + } + + const themeName = removeQuotes(node.initializer.getText()); + if (isTestStarterStructure && deprecatedThemes.includes(themeName)) { + this.#reporter.addMessage(MESSAGE.DEPRECATED_THEME, { + themeName, + }, node); + } + } } diff --git a/test/fixtures/linter/rules/NoDeprecatedApi/testsuite.qunit.js b/test/fixtures/linter/rules/NoDeprecatedApi/testsuite.qunit.js new file mode 100644 index 000000000..46ecc6984 --- /dev/null +++ b/test/fixtures/linter/rules/NoDeprecatedApi/testsuite.qunit.js @@ -0,0 +1,34 @@ +sap.ui.define(function () { + "use strict"; + return { + name: "QUnit test suite with deprecated themes (JS)", + defaults: { + page: "ui5://test-resources/sap/ui/demo/todo/Test.qunit.html?testsuite={suite}&test={name}", + qunit: { + version: 2 + }, + sinon: { + version: 4 + }, + ui5: { + language: "EN", + theme: "sap_bluecrystal" // positive finding + } + }, + tests: { + "unit/unitTests": { + theme: "sap_belize", // negative finding (wrong place) + title: "Unit tests for Todo App", + ui5: { + theme: "sap_belize_plus", // positive finding + } + }, + "integration/opaTests": { + title: "Integration tests for Todo App", + ui5: { + theme: "sap_belize_hcb", // positive finding + } + } + } + }; +}); diff --git a/test/fixtures/linter/rules/NoDeprecatedApi/testsuite.qunit.ts b/test/fixtures/linter/rules/NoDeprecatedApi/testsuite.qunit.ts new file mode 100644 index 000000000..d4549ba2c --- /dev/null +++ b/test/fixtures/linter/rules/NoDeprecatedApi/testsuite.qunit.ts @@ -0,0 +1,36 @@ +export default { + name: "QUnit test suite with deprecated themes (TS)", + defaults: { + page: "ui5://test-resources/ui5/walkthrough/Test.qunit.html?testsuite={suite}&test={name}", + qunit: { + version: 2 + }, + sinon: { + version: 4 + }, + ui5: { + language: "EN", + theme: "sap_belize" // positive finding + } + }, + tests: { + "unit/unitTests": { + title: "UI5 TypeScript Walkthrough - Unit Tests", + ui5: { + theme: "sap_bluecrystal" // positive finding + } + }, + "integration/opaTests": { + title: "Integration tests for Todo App", + ui5: { + theme: "sap_horizon", // negative finding + } + }, + anythingHere: { + title: "Without string property name", + ui5: { + theme: "sap_belize_hcb", // positive finding + } + } + } +}; diff --git a/test/fixtures/linter/rules/NoDeprecatedApi/testsuite2.qunit.js b/test/fixtures/linter/rules/NoDeprecatedApi/testsuite2.qunit.js new file mode 100644 index 000000000..86c7ae78a --- /dev/null +++ b/test/fixtures/linter/rules/NoDeprecatedApi/testsuite2.qunit.js @@ -0,0 +1,34 @@ +sap.ui.define(function () { + "use strict"; + return { + name: "QUnit test suite with deprecated themes (JS) - Property names are surrounded by quotes", + "defaults": { + page: "ui5://test-resources/sap/ui/demo/todo/Test.qunit.html?testsuite={suite}&test={name}", + qunit: { + version: 2 + }, + sinon: { + version: 4 + }, + "ui5": { + language: "EN", + "theme": `sap_belize_hcw`, // positive finding (with backticks) + } + }, + 'tests': { // mixture of "" and '' + 'unit/unitTests': { + theme: "sap_belize", // negative finding (wrong place) + title: "Unit tests for Todo App", + "ui5": { + "theme": 'sap_belize_plus', // positive finding + } + }, + "integration/opaTests": { + title: "Integration tests for Todo App", + 'ui5': { + 'theme': "sap_belize_hcb", // positive finding + } + } + } + }; +}); diff --git a/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md index 0dfe1d323..737d7b55b 100644 --- a/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md +++ b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.md @@ -2756,6 +2756,126 @@ Generated by [AVA](https://avajs.dev). }, ] +## General: testsuite.qunit.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 3, + fatalErrorCount: 0, + filePath: 'testsuite.qunit.js', + messages: [ + { + column: 5, + line: 15, + message: 'Use of deprecated theme \'sap_bluecrystal\'', + messageDetails: 'Deprecated Themes and Libraries (https://ui5.sap.com/#/topic/a87ca843bcee469f82a9072927a7dcdb)', + ruleId: 'no-deprecated-theme', + severity: 2, + }, + { + column: 6, + line: 23, + message: 'Use of deprecated theme \'sap_belize_plus\'', + messageDetails: 'Deprecated Themes and Libraries (https://ui5.sap.com/#/topic/a87ca843bcee469f82a9072927a7dcdb)', + ruleId: 'no-deprecated-theme', + severity: 2, + }, + { + column: 6, + line: 29, + message: 'Use of deprecated theme \'sap_belize_hcb\'', + messageDetails: 'Deprecated Themes and Libraries (https://ui5.sap.com/#/topic/a87ca843bcee469f82a9072927a7dcdb)', + ruleId: 'no-deprecated-theme', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: testsuite.qunit.ts + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 3, + fatalErrorCount: 0, + filePath: 'testsuite.qunit.ts', + messages: [ + { + column: 4, + line: 13, + message: 'Use of deprecated theme \'sap_belize\'', + messageDetails: 'Deprecated Themes and Libraries (https://ui5.sap.com/#/topic/a87ca843bcee469f82a9072927a7dcdb)', + ruleId: 'no-deprecated-theme', + severity: 2, + }, + { + column: 5, + line: 20, + message: 'Use of deprecated theme \'sap_bluecrystal\'', + messageDetails: 'Deprecated Themes and Libraries (https://ui5.sap.com/#/topic/a87ca843bcee469f82a9072927a7dcdb)', + ruleId: 'no-deprecated-theme', + severity: 2, + }, + { + column: 5, + line: 32, + message: 'Use of deprecated theme \'sap_belize_hcb\'', + messageDetails: 'Deprecated Themes and Libraries (https://ui5.sap.com/#/topic/a87ca843bcee469f82a9072927a7dcdb)', + ruleId: 'no-deprecated-theme', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + +## General: testsuite2.qunit.js + +> Snapshot 1 + + [ + { + coverageInfo: [], + errorCount: 3, + fatalErrorCount: 0, + filePath: 'testsuite2.qunit.js', + messages: [ + { + column: 5, + line: 15, + message: 'Use of deprecated theme \'sap_belize_hcw\'', + messageDetails: 'Deprecated Themes and Libraries (https://ui5.sap.com/#/topic/a87ca843bcee469f82a9072927a7dcdb)', + ruleId: 'no-deprecated-theme', + severity: 2, + }, + { + column: 6, + line: 23, + message: 'Use of deprecated theme \'sap_belize_plus\'', + messageDetails: 'Deprecated Themes and Libraries (https://ui5.sap.com/#/topic/a87ca843bcee469f82a9072927a7dcdb)', + ruleId: 'no-deprecated-theme', + severity: 2, + }, + { + column: 6, + line: 29, + message: 'Use of deprecated theme \'sap_belize_hcb\'', + messageDetails: 'Deprecated Themes and Libraries (https://ui5.sap.com/#/topic/a87ca843bcee469f82a9072927a7dcdb)', + ruleId: 'no-deprecated-theme', + severity: 2, + }, + ], + warningCount: 0, + }, + ] + ## General: ui5.yaml > Snapshot 1 diff --git a/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.snap b/test/lib/linter/rules/snapshots/NoDeprecatedApi.ts.snap index b3446ee3fc5028ee1d586f50ba19bc7b185d894c..eeef2a9e58a6872f74a79a67f0d42c7894354624 100644 GIT binary patch literal 16324 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 Z#yy22uD5HG^X>Itj|aC7>MJzV{{f!>p<@65 literal 15986 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 ArvLx|