Better document the TechDocsAddonTester

Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
Eric Peterson
2022-05-11 11:59:46 +02:00
parent 2b74671f52
commit b859092abf
2 changed files with 50 additions and 15 deletions
@@ -10,31 +10,23 @@ import { screen as screen_2 } from 'testing-library__dom';
import { TechDocsEntityMetadata } from '@backstage/plugin-techdocs-react';
import { TechDocsMetadata } from '@backstage/plugin-techdocs-react';
// @public (undocumented)
// @public
export class TechDocsAddonTester {
protected constructor(addons: ReactElement[]);
// (undocumented)
atPath(path: string): this;
// (undocumented)
build(): React_2.ReactElement<
any,
string | React_2.JSXElementConstructor<any>
>;
// (undocumented)
static buildAddonsInTechDocs(addons: ReactElement[]): TechDocsAddonTester;
// (undocumented)
renderWithEffects(): Promise<
typeof screen_2 & {
shadowRoot: ShadowRoot | null;
}
>;
// (undocumented)
withApis<T extends any[]>(apis: TechdocsAddonTesterApis<T>): this;
// (undocumented)
withDom(dom: ReactElement): this;
// (undocumented)
withEntity(entity: Partial<TechDocsEntityMetadata>): this;
// (undocumented)
withMetadata(metadata: Partial<TechDocsMetadata>): this;
}
```
@@ -113,13 +113,27 @@ const defaultDom = (
);
/**
* Utility class for rendering TechDocs Addons end-to-end within the TechDocs
* reader page, with a set of givens (e.g. page DOM, metadata, etc).
*
* @example
* ```tsx
* const { getByText } = await TechDocsAddonTester.buildAddonsInTechDocs([<AnAddon />])
* .withDom(<body>TEST_CONTENT</body>)
* .renderWithEffects();
*
* expect(getByText('TEST_CONTENT')).toBeInTheDocument();
* ```
*
* @public
*/
export class TechDocsAddonTester {
private options: TechDocsAddonTesterOptions = defaultOptions;
private addons: ReactElement[];
/**
* Get a TechDocsAddonTester instance for a given set of Addons.
*/
static buildAddonsInTechDocs(addons: ReactElement[]) {
return new TechDocsAddonTester(addons);
}
@@ -129,6 +143,9 @@ export class TechDocsAddonTester {
this.addons = addons;
}
/**
* Provide mock API implementations if your Addon expects any.
*/
withApis<T extends any[]>(apis: TechdocsAddonTesterApis<T>) {
const refs = apis.map(([ref]) => ref);
this.options.apis = this.options.apis
@@ -137,26 +154,44 @@ export class TechDocsAddonTester {
return this;
}
/**
* Provide mock HTML if your Addon expects it in the shadow DOM.
*/
withDom(dom: ReactElement) {
this.options.dom = dom;
return this;
}
/**
* Provide mock techdocs_metadata.json values if your Addon needs it.
*/
withMetadata(metadata: Partial<TechDocsMetadata>) {
this.options.metadata = metadata;
return this;
}
/**
* Provide a mock entity if your Addon needs it. This also controls the base
* path at which the Addon is rendered.
*/
withEntity(entity: Partial<TechDocsEntityMetadata>) {
this.options.entity = entity;
return this;
}
/**
* Provide the TechDocs page path at which the Addon is rendered (e.g. the
* part of the path after the entity namespace/kind/name).
*/
atPath(path: string) {
this.options.path = path;
return this;
}
/**
* Return a fully configured and mocked TechDocs reader page within a test
* App instance, using the given Addon(s).
*/
build() {
const apis: TechdocsAddonTesterApis<any[]> = [
[techdocsApiRef, techdocsApi],
@@ -223,11 +258,19 @@ export class TechDocsAddonTester {
});
}
// Components using useEffect to perform an asynchronous action (such as fetch) must be rendered within an async
// act call to properly get the final state, even with mocked responses. This utility method makes the signature a bit
// cleaner, since act doesn't return the result of the evaluated function.
// https://github.com/testing-library/react-testing-library/issues/281
// https://github.com/facebook/react/pull/14853
/**
* Render the Addon within a fully configured and mocked TechDocs reader.
*
* @remarks
* Components using useEffect to perform an asynchronous action (such as
* fetch) must be rendered within an async act call to properly get the final
* state, even with mocked responses. This utility method makes the signature
* a bit cleaner, since act doesn't return the result of the evaluated
* function.
*
* @see https://github.com/testing-library/react-testing-library/issues/281
* @see https://github.com/facebook/react/pull/14853
*/
async renderWithEffects(): Promise<
typeof screen & { shadowRoot: ShadowRoot | null }
> {