From 0142e3401e41b5e542d1b1eb412c3ab56e015ce8 Mon Sep 17 00:00:00 2001 From: Amir Alami Date: Thu, 24 Oct 2024 10:02:24 +0200 Subject: [PATCH] feat: Adds findXAll and findXByTestId selectors --- build-tools/tasks/test-utils.js | 74 +++++++++++++++++++++++++++++---- package-lock.json | 5 ++- package.json | 1 + 3 files changed, 70 insertions(+), 10 deletions(-) diff --git a/build-tools/tasks/test-utils.js b/build-tools/tasks/test-utils.js index bc08604888..a1e43ca91c 100644 --- a/build-tools/tasks/test-utils.js +++ b/build-tools/tasks/test-utils.js @@ -3,6 +3,7 @@ const { src, dest, series, parallel } = require('gulp'); const execa = require('execa'); const path = require('path'); +const pluralize = require('pluralize'); const { pascalCase } = require('change-case'); const { default: convertToSelectorUtil } = require('@cloudscape-design/test-utils-converter'); const { through, task } = require('../utils/gulp-utils'); @@ -18,12 +19,59 @@ const configs = { dom: { defaultExport: `export default function wrapper(root: Element = document.body) { if (document && document.body && !document.body.contains(root)) { console.warn('[AwsUi] [test-utils] provided element is not part of the document body, interactions may work incorrectly')}; return new ElementWrapper(root); }`, buildFinderInterface: ({ componentName }) => - `find${componentName}(selector?: string): ${toWrapper(componentName)} | null;`, + `/** + * Returns the wrapper of the first ${componentName} that matches the specified CSS selector. + * If no CSS selector specified, returns the wrapper of the first ${componentName}. + * If no matching ${componentName} is found, returns \`null\`. + * + * @param {string} [selector] CSS Selector + * @returns {${toWrapper(componentName)} | null} + */ + find${componentName}(selector?: string): ${toWrapper(componentName)} | null; + /** + * Returns the wrappers of all ${pluralize(componentName)} that match the specified CSS selector. + * If no CSS selector specified, returns all of the ${pluralize(componentName)} inside current wrapper. + * If no matching ${componentName} is found, returns an empty array. + * + * @returns {Array<${toWrapper(componentName)}>} + */ + findAll${pluralize(componentName)}(selector?: string): Array<${toWrapper(componentName)}>; + /** + * Returns the first ${componentName} that matches the specified test id. + * Looks for \`data-testid\` attribute assigned to the component. + * If no matching ${componentName} is found, returns \`null\`. + * + * @param {string} testId + * @returns {${toWrapper(componentName)} | null} + */ + find${componentName}ByTestId(testId: string): ${toWrapper(componentName)} | null;`, }, selectors: { defaultExport: `export default function wrapper(root: string = 'body') { return new ElementWrapper(root); }`, buildFinderInterface: ({ componentName }) => - `find${componentName}(selector?: string): ${toWrapper(componentName)};`, + `/** + * Returns a wrapper that matches a ${componentName} with the specified CSS selector. + * If no CSS selector is specified, returns a wrapper that matches ${componentName}. + * + * @param {string} [selector] CSS Selector + * @returns {${toWrapper(componentName)}} + */ + find${componentName}(selector?: string): ${toWrapper(componentName)}; + /** + * Returns a wrapper that matches all of the ${pluralize(componentName)} satisfying the specified CSS selector. + * If no CSS selector specified, returns a wrapper that matches all of the ${pluralize(componentName)} inside current wrapper. + * + * @returns {MultiElementWrapper<${toWrapper(componentName)}>} + */ + findAll${pluralize(componentName)}(selector?: string): MultiElementWrapper<${toWrapper(componentName)}>; + /** + * Returns a wrapper that matches ${componentName} with the specified test id. + * Matches \`data-testid\` attribute assigned to the component. + * + * @param {string} testId + * @returns {${toWrapper(componentName)}} + */ + find${componentName}ByTestId(testId: string): ${toWrapper(componentName)};`, }, }; @@ -57,12 +105,22 @@ function generateIndexFileContent(testUtilType, testUtilMetaData) { ...testUtilMetaData.map(({ componentName }) => { const wrapperName = toWrapper(componentName); // language=TypeScript - return `ElementWrapper.prototype.find${componentName} = function(selector) { - const rootSelector = \`.$\{${wrapperName}.rootSelector}\`; - // casting to 'any' is needed to avoid this issue with generics - // https://github.com/microsoft/TypeScript/issues/29132 - return (this as any).findComponent(selector ? appendSelector(selector, rootSelector) : rootSelector, ${wrapperName}); - };`; + return ` + ElementWrapper.prototype.find${componentName} = function(selector) { + const rootSelector = \`.$\{${wrapperName}.rootSelector}\`; + return this.findComponent(selector ? appendSelector(selector, rootSelector) : rootSelector, ${wrapperName}); + }; + + ElementWrapper.prototype.findAll${pluralize(componentName)} = function(selector) { + const rootSelector = \`.$\{${wrapperName}.rootSelector}\`; + return this.findAllComponents(selector ? appendSelector(selector, rootSelector) : rootSelector, ${wrapperName}); + }; + + ElementWrapper.prototype.find${componentName}ByTestId = function(testId) { + const selector = \`.\${${wrapperName}.rootSelector}[data-testid="\${testId}"]\`; + return this.findComponent(selector, ${wrapperName}); + }; + `; }), defaultExport, ].join('\n'); diff --git a/package-lock.json b/package-lock.json index 7e513fb680..e3b55159f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "date-fns": "^2.25.0", "intl-messageformat": "^10.3.1", "mnth": "^2.0.0", + "pluralize": "^8.0.0", "react-keyed-flatten-children": "^1.3.0", "react-transition-group": "^4.4.2", "tslib": "^2.4.0", @@ -14706,8 +14707,8 @@ }, "node_modules/pluralize": { "version": "8.0.0", - "dev": true, - "license": "MIT", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "engines": { "node": ">=4" } diff --git a/package.json b/package.json index 4abc584b4e..d7db70eee6 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "date-fns": "^2.25.0", "intl-messageformat": "^10.3.1", "mnth": "^2.0.0", + "pluralize": "^8.0.0", "react-keyed-flatten-children": "^1.3.0", "react-transition-group": "^4.4.2", "tslib": "^2.4.0",