[CORL-720] Integratejest-axe (#2741)

* feat: axe checks for tests

* test: add another axe check

* fix: tests
This commit is contained in:
Vinh
2019-12-05 16:44:16 -05:00
committed by Kim Gardner
parent 51bfde8cf8
commit 7615dc2aaf
35 changed files with 283 additions and 40 deletions
@@ -48,7 +48,7 @@ export function denormalizeComments(commentList: Array<Fixture<GQLComment>>) {
}
export function denormalizeStory(story: Fixture<GQLStory>) {
const commentNodes =
const commentEdges =
(story.comments &&
story.comments.edges &&
story.comments.edges.map((edge: any) => ({
@@ -61,20 +61,21 @@ export function denormalizeStory(story: Fixture<GQLStory>) {
};
if (commentsPageInfo.endCursor === undefined) {
commentsPageInfo.endCursor =
commentNodes.length > 0
? commentNodes[commentNodes.length - 1].node.createdAt
commentEdges.length > 0
? commentEdges[commentEdges.length - 1].node.createdAt
: null;
}
const featuredCommentsCount = commentNodes.filter(
n => n.tags && n.tags.some((t: GQLTag) => t.code === GQLTAG.FEATURED)
const featuredCommentsCount = commentEdges.filter(
e =>
e.node.tags && e.node.tags.some((t: GQLTag) => t.code === GQLTAG.FEATURED)
).length;
return createFixture<GQLStory>({
...story,
comments: { edges: commentNodes, pageInfo: commentsPageInfo },
comments: { edges: commentEdges, pageInfo: commentsPageInfo },
commentCounts: {
...story.commentCounts,
totalPublished: commentNodes.length,
totalPublished: commentEdges.length,
tags: {
...(story.commentCounts && story.commentCounts.tags),
FEATURED: featuredCommentsCount,
@@ -46,3 +46,4 @@ export {
default as overwriteQueryResolver,
createQueryResolverOverwrite,
} from "./overwriteQueryResolver";
export { default as toHTML } from "./toHTML";
@@ -0,0 +1,89 @@
import { stripIndent } from "common-tags";
import prettier from "prettier";
import { ReactTestInstance } from "react-test-renderer";
import toJSON, { ReactTestRendererNode } from "./toJSON";
function convertPropertyToString(prop: string, value: any): string {
let propOut = prop;
let valueOut = "";
if (propOut === "dangerouslySetInnerHTML") {
return "";
}
// React uses `htmlFor` instead of `for` because of js restrictions.
if (propOut === "htmlFor") {
propOut = "for";
}
switch (typeof value) {
case "function":
valueOut = "[Function]";
break;
case "string":
valueOut = value;
break;
case "undefined":
valueOut = propOut;
return "";
case "boolean":
// Usually true means the property has been set without a value
// and false the property is not set.
// Exception: aria-labels need to be set to "true" / "false".
if (!prop.startsWith("aria-")) {
return value ? propOut : "";
}
// fall through
default:
valueOut = JSON.stringify(value);
}
valueOut = valueOut.replace('"', "&quot;");
return `${propOut}="${valueOut}"`;
}
function convertJSONToHTML(
node: ReactTestRendererNode | ReactTestRendererNode[]
): string {
if (typeof node === "string") {
return node;
}
if (Array.isArray(node)) {
return node.map(c => convertJSONToHTML(c)).join("\n");
}
const props = Object.keys(node.props)
.map(k => convertPropertyToString(k, node.props[k]))
.join(" ");
let innerHTML = "";
if ("dangerouslySetInnerHTML" in node.props) {
innerHTML = node.props.dangerouslySetInnerHTML.__html;
} else if (node.children) {
innerHTML = convertJSONToHTML(node.children);
}
if (innerHTML === "") {
return `<${node.type} ${props} />`;
}
return stripIndent`
<${node.type} ${props}>
${innerHTML}
</${node.type}>`;
}
/**
* Turns a ReactTestInstance into its HTML representation.
*/
export default function toHTML(
inst: ReactTestInstance,
options: { pretty?: boolean } = {}
) {
const result = toJSON(inst);
if (result === null) {
return "";
}
const output = convertJSONToHTML(result);
return options.pretty ? prettier.format(output, { parser: "html" }) : output;
}
@@ -1,12 +1,12 @@
import { ReactTestInstance } from "react-test-renderer";
interface ReactTestRendererJSON {
export interface ReactTestRendererJSON {
type: string;
props: { [propName: string]: any };
children: null | ReactTestRendererNode[];
$$typeof?: symbol; // Optional because we add it with defineProperty().
}
type ReactTestRendererNode = ReactTestRendererJSON | string;
export type ReactTestRendererNode = ReactTestRendererJSON | string;
export function toJSONRecursive(
inst: ReactTestInstance
@@ -1,3 +1,4 @@
import { axe } from "jest-axe";
import { ReactTestInstance } from "react-test-renderer";
import { getByID, queryByID } from "./byID";
@@ -22,6 +23,7 @@ import {
queryByType,
queryParentByType,
} from "./byType";
import toHTML from "./toHTML";
import toJSON from "./toJSON";
type Func0<R> = () => R;
@@ -68,6 +70,17 @@ export default function within(container: ReactTestInstance) {
queryByType: applyContainer(container, queryByType),
queryParentByType: applyContainer(container, queryParentByType),
queryAllByType: applyContainer(container, queryAllByType),
toJSON: () => toJSON(container),
toJSON: applyContainer(container, toJSON),
toHTML: applyContainer(container, toHTML),
/**
* Check for some accessibility violations
*
* Example use:
* `expect(await within(container).axe()).toHaveNoViolations();`
*/
axe: () => axe(toHTML(container)),
/** Output the html representation of the container */
// eslint-disable-next-line no-console
debug: () => console.log(toHTML(container, { pretty: true })),
};
}