Skip to content

Commit bd74aec

Browse files
authored
chore: Reuses test utils logic from test utils repo (#54)
1 parent 8bb80fa commit bd74aec

File tree

3 files changed

+126
-253
lines changed

3 files changed

+126
-253
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/test-utils.js

Lines changed: 16 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -2,183 +2,31 @@
22
// SPDX-License-Identifier: Apache-2.0
33
import { execaSync } from "execa";
44
import { globbySync } from "globby";
5-
import fs from "node:fs";
65
import path from "node:path";
76

8-
import { default as convertToSelectorUtil } from "@cloudscape-design/test-utils-converter";
7+
import { generateTestUtils } from "@cloudscape-design/test-utils-converter";
98

109
import { pluralizeComponentName } from "./pluralize.js";
11-
import { pascalCase, writeSourceFile } from "./utils.js";
10+
import { pascalCase } from "./utils.js";
1211

13-
const components = globbySync(["src/test-utils/dom/**/index.ts", "!src/test-utils/dom/index.ts"]).map((fileName) =>
14-
fileName.replace("src/test-utils/dom/", "").replace("/index.ts", ""),
15-
);
16-
17-
function toWrapper(componentClass) {
18-
return `${componentClass}Wrapper`;
19-
}
20-
21-
const configs = {
22-
common: {
23-
buildFinder: ({ componentName, componentNamePlural }) => `
24-
ElementWrapper.prototype.find${componentName} = function(selector) {
25-
const rootSelector = \`.$\{${toWrapper(componentName)}.rootSelector}\`;
26-
// casting to 'any' is needed to avoid this issue with generics
27-
// https://github.com/microsoft/TypeScript/issues/29132
28-
return (this as any).findComponent(selector ? appendSelector(selector, rootSelector) : rootSelector, ${toWrapper(componentName)});
29-
};
30-
31-
ElementWrapper.prototype.findAll${componentNamePlural} = function(selector) {
32-
return this.findAllComponents(${toWrapper(componentName)}, selector);
33-
};`,
34-
},
35-
dom: {
36-
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); }`,
37-
buildFinderInterface: ({ componentName, componentNamePlural }) => `
38-
/**
39-
* Returns the wrapper of the first ${componentName} that matches the specified CSS selector.
40-
* If no CSS selector is specified, returns the wrapper of the first ${componentName}.
41-
* If no matching ${componentName} is found, returns \`null\`.
42-
*
43-
* @param {string} [selector] CSS Selector
44-
* @returns {${toWrapper(componentName)} | null}
45-
*/
46-
find${componentName}(selector?: string): ${toWrapper(componentName)} | null;
47-
48-
/**
49-
* Returns an array of ${componentName} wrapper that matches the specified CSS selector.
50-
* If no CSS selector is specified, returns all of the ${componentNamePlural} inside the current wrapper.
51-
* If no matching ${componentName} is found, returns an empty array.
52-
*
53-
* @param {string} [selector] CSS Selector
54-
* @returns {Array<${toWrapper(componentName)}>}
55-
*/
56-
findAll${componentNamePlural}(selector?: string): Array<${toWrapper(componentName)}>;`,
57-
},
58-
selectors: {
59-
defaultExport: `export default function wrapper(root: string = 'body') { return new ElementWrapper(root); }`,
60-
buildFinderInterface: ({ componentName, componentNamePlural }) => `
61-
/**
62-
* Returns a wrapper that matches the ${componentNamePlural} with the specified CSS selector.
63-
* If no CSS selector is specified, returns a wrapper that matches ${componentNamePlural}.
64-
*
65-
* @param {string} [selector] CSS Selector
66-
* @returns {${toWrapper(componentName)}}
67-
*/
68-
find${componentName}(selector?: string): ${toWrapper(componentName)};
69-
70-
/**
71-
* Returns a multi-element wrapper that matches ${componentNamePlural} with the specified CSS selector.
72-
* If no CSS selector is specified, returns a multi-element wrapper that matches ${componentNamePlural}.
73-
*
74-
* @param {string} [selector] CSS Selector
75-
* @returns {MultiElementWrapper<${toWrapper(componentName)}>}
76-
*/
77-
findAll${componentNamePlural}(selector?: string): MultiElementWrapper<${toWrapper(componentName)}>;`,
12+
const componentNames = globbySync(["src/test-utils/dom/**/index.ts", "!src/test-utils/dom/index.ts"]).map(
13+
(filePath) => {
14+
const fileNameKebabCase = filePath.replace("src/test-utils/dom/", "").replace("/index.ts", "");
15+
return pascalCase(fileNameKebabCase);
7816
},
79-
};
80-
81-
function generateTestUtilMetaData() {
82-
const testUtilsSrcDir = path.resolve("src/test-utils");
83-
const metaData = components.reduce((allMetaData, componentFolderName) => {
84-
const absPathComponentFolder = path.resolve(testUtilsSrcDir, componentFolderName);
85-
const relPathTestUtilFile = `./${path.relative(testUtilsSrcDir, absPathComponentFolder)}`;
86-
87-
const componentNameKebab = componentFolderName;
88-
const componentName = pascalCase(componentNameKebab);
89-
const componentNamePlural = pluralizeComponentName(componentName);
90-
91-
const componentMetaData = {
92-
componentName,
93-
componentNamePlural,
94-
relPathTestUtilFile,
95-
};
96-
97-
return allMetaData.concat(componentMetaData);
98-
}, []);
99-
100-
return metaData;
101-
}
102-
103-
function generateFindersInterfaces({ testUtilMetaData, testUtilType, configs }) {
104-
const { buildFinderInterface } = configs[testUtilType];
105-
const findersInterfaces = testUtilMetaData.map(buildFinderInterface);
106-
107-
// we need to redeclare the interface in its original definition, extending a re-export will not work
108-
// https://github.com/microsoft/TypeScript/issues/12607
109-
const interfaces = `declare module '@cloudscape-design/test-utils-core/dist/${testUtilType}' {
110-
interface ElementWrapper {
111-
${findersInterfaces.join("\n")}
112-
}
113-
}`;
114-
115-
return interfaces;
116-
}
117-
118-
function generateFindersImplementations({ testUtilMetaData, configs }) {
119-
const { buildFinder } = configs.common;
120-
const findersImplementations = testUtilMetaData.map(buildFinder);
121-
return findersImplementations.join("\n");
122-
}
123-
124-
generateSelectorUtils();
125-
generateDomIndexFile();
126-
generateSelectorsIndexFile();
127-
compileTypescript();
128-
129-
function generateSelectorUtils() {
130-
components.forEach((componentName) => {
131-
const domFileName = `./src/test-utils/dom/${componentName}/index.ts`;
132-
const domFileContent = fs.readFileSync(domFileName, "utf-8");
133-
const selectorsFileName = `./src/test-utils/selectors/${componentName}/index.ts`;
134-
const selectorsFileContent = convertToSelectorUtil.default(domFileContent);
135-
writeSourceFile(selectorsFileName, selectorsFileContent);
136-
});
137-
}
138-
139-
function generateDomIndexFile() {
140-
const content = generateIndexFileContent({
141-
testUtilType: "dom",
142-
testUtilMetaData: generateTestUtilMetaData(),
143-
});
144-
writeSourceFile("./src/test-utils/dom/index.ts", content);
145-
}
146-
147-
function generateSelectorsIndexFile() {
148-
const content = generateIndexFileContent({
149-
testUtilType: "selectors",
150-
testUtilMetaData: generateTestUtilMetaData(),
151-
});
152-
writeSourceFile("./src/test-utils/selectors/index.ts", content);
153-
}
154-
155-
function generateIndexFileContent({ testUtilType, testUtilMetaData }) {
156-
const config = configs[testUtilType];
157-
if (config === undefined) {
158-
throw new Error("Unknown test util type");
159-
}
160-
161-
return [
162-
// language=TypeScript
163-
`import { ElementWrapper } from '@cloudscape-design/test-utils-core/${testUtilType}';`,
164-
`import '@cloudscape-design/components/test-utils/${testUtilType}';`,
165-
`import { appendSelector } from '@cloudscape-design/test-utils-core/utils';`,
166-
`export { ElementWrapper };`,
167-
...testUtilMetaData.map((metaData) => {
168-
const { componentName, relPathTestUtilFile } = metaData;
17+
);
16918

170-
return `
171-
import ${toWrapper(componentName)} from '${relPathTestUtilFile}';
172-
export { ${componentName}Wrapper };
173-
`;
174-
}),
175-
generateFindersInterfaces({ testUtilMetaData, testUtilType, configs }),
176-
generateFindersImplementations({ testUtilMetaData, configs }),
177-
config.defaultExport,
178-
].join("\n");
179-
}
19+
generateTestUtils({
20+
testUtilsPath: path.resolve("src/test-utils"),
21+
components: componentNames.map((name) => ({
22+
name,
23+
pluralName: pluralizeComponentName(name),
24+
})),
25+
});
18026

18127
function compileTypescript() {
18228
const config = path.resolve("src/test-utils/tsconfig.json");
18329
execaSync("tsc", ["-p", config, "--sourceMap", "--inlineSources"], { stdio: "inherit" });
18430
}
31+
32+
compileTypescript();

0 commit comments

Comments
 (0)