Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions src/test-utils/extractor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function getInheritedFrom(declaration: ts.Declaration, currentClassName: string)
if (parentName === currentClassName) {
return undefined;
}
return { name: parentName + '.' + declaration.name.getText() };
return { className: parentName, methodName: declaration.name.getText() };
}

function getDefaultValue(declaration: ts.Declaration) {
Expand All @@ -35,7 +35,8 @@ function getDefaultValue(declaration: ts.Declaration) {
export default function extractDocumentation(
sourceFile: ts.SourceFile,
checker: ts.TypeChecker,
extraExports: Array<string>
extraExports: Array<string>,
includeCoreMethods: boolean
): Array<TestUtilsDoc> {
const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
if (!moduleSymbol) {
Expand All @@ -51,7 +52,7 @@ export default function extractDocumentation(
continue;
}
const classType = checker.getDeclaredTypeOfSymbol(symbol);
documentClass(definitions, symbol, classType, checker);
documentClass(definitions, symbol, classType, checker, includeCoreMethods);
}

return Array.from(definitions.values());
Expand All @@ -61,7 +62,8 @@ function documentClass(
definitions: Map<string, TestUtilsDoc>,
symbol: ts.Symbol,
classType: ts.Type,
checker: ts.TypeChecker
checker: ts.TypeChecker,
includeCoreMethods: boolean
) {
if (!classType.isClass()) {
throw new Error(`Exported symbol is not a class, got ${checker.symbolToString(symbol)}`);
Expand Down Expand Up @@ -92,11 +94,20 @@ function documentClass(
maybeReturnType.flags & ts.TypeFlags.Void ? maybeReturnType : maybeReturnType.getNonNullableType();
const dependency = findDependencyType(returnType, checker);
if (dependency && !definitions.has(dependency.typeName)) {
documentClass(definitions, dependency.symbol, dependency.type, checker);
documentClass(definitions, dependency.symbol, dependency.type, checker, includeCoreMethods);
}

const { typeName, typeParameters } = extractTypeArguments(returnType, checker);

const inheritedFrom = getInheritedFrom(declaration, className);
if (
inheritedFrom &&
!includeCoreMethods &&
['AbstractWrapper', 'ElementWrapper'].includes(inheritedFrom?.className)
) {
continue;
}

definition.methods.push({
name: property.getName(),
description: getDescription(property.getDocumentationComment(checker), declaration).text,
Expand All @@ -117,7 +128,7 @@ function documentClass(
defaultValue: getDefaultValue(extractDeclaration(parameter)),
};
}),
inheritedFrom: getInheritedFrom(declaration, className),
inheritedFrom: inheritedFrom ? { name: `${inheritedFrom.className}.${inheritedFrom.methodName}` } : undefined,
});
}
}
Expand Down
21 changes: 17 additions & 4 deletions src/test-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface TestUtilsVariantOptions {

export interface TestUtilsDocumenterOptions {
tsconfigPath: string;
includeCoreMethods?: boolean;
domUtils: TestUtilsVariantOptions;
selectorsUtils: TestUtilsVariantOptions;
}
Expand All @@ -22,7 +23,7 @@ interface TestUtilsDefinitions {
selectorsDefinitions: Array<TestUtilsDoc>;
}

export function documentTestUtilsNew(options: TestUtilsDocumenterOptions): TestUtilsDefinitions {
export function documentTestUtils(options: TestUtilsDocumenterOptions): TestUtilsDefinitions {
const domUtilsRoot = pathe.resolve(options.domUtils.root);
const selectorsUtilsRoot = pathe.resolve(options.selectorsUtils.root);
const program = bootstrapTypescriptProject(options.tsconfigPath);
Expand All @@ -37,17 +38,29 @@ export function documentTestUtilsNew(options: TestUtilsDocumenterOptions): TestU
if (!selectorsUtilsFile) {
throw new Error(`File '${selectorsUtilsFile}' not found`);
}
// TODO: switch to false after all consumers updated
const includeCoreMethods = options.includeCoreMethods ?? true;
return {
domDefinitions: extractDocumentation(domUtilsFile, checker, options.domUtils.extraExports ?? []),
selectorsDefinitions: extractDocumentation(selectorsUtilsFile, checker, options.selectorsUtils.extraExports ?? []),
domDefinitions: extractDocumentation(
domUtilsFile,
checker,
options.domUtils.extraExports ?? [],
includeCoreMethods
),
selectorsDefinitions: extractDocumentation(
selectorsUtilsFile,
checker,
options.selectorsUtils.extraExports ?? [],
includeCoreMethods
),
};
}

export function writeTestUtilsDocumentation({
outDir,
...rest
}: TestUtilsDocumenterOptions & { outDir: string }): void {
const { domDefinitions, selectorsDefinitions } = documentTestUtilsNew(rest);
const { domDefinitions, selectorsDefinitions } = documentTestUtils(rest);
fs.mkdirSync(outDir, { recursive: true });
fs.writeFileSync(
pathe.join(outDir, 'dom.js'),
Expand Down
1 change: 1 addition & 0 deletions src/test-utils/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface TestUtilMethod {
typeArguments?: Array<TypeArgument>;
};
parameters: Array<Parameter>;
/* @deprecated All inherited methods should be filtered automatically */
inheritedFrom?: {
name: string;
};
Expand Down
55 changes: 55 additions & 0 deletions test/test-utils/__snapshots__/doc-generation.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,27 @@ exports[`Generate documentation > For simple cases 1`] = `
]
`;

exports[`Generate documentation > allows to skip methods from core wrappers 1`] = `
[
{
"methods": [
{
"description": undefined,
"inheritedFrom": undefined,
"name": "childClassMethod",
"parameters": [],
"returnType": {
"isNullable": false,
"name": "void",
"typeArguments": undefined,
},
},
],
"name": "TestUtilWrapper",
},
]
`;

exports[`Generate documentation > deal with more complex types 1`] = `
[
{
Expand Down Expand Up @@ -285,3 +306,37 @@ exports[`Generate documentation > deal with re-exports 1`] = `
},
]
`;

exports[`Generate documentation > includes inherited methods from core wrappers 1`] = `
[
{
"methods": [
{
"description": undefined,
"inheritedFrom": undefined,
"name": "childClassMethod",
"parameters": [],
"returnType": {
"isNullable": false,
"name": "void",
"typeArguments": undefined,
},
},
{
"description": undefined,
"inheritedFrom": {
"name": "AbstractWrapper.inheritedMethod",
},
"name": "inheritedMethod",
"parameters": [],
"returnType": {
"isNullable": false,
"name": "void",
"typeArguments": undefined,
},
},
],
"name": "TestUtilWrapper",
},
]
`;
30 changes: 10 additions & 20 deletions test/test-utils/doc-generation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('Generate documentation', () => {
});

test('deal with more complex types', () => {
const results = buildTestUtilsProject('advanced-types', { extraExports: ['default'] });
const results = buildTestUtilsProject('advanced-types', undefined, { extraExports: ['default'] });

expect(results.length).toBe(1);
const classDoc = results[0];
Expand All @@ -61,26 +61,16 @@ describe('Generate documentation', () => {
expect(methods).toMatchSnapshot();
});

test('and deal with inheritance', () => {
const results = buildTestUtilsProject('inheritance');

expect(results.length).toBe(1);
const classDoc = results.find(classDoc => classDoc.name === 'TestUtilWrapper');

expect(classDoc).toBeDefined();

const methods = classDoc?.methods || [];
expect(methods.length).toBe(2);

const inheritedMethod = methods.find(method => method.name === 'inheritedMethod');
expect(inheritedMethod).toBeDefined();
expect(inheritedMethod?.inheritedFrom).toEqual({
name: 'AbstractWrapper.inheritedMethod',
});
test('includes inherited methods from core wrappers', () => {
const results = buildTestUtilsProject('inheritance', { includeCoreMethods: true });
expect(results[0].methods.find(method => method.name === 'inheritedMethod')).toBeTruthy();
expect(results).toMatchSnapshot();
});

const childClassMethod = methods.find(method => method.name === 'childClassMethod');
expect(childClassMethod).toBeDefined();
expect(childClassMethod?.inheritedFrom).toBeUndefined();
test('allows to skip methods from core wrappers', () => {
const results = buildTestUtilsProject('inheritance', { includeCoreMethods: false });
expect(results[0].methods.find(method => method.name === 'inheritedMethod')).toBeFalsy();
expect(results).toMatchSnapshot();
});

test('deal with re-exports', () => {
Expand Down
12 changes: 7 additions & 5 deletions test/test-utils/test-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { documentTestUtilsNew, TestUtilsVariantOptions } from '../../src/test-utils';
import { documentTestUtils, TestUtilsDocumenterOptions, TestUtilsVariantOptions } from '../../src/test-utils';
import { TestUtilsDoc } from '../../src/test-utils/interfaces';

export function buildTestUtilsProject(
name: string,
configOverrides?: Partial<TestUtilsVariantOptions>
configOverrides?: Partial<TestUtilsDocumenterOptions>,
wrapperConfigOverrides?: Partial<TestUtilsVariantOptions>
): TestUtilsDoc[] {
return documentTestUtilsNew({
return documentTestUtils({
tsconfigPath: require.resolve(`../../fixtures/test-utils/${name}/tsconfig.json`),
domUtils: { root: `fixtures/test-utils/${name}/index.ts`, ...configOverrides },
selectorsUtils: { root: `fixtures/test-utils/${name}/index.ts`, ...configOverrides },
domUtils: { root: `fixtures/test-utils/${name}/index.ts`, ...wrapperConfigOverrides },
selectorsUtils: { root: `fixtures/test-utils/${name}/index.ts`, ...wrapperConfigOverrides },
...configOverrides,
}).domDefinitions;
}
10 changes: 7 additions & 3 deletions test/test-utils/usage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ describe('documentTestUtils throws error for ', () => {

test('having no input files because of a non-matching glob', () => {
expect(() =>
buildTestUtilsProject('simple', {
root: 'fixtures/does-not-exist/index.ts',
})
buildTestUtilsProject(
'simple',
{},
{
root: 'fixtures/does-not-exist/index.ts',
}
)
).toThrow(/File '.*fixtures\/does-not-exist\/index.ts' not found/);
});
});
Loading