mirror of
https://github.com/wassname/talk.git
synced 2026-07-17 11:33:39 +08:00
[CORL-720] Integratejest-axe (#2741)
* feat: axe checks for tests * test: add another axe check * fix: tests
This commit is contained in:
@@ -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('"', """);
|
||||
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 })),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user