diff --git a/package-lock.json b/package-lock.json index b1212fa..0924f7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11674,21 +11674,21 @@ "dev": true }, "node_modules/react-keyed-flatten-children": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-keyed-flatten-children/-/react-keyed-flatten-children-1.3.0.tgz", - "integrity": "sha512-qB7A6n+NHU0x88qTZGAJw6dsqwI941jcRPBB640c/CyWqjPQQ+YUmXOuzPziuHb7iqplM3xksWAbGYwkQT0tXA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-keyed-flatten-children/-/react-keyed-flatten-children-2.2.1.tgz", + "integrity": "sha512-6yBLVO6suN8c/OcJk1mzIrUHdeEzf5rtRVBhxEXAHO49D7SlJ70cG4xrSJrBIAG7MMeQ+H/T151mM2dRDNnFaA==", "dev": true, "dependencies": { - "react-is": "^16.8.6" + "react-is": "^18.2.0" }, "peerDependencies": { "react": ">=15.0.0" } }, "node_modules/react-keyed-flatten-children/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, "node_modules/react-refresh": { @@ -23341,18 +23341,18 @@ "dev": true }, "react-keyed-flatten-children": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-keyed-flatten-children/-/react-keyed-flatten-children-1.3.0.tgz", - "integrity": "sha512-qB7A6n+NHU0x88qTZGAJw6dsqwI941jcRPBB640c/CyWqjPQQ+YUmXOuzPziuHb7iqplM3xksWAbGYwkQT0tXA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-keyed-flatten-children/-/react-keyed-flatten-children-2.2.1.tgz", + "integrity": "sha512-6yBLVO6suN8c/OcJk1mzIrUHdeEzf5rtRVBhxEXAHO49D7SlJ70cG4xrSJrBIAG7MMeQ+H/T151mM2dRDNnFaA==", "dev": true, "requires": { - "react-is": "^16.8.6" + "react-is": "^18.2.0" }, "dependencies": { "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true } } diff --git a/scripts/test-utils.js b/scripts/test-utils.js index f41a015..e2f78cc 100644 --- a/scripts/test-utils.js +++ b/scripts/test-utils.js @@ -2,183 +2,31 @@ // SPDX-License-Identifier: Apache-2.0 import { execaSync } from "execa"; import { globbySync } from "globby"; -import fs from "node:fs"; import path from "node:path"; -import { default as convertToSelectorUtil } from "@cloudscape-design/test-utils-converter"; +import { generateTestUtils } from "@cloudscape-design/test-utils-converter"; import { pluralizeComponentName } from "./pluralize.js"; -import { pascalCase, writeSourceFile } from "./utils.js"; +import { pascalCase } from "./utils.js"; -const components = globbySync(["src/test-utils/dom/**/index.ts", "!src/test-utils/dom/index.ts"]).map((fileName) => - fileName.replace("src/test-utils/dom/", "").replace("/index.ts", ""), -); - -function toWrapper(componentClass) { - return `${componentClass}Wrapper`; -} - -const configs = { - common: { - buildFinder: ({ componentName, componentNamePlural }) => ` - ElementWrapper.prototype.find${componentName} = function(selector) { - const rootSelector = \`.$\{${toWrapper(componentName)}.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, ${toWrapper(componentName)}); - }; - - ElementWrapper.prototype.findAll${componentNamePlural} = function(selector) { - return this.findAllComponents(${toWrapper(componentName)}, selector); - };`, - }, - 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, componentNamePlural }) => ` - /** - * Returns the wrapper of the first ${componentName} that matches the specified CSS selector. - * If no CSS selector is 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 an array of ${componentName} wrapper that matches the specified CSS selector. - * If no CSS selector is specified, returns all of the ${componentNamePlural} inside the current wrapper. - * If no matching ${componentName} is found, returns an empty array. - * - * @param {string} [selector] CSS Selector - * @returns {Array<${toWrapper(componentName)}>} - */ - findAll${componentNamePlural}(selector?: string): Array<${toWrapper(componentName)}>;`, - }, - selectors: { - defaultExport: `export default function wrapper(root: string = 'body') { return new ElementWrapper(root); }`, - buildFinderInterface: ({ componentName, componentNamePlural }) => ` - /** - * Returns a wrapper that matches the ${componentNamePlural} with the specified CSS selector. - * If no CSS selector is specified, returns a wrapper that matches ${componentNamePlural}. - * - * @param {string} [selector] CSS Selector - * @returns {${toWrapper(componentName)}} - */ - find${componentName}(selector?: string): ${toWrapper(componentName)}; - - /** - * Returns a multi-element wrapper that matches ${componentNamePlural} with the specified CSS selector. - * If no CSS selector is specified, returns a multi-element wrapper that matches ${componentNamePlural}. - * - * @param {string} [selector] CSS Selector - * @returns {MultiElementWrapper<${toWrapper(componentName)}>} - */ - findAll${componentNamePlural}(selector?: string): MultiElementWrapper<${toWrapper(componentName)}>;`, +const componentNames = globbySync(["src/test-utils/dom/**/index.ts", "!src/test-utils/dom/index.ts"]).map( + (filePath) => { + const fileNameKebabCase = filePath.replace("src/test-utils/dom/", "").replace("/index.ts", ""); + return pascalCase(fileNameKebabCase); }, -}; - -function generateTestUtilMetaData() { - const testUtilsSrcDir = path.resolve("src/test-utils"); - const metaData = components.reduce((allMetaData, componentFolderName) => { - const absPathComponentFolder = path.resolve(testUtilsSrcDir, componentFolderName); - const relPathTestUtilFile = `./${path.relative(testUtilsSrcDir, absPathComponentFolder)}`; - - const componentNameKebab = componentFolderName; - const componentName = pascalCase(componentNameKebab); - const componentNamePlural = pluralizeComponentName(componentName); - - const componentMetaData = { - componentName, - componentNamePlural, - relPathTestUtilFile, - }; - - return allMetaData.concat(componentMetaData); - }, []); - - return metaData; -} - -function generateFindersInterfaces({ testUtilMetaData, testUtilType, configs }) { - const { buildFinderInterface } = configs[testUtilType]; - const findersInterfaces = testUtilMetaData.map(buildFinderInterface); - - // we need to redeclare the interface in its original definition, extending a re-export will not work - // https://github.com/microsoft/TypeScript/issues/12607 - const interfaces = `declare module '@cloudscape-design/test-utils-core/dist/${testUtilType}' { - interface ElementWrapper { - ${findersInterfaces.join("\n")} - } - }`; - - return interfaces; -} - -function generateFindersImplementations({ testUtilMetaData, configs }) { - const { buildFinder } = configs.common; - const findersImplementations = testUtilMetaData.map(buildFinder); - return findersImplementations.join("\n"); -} - -generateSelectorUtils(); -generateDomIndexFile(); -generateSelectorsIndexFile(); -compileTypescript(); - -function generateSelectorUtils() { - components.forEach((componentName) => { - const domFileName = `./src/test-utils/dom/${componentName}/index.ts`; - const domFileContent = fs.readFileSync(domFileName, "utf-8"); - const selectorsFileName = `./src/test-utils/selectors/${componentName}/index.ts`; - const selectorsFileContent = convertToSelectorUtil.default(domFileContent); - writeSourceFile(selectorsFileName, selectorsFileContent); - }); -} - -function generateDomIndexFile() { - const content = generateIndexFileContent({ - testUtilType: "dom", - testUtilMetaData: generateTestUtilMetaData(), - }); - writeSourceFile("./src/test-utils/dom/index.ts", content); -} - -function generateSelectorsIndexFile() { - const content = generateIndexFileContent({ - testUtilType: "selectors", - testUtilMetaData: generateTestUtilMetaData(), - }); - writeSourceFile("./src/test-utils/selectors/index.ts", content); -} - -function generateIndexFileContent({ testUtilType, testUtilMetaData }) { - const config = configs[testUtilType]; - if (config === undefined) { - throw new Error("Unknown test util type"); - } - - return [ - // language=TypeScript - `import { ElementWrapper } from '@cloudscape-design/test-utils-core/${testUtilType}';`, - `import '@cloudscape-design/components/test-utils/${testUtilType}';`, - `import { appendSelector } from '@cloudscape-design/test-utils-core/utils';`, - `export { ElementWrapper };`, - ...testUtilMetaData.map((metaData) => { - const { componentName, relPathTestUtilFile } = metaData; +); - return ` - import ${toWrapper(componentName)} from '${relPathTestUtilFile}'; - export { ${componentName}Wrapper }; - `; - }), - generateFindersInterfaces({ testUtilMetaData, testUtilType, configs }), - generateFindersImplementations({ testUtilMetaData, configs }), - config.defaultExport, - ].join("\n"); -} +generateTestUtils({ + testUtilsPath: path.resolve("src/test-utils"), + components: componentNames.map((name) => ({ + name, + pluralName: pluralizeComponentName(name), + })), +}); function compileTypescript() { const config = path.resolve("src/test-utils/tsconfig.json"); execaSync("tsc", ["-p", config, "--sourceMap", "--inlineSources"], { stdio: "inherit" }); } + +compileTypescript(); diff --git a/src/__tests__/__snapshots__/test-utils-wrappers.test.tsx.snap b/src/__tests__/__snapshots__/test-utils-wrappers.test.tsx.snap index f7ff663..dce55d3 100644 --- a/src/__tests__/__snapshots__/test-utils-wrappers.test.tsx.snap +++ b/src/__tests__/__snapshots__/test-utils-wrappers.test.tsx.snap @@ -1,229 +1,238 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`Generate test utils ElementWrapper > 'dom' ElementWrapper matches the snapshot 1`] = ` -"import { ElementWrapper } from '@cloudscape-design/test-utils-core/dom'; -import '@cloudscape-design/components/test-utils/dom'; +" +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { ElementWrapper } from '@cloudscape-design/test-utils-core/dom'; import { appendSelector } from '@cloudscape-design/test-utils-core/utils'; + export { ElementWrapper }; - import AvatarWrapper from './avatar'; - export { AvatarWrapper }; - +import AvatarWrapper from './avatar'; +import ChatBubbleWrapper from './chat-bubble'; +import LoadingBarWrapper from './loading-bar'; + - import ChatBubbleWrapper from './chat-bubble'; - export { ChatBubbleWrapper }; - +export { AvatarWrapper }; +export { ChatBubbleWrapper }; +export { LoadingBarWrapper }; - import LoadingBarWrapper from './loading-bar'; - export { LoadingBarWrapper }; - declare module '@cloudscape-design/test-utils-core/dist/dom' { - interface ElementWrapper { - - /** - * Returns the wrapper of the first Avatar that matches the specified CSS selector. - * If no CSS selector is specified, returns the wrapper of the first Avatar. - * If no matching Avatar is found, returns \`null\`. - * - * @param {string} [selector] CSS Selector - * @returns {AvatarWrapper | null} - */ - findAvatar(selector?: string): AvatarWrapper | null; - - /** - * Returns an array of Avatar wrapper that matches the specified CSS selector. - * If no CSS selector is specified, returns all of the Avatars inside the current wrapper. - * If no matching Avatar is found, returns an empty array. - * - * @param {string} [selector] CSS Selector - * @returns {Array} - */ - findAllAvatars(selector?: string): Array; - - /** - * Returns the wrapper of the first ChatBubble that matches the specified CSS selector. - * If no CSS selector is specified, returns the wrapper of the first ChatBubble. - * If no matching ChatBubble is found, returns \`null\`. - * - * @param {string} [selector] CSS Selector - * @returns {ChatBubbleWrapper | null} - */ - findChatBubble(selector?: string): ChatBubbleWrapper | null; - - /** - * Returns an array of ChatBubble wrapper that matches the specified CSS selector. - * If no CSS selector is specified, returns all of the ChatBubbles inside the current wrapper. - * If no matching ChatBubble is found, returns an empty array. - * - * @param {string} [selector] CSS Selector - * @returns {Array} - */ - findAllChatBubbles(selector?: string): Array; - - /** - * Returns the wrapper of the first LoadingBar that matches the specified CSS selector. - * If no CSS selector is specified, returns the wrapper of the first LoadingBar. - * If no matching LoadingBar is found, returns \`null\`. - * - * @param {string} [selector] CSS Selector - * @returns {LoadingBarWrapper | null} - */ - findLoadingBar(selector?: string): LoadingBarWrapper | null; - - /** - * Returns an array of LoadingBar wrapper that matches the specified CSS selector. - * If no CSS selector is specified, returns all of the LoadingBars inside the current wrapper. - * If no matching LoadingBar is found, returns an empty array. - * - * @param {string} [selector] CSS Selector - * @returns {Array} - */ - findAllLoadingBars(selector?: string): Array; - } - } - - ElementWrapper.prototype.findAvatar = function(selector) { - const rootSelector = \`.\${AvatarWrapper.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, AvatarWrapper); - }; - - ElementWrapper.prototype.findAllAvatars = function(selector) { - return this.findAllComponents(AvatarWrapper, selector); - }; - - ElementWrapper.prototype.findChatBubble = function(selector) { - const rootSelector = \`.\${ChatBubbleWrapper.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, ChatBubbleWrapper); - }; - - ElementWrapper.prototype.findAllChatBubbles = function(selector) { - return this.findAllComponents(ChatBubbleWrapper, selector); - }; - - ElementWrapper.prototype.findLoadingBar = function(selector) { - const rootSelector = \`.\${LoadingBarWrapper.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, LoadingBarWrapper); - }; - - ElementWrapper.prototype.findAllLoadingBars = function(selector) { - return this.findAllComponents(LoadingBarWrapper, selector); - }; -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); }" + interface ElementWrapper { + +/** + * Returns the wrapper of the first Avatar that matches the specified CSS selector. + * If no CSS selector is specified, returns the wrapper of the first Avatar. + * If no matching Avatar is found, returns \`null\`. + * + * @param {string} [selector] CSS Selector + * @returns {AvatarWrapper | null} + */ +findAvatar(selector?: string): AvatarWrapper | null; + +/** + * Returns an array of Avatar wrapper that matches the specified CSS selector. + * If no CSS selector is specified, returns all of the Avatars inside the current wrapper. + * If no matching Avatar is found, returns an empty array. + * + * @param {string} [selector] CSS Selector + * @returns {Array} + */ +findAllAvatars(selector?: string): Array; +/** + * Returns the wrapper of the first ChatBubble that matches the specified CSS selector. + * If no CSS selector is specified, returns the wrapper of the first ChatBubble. + * If no matching ChatBubble is found, returns \`null\`. + * + * @param {string} [selector] CSS Selector + * @returns {ChatBubbleWrapper | null} + */ +findChatBubble(selector?: string): ChatBubbleWrapper | null; + +/** + * Returns an array of ChatBubble wrapper that matches the specified CSS selector. + * If no CSS selector is specified, returns all of the ChatBubbles inside the current wrapper. + * If no matching ChatBubble is found, returns an empty array. + * + * @param {string} [selector] CSS Selector + * @returns {Array} + */ +findAllChatBubbles(selector?: string): Array; +/** + * Returns the wrapper of the first LoadingBar that matches the specified CSS selector. + * If no CSS selector is specified, returns the wrapper of the first LoadingBar. + * If no matching LoadingBar is found, returns \`null\`. + * + * @param {string} [selector] CSS Selector + * @returns {LoadingBarWrapper | null} + */ +findLoadingBar(selector?: string): LoadingBarWrapper | null; + +/** + * Returns an array of LoadingBar wrapper that matches the specified CSS selector. + * If no CSS selector is specified, returns all of the LoadingBars inside the current wrapper. + * If no matching LoadingBar is found, returns an empty array. + * + * @param {string} [selector] CSS Selector + * @returns {Array} + */ +findAllLoadingBars(selector?: string): Array; + } +} + + +ElementWrapper.prototype.findAvatar = function(selector) { + const rootSelector = \`.\${AvatarWrapper.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, AvatarWrapper); +}; + +ElementWrapper.prototype.findAllAvatars = function(selector) { + return this.findAllComponents(AvatarWrapper, selector); +}; +ElementWrapper.prototype.findChatBubble = function(selector) { + const rootSelector = \`.\${ChatBubbleWrapper.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, ChatBubbleWrapper); +}; + +ElementWrapper.prototype.findAllChatBubbles = function(selector) { + return this.findAllComponents(ChatBubbleWrapper, selector); +}; +ElementWrapper.prototype.findLoadingBar = function(selector) { + const rootSelector = \`.\${LoadingBarWrapper.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, LoadingBarWrapper); +}; + +ElementWrapper.prototype.findAllLoadingBars = function(selector) { + return this.findAllComponents(LoadingBarWrapper, selector); +}; + + +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); +} +" `; exports[`Generate test utils ElementWrapper > 'selectors' ElementWrapper matches the snapshot 1`] = ` -"import { ElementWrapper } from '@cloudscape-design/test-utils-core/selectors'; -import '@cloudscape-design/components/test-utils/selectors'; +" +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { ElementWrapper } from '@cloudscape-design/test-utils-core/selectors'; import { appendSelector } from '@cloudscape-design/test-utils-core/utils'; + export { ElementWrapper }; - import AvatarWrapper from './avatar'; - export { AvatarWrapper }; - +import AvatarWrapper from './avatar'; +import ChatBubbleWrapper from './chat-bubble'; +import LoadingBarWrapper from './loading-bar'; + - import ChatBubbleWrapper from './chat-bubble'; - export { ChatBubbleWrapper }; - +export { AvatarWrapper }; +export { ChatBubbleWrapper }; +export { LoadingBarWrapper }; - import LoadingBarWrapper from './loading-bar'; - export { LoadingBarWrapper }; - declare module '@cloudscape-design/test-utils-core/dist/selectors' { - interface ElementWrapper { - - /** - * Returns a wrapper that matches the Avatars with the specified CSS selector. - * If no CSS selector is specified, returns a wrapper that matches Avatars. - * - * @param {string} [selector] CSS Selector - * @returns {AvatarWrapper} - */ - findAvatar(selector?: string): AvatarWrapper; - - /** - * Returns a multi-element wrapper that matches Avatars with the specified CSS selector. - * If no CSS selector is specified, returns a multi-element wrapper that matches Avatars. - * - * @param {string} [selector] CSS Selector - * @returns {MultiElementWrapper} - */ - findAllAvatars(selector?: string): MultiElementWrapper; - - /** - * Returns a wrapper that matches the ChatBubbles with the specified CSS selector. - * If no CSS selector is specified, returns a wrapper that matches ChatBubbles. - * - * @param {string} [selector] CSS Selector - * @returns {ChatBubbleWrapper} - */ - findChatBubble(selector?: string): ChatBubbleWrapper; - - /** - * Returns a multi-element wrapper that matches ChatBubbles with the specified CSS selector. - * If no CSS selector is specified, returns a multi-element wrapper that matches ChatBubbles. - * - * @param {string} [selector] CSS Selector - * @returns {MultiElementWrapper} - */ - findAllChatBubbles(selector?: string): MultiElementWrapper; - - /** - * Returns a wrapper that matches the LoadingBars with the specified CSS selector. - * If no CSS selector is specified, returns a wrapper that matches LoadingBars. - * - * @param {string} [selector] CSS Selector - * @returns {LoadingBarWrapper} - */ - findLoadingBar(selector?: string): LoadingBarWrapper; - - /** - * Returns a multi-element wrapper that matches LoadingBars with the specified CSS selector. - * If no CSS selector is specified, returns a multi-element wrapper that matches LoadingBars. - * - * @param {string} [selector] CSS Selector - * @returns {MultiElementWrapper} - */ - findAllLoadingBars(selector?: string): MultiElementWrapper; - } - } - - ElementWrapper.prototype.findAvatar = function(selector) { - const rootSelector = \`.\${AvatarWrapper.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, AvatarWrapper); - }; - - ElementWrapper.prototype.findAllAvatars = function(selector) { - return this.findAllComponents(AvatarWrapper, selector); - }; - - ElementWrapper.prototype.findChatBubble = function(selector) { - const rootSelector = \`.\${ChatBubbleWrapper.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, ChatBubbleWrapper); - }; - - ElementWrapper.prototype.findAllChatBubbles = function(selector) { - return this.findAllComponents(ChatBubbleWrapper, selector); - }; - - ElementWrapper.prototype.findLoadingBar = function(selector) { - const rootSelector = \`.\${LoadingBarWrapper.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, LoadingBarWrapper); - }; - - ElementWrapper.prototype.findAllLoadingBars = function(selector) { - return this.findAllComponents(LoadingBarWrapper, selector); - }; -export default function wrapper(root: string = 'body') { return new ElementWrapper(root); }" + interface ElementWrapper { + +/** + * Returns a wrapper that matches the Avatars with the specified CSS selector. + * If no CSS selector is specified, returns a wrapper that matches Avatars. + * + * @param {string} [selector] CSS Selector + * @returns {AvatarWrapper} + */ +findAvatar(selector?: string): AvatarWrapper; + +/** + * Returns a multi-element wrapper that matches Avatars with the specified CSS selector. + * If no CSS selector is specified, returns a multi-element wrapper that matches Avatars. + * + * @param {string} [selector] CSS Selector + * @returns {MultiElementWrapper} + */ +findAllAvatars(selector?: string): MultiElementWrapper; +/** + * Returns a wrapper that matches the ChatBubbles with the specified CSS selector. + * If no CSS selector is specified, returns a wrapper that matches ChatBubbles. + * + * @param {string} [selector] CSS Selector + * @returns {ChatBubbleWrapper} + */ +findChatBubble(selector?: string): ChatBubbleWrapper; + +/** + * Returns a multi-element wrapper that matches ChatBubbles with the specified CSS selector. + * If no CSS selector is specified, returns a multi-element wrapper that matches ChatBubbles. + * + * @param {string} [selector] CSS Selector + * @returns {MultiElementWrapper} + */ +findAllChatBubbles(selector?: string): MultiElementWrapper; +/** + * Returns a wrapper that matches the LoadingBars with the specified CSS selector. + * If no CSS selector is specified, returns a wrapper that matches LoadingBars. + * + * @param {string} [selector] CSS Selector + * @returns {LoadingBarWrapper} + */ +findLoadingBar(selector?: string): LoadingBarWrapper; + +/** + * Returns a multi-element wrapper that matches LoadingBars with the specified CSS selector. + * If no CSS selector is specified, returns a multi-element wrapper that matches LoadingBars. + * + * @param {string} [selector] CSS Selector + * @returns {MultiElementWrapper} + */ +findAllLoadingBars(selector?: string): MultiElementWrapper; + } +} + + +ElementWrapper.prototype.findAvatar = function(selector) { + const rootSelector = \`.\${AvatarWrapper.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, AvatarWrapper); +}; + +ElementWrapper.prototype.findAllAvatars = function(selector) { + return this.findAllComponents(AvatarWrapper, selector); +}; +ElementWrapper.prototype.findChatBubble = function(selector) { + const rootSelector = \`.\${ChatBubbleWrapper.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, ChatBubbleWrapper); +}; + +ElementWrapper.prototype.findAllChatBubbles = function(selector) { + return this.findAllComponents(ChatBubbleWrapper, selector); +}; +ElementWrapper.prototype.findLoadingBar = function(selector) { + const rootSelector = \`.\${LoadingBarWrapper.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, LoadingBarWrapper); +}; + +ElementWrapper.prototype.findAllLoadingBars = function(selector) { + return this.findAllComponents(LoadingBarWrapper, selector); +}; + + +export default function wrapper(root: string = 'body') { + return new ElementWrapper(root); +} +" `; diff --git a/src/chat-bubble/__tests__/chat-bubble.test.tsx b/src/chat-bubble/__tests__/chat-bubble.test.tsx index 70db2ac..edced63 100644 --- a/src/chat-bubble/__tests__/chat-bubble.test.tsx +++ b/src/chat-bubble/__tests__/chat-bubble.test.tsx @@ -5,10 +5,11 @@ import { describe, expect, test } from "vitest"; import ButtonGroup from "@cloudscape-design/components/button-group"; import ExpandableSection from "@cloudscape-design/components/expandable-section"; +import createWrapper from "@cloudscape-design/components/test-utils/dom"; +import "../../../lib/components/test-utils/dom"; import { Avatar } from "../../../lib/components"; import ChatBubble, { ChatBubbleProps } from "../../../lib/components/chat-bubble"; -import createWrapper from "../../../lib/components/test-utils/dom"; import styles from "../../../lib/components/chat-bubble/styles.selectors.js";