mirror of
https://github.com/wassname/talk.git
synced 2026-06-27 17:50:42 +08:00
[CORL-720] Integratejest-axe (#2741)
* feat: axe checks for tests * test: add another axe check * fix: tests
This commit is contained in:
Generated
+38
-9
@@ -3904,19 +3904,23 @@
|
||||
}
|
||||
},
|
||||
"@types/jest": {
|
||||
"version": "24.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.13.tgz",
|
||||
"integrity": "sha512-3m6RPnO35r7Dg+uMLj1+xfZaOgIHHHut61djNjzwExXN4/Pm9has9C6I1KMYSfz7mahDhWUOVg4HW/nZdv5Pww==",
|
||||
"version": "24.0.23",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.23.tgz",
|
||||
"integrity": "sha512-L7MBvwfNpe7yVPTXLn32df/EK+AMBFAFvZrRuArGs7npEWnlziUXK+5GMIUTI4NIuwok3XibsjXCs5HxviYXjg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/jest-diff": "*"
|
||||
"jest-diff": "^24.3.0"
|
||||
}
|
||||
},
|
||||
"@types/jest-diff": {
|
||||
"version": "20.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz",
|
||||
"integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==",
|
||||
"dev": true
|
||||
"@types/jest-axe": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest-axe/-/jest-axe-3.2.1.tgz",
|
||||
"integrity": "sha512-sn+MFd66gNnvhtBkbQBY6q2aznzLXUIN/jJqXd11D0P+PbUnDrthqyOj81O8BLhEYopmUXIp/ktVvdtj/1GZdw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/jest": "*",
|
||||
"axe-core": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"@types/joi": {
|
||||
"version": "13.3.0",
|
||||
@@ -4184,6 +4188,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/prettier": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-1.19.0.tgz",
|
||||
"integrity": "sha512-gDE8JJEygpay7IjA/u3JiIURvwZW08f0cZSZLAzFoX/ZmeqvS0Sqv+97aKuHpNsalAMMhwPe+iAS6fQbfmbt7A=="
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.5.8.tgz",
|
||||
@@ -19836,6 +19845,26 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"jest-axe": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-axe/-/jest-axe-3.2.0.tgz",
|
||||
"integrity": "sha512-QSQwSwG72/cpmhJU0fBsaUUvu9mb2uAqhccGQVG6JbIV8sK+aIXh8hYl7vxraMF/I6soQod1aqSdD/j7LjpVFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"axe-core": "3.3.1",
|
||||
"chalk": "2.4.2",
|
||||
"jest-matcher-utils": "24.8.0",
|
||||
"lodash.merge": "4.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"axe-core": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-3.3.1.tgz",
|
||||
"integrity": "sha512-gw1T0JptHPF4AdLLqE8yQq3Z7YvsYkpFmFWd84r6hnq/QoKRr8icYHFumhE7wYl5TVIHgVlchMyJsAYh0CfwCQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"jest-changed-files": {
|
||||
"version": "24.8.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.8.0.tgz",
|
||||
|
||||
+4
-1
@@ -59,6 +59,7 @@
|
||||
"dependencies": {
|
||||
"@coralproject/bunyan-prettystream": "^0.1.4",
|
||||
"@metascraper/helpers": "^5.7.21",
|
||||
"@types/prettier": "^1.19.0",
|
||||
"abort-controller": "^3.0.0",
|
||||
"akismet-api": "^4.2.0",
|
||||
"apollo-server-express": "^2.8.1",
|
||||
@@ -186,7 +187,8 @@
|
||||
"@types/html-to-text": "^1.4.31",
|
||||
"@types/html-webpack-plugin": "^3.2.0",
|
||||
"@types/ioredis": "^4.0.10",
|
||||
"@types/jest": "^24.0.13",
|
||||
"@types/jest": "^24.0.23",
|
||||
"@types/jest-axe": "^3.2.1",
|
||||
"@types/joi": "^13.0.8",
|
||||
"@types/jsdom": "^12.2.3",
|
||||
"@types/jsonwebtoken": "^7.2.7",
|
||||
@@ -300,6 +302,7 @@
|
||||
"husky": "^2.2.0",
|
||||
"intersection-observer": "^0.6.0",
|
||||
"jest": "^24.8.0",
|
||||
"jest-axe": "^3.2.0",
|
||||
"jest-junit": "^6.4.0",
|
||||
"jest-localstorage-mock": "^2.4.0",
|
||||
"jest-mock-console": "^1.0.0",
|
||||
|
||||
@@ -23,9 +23,10 @@ export default class ChokidarWatcher implements Watcher {
|
||||
let firstError: Error | null = null;
|
||||
|
||||
// If this is set, a pending promise is waiting for the next result.
|
||||
let pending:
|
||||
| ({ resolve: (result: string) => void; reject: (error: Error) => void })
|
||||
| null = null;
|
||||
let pending: {
|
||||
resolve: (result: string) => void;
|
||||
reject: (error: Error) => void;
|
||||
} | null = null;
|
||||
|
||||
// Only start client if we have something to watch.
|
||||
if (paths.length) {
|
||||
|
||||
@@ -48,7 +48,7 @@ export default class SaneWatcher implements Watcher {
|
||||
const queue: string[] = [];
|
||||
|
||||
// If this is set, a pending promise is waiting for the next result.
|
||||
let pending: ({ resolve: (result: string) => void }) | null = null;
|
||||
let pending: { resolve: (result: string) => void } | null = null;
|
||||
|
||||
// Only start client if we have something to watch.
|
||||
if (paths.length) {
|
||||
|
||||
@@ -31,7 +31,9 @@ it("renders missing confirm token", async () => {
|
||||
replaceHistoryLocation("http://localhost/account/email/confirm");
|
||||
const { root } = await createTestRenderer();
|
||||
await waitForElement(() => within(root).getByTestID("invalid-link"));
|
||||
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("renders form", async () => {
|
||||
@@ -57,6 +59,7 @@ it("renders form", async () => {
|
||||
);
|
||||
});
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
restMock.verify();
|
||||
});
|
||||
|
||||
@@ -98,6 +101,7 @@ it("renders error from server", async () => {
|
||||
);
|
||||
});
|
||||
restMock.verify();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ it("renders missing reset token", async () => {
|
||||
const { root } = await createTestRenderer();
|
||||
await waitForElement(() => within(root).getByTestID("invalid-link"));
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("renders form", async () => {
|
||||
@@ -57,6 +58,7 @@ it("renders form", async () => {
|
||||
);
|
||||
});
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
restMock.verify();
|
||||
});
|
||||
|
||||
@@ -98,6 +100,7 @@ it("renders error from server", async () => {
|
||||
);
|
||||
});
|
||||
restMock.verify();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ it("renders missing confirm token", async () => {
|
||||
const { root } = await createTestRenderer();
|
||||
await waitForElement(() => within(root).getByTestID("invalid-link"));
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("renders form", async () => {
|
||||
@@ -53,6 +54,7 @@ it("renders form", async () => {
|
||||
await waitForElement(() => within(root).getByTestID("unsubscribe-form"));
|
||||
});
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
restMock.verify();
|
||||
});
|
||||
|
||||
@@ -93,6 +95,7 @@ it("renders error from server", async () => {
|
||||
);
|
||||
});
|
||||
restMock.verify();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ it("renders addEmailAddress view", async () => {
|
||||
expect(toJSON(root)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("shows error when submitting empty form", async () => {
|
||||
|
||||
@@ -60,6 +60,7 @@ async function createTestRenderer(
|
||||
it("renders createPassword view", async () => {
|
||||
const { root } = await createTestRenderer();
|
||||
expect(toJSON(root)).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("shows error when submitting empty form", async () => {
|
||||
|
||||
@@ -58,6 +58,7 @@ async function createTestRenderer(
|
||||
it("renders createUsername view", async () => {
|
||||
const { root } = await createTestRenderer();
|
||||
expect(toJSON(root)).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("shows error when submitting empty form", async () => {
|
||||
|
||||
@@ -64,6 +64,7 @@ afterEach(async () => {
|
||||
it("renders forgot password view", async () => {
|
||||
const { testRenderer } = await createTestRenderer();
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
expect(await within(testRenderer.root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("shows error when submitting empty form", async () => {
|
||||
|
||||
@@ -58,6 +58,7 @@ async function createTestRenderer(
|
||||
it("renders sign in view", async () => {
|
||||
const { testRenderer } = await createTestRenderer();
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
expect(await within(testRenderer.root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("renders sign in view with error", async () => {
|
||||
|
||||
@@ -53,6 +53,7 @@ async function createTestRenderer(customResolver: any = {}) {
|
||||
it("renders sign up form", async () => {
|
||||
const { testRenderer } = await createTestRenderer();
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
expect(await within(testRenderer.root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("shows error when submitting empty form", async () => {
|
||||
|
||||
@@ -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 })),
|
||||
};
|
||||
}
|
||||
|
||||
+70
-1
@@ -253,6 +253,75 @@ exports[`renders comment stream 1`] = `
|
||||
className="TabBar-root TabBar-secondary coral coral-tabBarSecondary coral-tabBarComments StreamContainer-tabBarRoot"
|
||||
role="tablist"
|
||||
>
|
||||
<div
|
||||
className="StreamContainer-featuredCommentsTabContainer"
|
||||
>
|
||||
<li
|
||||
className="Tab-root"
|
||||
id="tab-FEATURED_COMMENTS"
|
||||
role="presentation"
|
||||
>
|
||||
<button
|
||||
aria-controls="tabPane-FEATURED_COMMENTS"
|
||||
aria-selected={true}
|
||||
className="BaseButton-root Tab-button Tab-secondary StreamContainer-featuredCommentsTabButton Tab-active StreamContainer-fixedTab coral coral-tabBarSecondary-tab coral-tabBarComments-featured StreamContainer-featuredCommentsTab"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
role="tab"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
className="Box-root Flex-root Flex-flex Flex-alignCenter gutter Flex-spacing-1"
|
||||
>
|
||||
<span>
|
||||
Featured
|
||||
</span>
|
||||
<span
|
||||
className="Counter-root Counter-colorPrimary Counter-sizeSmall coral coral-counter"
|
||||
data-testid="comments-featuredCount"
|
||||
>
|
||||
<span
|
||||
className="Counter-text"
|
||||
>
|
||||
2
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
<div
|
||||
className="Popover-root Tooltip-root StreamContainer-featuredCommentsInfo coral coral-tabBarComments-featuredTooltip"
|
||||
>
|
||||
<button
|
||||
aria-label="Toggle featured comments tooltip"
|
||||
className="BaseButton-root TooltipButton-button"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<i
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm Icon-colorPrimary"
|
||||
>
|
||||
info
|
||||
</i>
|
||||
</button>
|
||||
<div
|
||||
aria-hidden={true}
|
||||
aria-labelledby="comments-featuredCommentPopover-ariainfo"
|
||||
id="comments-featuredCommentPopover"
|
||||
role="dialog"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<li
|
||||
className="Tab-root"
|
||||
id="tab-ALL_COMMENTS"
|
||||
@@ -261,7 +330,7 @@ exports[`renders comment stream 1`] = `
|
||||
<button
|
||||
aria-controls="tabPane-ALL_COMMENTS"
|
||||
aria-selected={false}
|
||||
className="BaseButton-root Tab-button Tab-secondary coral coral-tabBarSecondary-tab coral-tabBarComments-allComments"
|
||||
className="BaseButton-root Tab-button Tab-secondary StreamContainer-fixedTab coral coral-tabBarSecondary-tab coral-tabBarComments-allComments"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
|
||||
@@ -53,4 +53,5 @@ it("renders comment stream", async () => {
|
||||
within(testRenderer.root).getByTestID("comments-featuredComments-log")
|
||||
);
|
||||
expect(within(testRenderer.root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(testRenderer.root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
@@ -93,6 +93,7 @@ it("renders permalink view", async () => {
|
||||
within(testRenderer.root).getByTestID("current-tab-pane")
|
||||
);
|
||||
expect(within(tabPane).toJSON()).toMatchSnapshot();
|
||||
expect(await within(testRenderer.root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("show all comments", async () => {
|
||||
|
||||
@@ -125,6 +125,8 @@ it("post a reply", async () => {
|
||||
}),
|
||||
});
|
||||
|
||||
expect(await within(form).axe()).toHaveNoViolations();
|
||||
|
||||
// Write reply .
|
||||
act(() => rte.props.onChange({ html: "<b>Hello world!</b>" }));
|
||||
act(() => {
|
||||
|
||||
@@ -100,6 +100,7 @@ it("edit a comment", async () => {
|
||||
.props.onClick()
|
||||
);
|
||||
expect(within(comment).toJSON()).toMatchSnapshot("edit form");
|
||||
expect(await within(comment).axe()).toHaveNoViolations();
|
||||
|
||||
act(() =>
|
||||
testRenderer.root
|
||||
|
||||
@@ -119,6 +119,8 @@ it("loads more comments", async () => {
|
||||
within(testRenderer.root).getByTestID("comments-allComments-log")
|
||||
);
|
||||
|
||||
expect(await within(streamLog).axe()).toHaveNoViolations();
|
||||
|
||||
// Get amount of comments before.
|
||||
const commentsBefore = within(streamLog).getAllByTestID(/^comment-/).length;
|
||||
|
||||
|
||||
@@ -42,4 +42,5 @@ it("renders reply list", async () => {
|
||||
);
|
||||
// Wait for loading.
|
||||
expect(within(commentReplyList).toJSON()).toMatchSnapshot();
|
||||
expect(await within(commentReplyList).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
@@ -45,4 +45,5 @@ it("renders comment stream", async () => {
|
||||
within(testRenderer.root).getByTestID("comments-allComments-log")
|
||||
);
|
||||
expect(within(testRenderer.root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(testRenderer.root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import sinon from "sinon";
|
||||
|
||||
import { act, wait, waitForElement, within } from "coral-framework/testHelpers";
|
||||
import { act, waitForElement, within } from "coral-framework/testHelpers";
|
||||
|
||||
import { moderators, settings, stories } from "../fixtures";
|
||||
import create from "./create";
|
||||
@@ -42,11 +42,7 @@ async function createTestRenderer(
|
||||
}
|
||||
|
||||
it("renders configure", async () => {
|
||||
const { tabPane } = await createTestRenderer();
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(within(tabPane).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
const { tabPane, testRenderer } = await createTestRenderer();
|
||||
expect(within(tabPane).toJSON()).toMatchSnapshot();
|
||||
expect(await within(testRenderer.root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
@@ -67,6 +67,7 @@ it("renders the empty settings pane", async () => {
|
||||
testRenderer: { root },
|
||||
} = await createTestRenderer();
|
||||
expect(within(root).toJSON()).toMatchSnapshot();
|
||||
expect(await within(root).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("doesn't show the change password pane when local auth is disabled", async () => {
|
||||
@@ -112,6 +113,7 @@ it("render password change form", async () => {
|
||||
const newPassword = await waitForElement(() =>
|
||||
within(form).getByID("newPassword", { exact: false })
|
||||
);
|
||||
expect(await within(changePassword).axe()).toHaveNoViolations();
|
||||
|
||||
// Submit an empty form.
|
||||
act(() => {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
within,
|
||||
} from "coral-framework/testHelpers";
|
||||
|
||||
import { baseUser, settings, stories } from "../fixtures";
|
||||
import { settings, stories, userWithEmail } from "../fixtures";
|
||||
import create from "./create";
|
||||
|
||||
const story = stories[0];
|
||||
@@ -23,7 +23,7 @@ async function createTestRenderer(
|
||||
createResolversStub<GQLResolver>({
|
||||
Query: {
|
||||
settings: () => settings,
|
||||
viewer: () => baseUser,
|
||||
viewer: () => userWithEmail,
|
||||
stream: () => story,
|
||||
},
|
||||
}),
|
||||
@@ -49,7 +49,7 @@ describe("change email form", () => {
|
||||
const setup = await createTestRenderer({
|
||||
resolvers: createResolversStub<GQLResolver>({
|
||||
Query: {
|
||||
viewer: () => baseUser,
|
||||
viewer: () => userWithEmail,
|
||||
},
|
||||
Mutation: {
|
||||
updateEmail: ({ variables }) => {
|
||||
@@ -58,7 +58,7 @@ describe("change email form", () => {
|
||||
});
|
||||
return {
|
||||
user: {
|
||||
...baseUser,
|
||||
...userWithEmail,
|
||||
email: "updated_email@test.com",
|
||||
},
|
||||
};
|
||||
@@ -77,6 +77,7 @@ describe("change email form", () => {
|
||||
act(() => {
|
||||
editButton.props.onClick();
|
||||
});
|
||||
expect(await within(changeEmail).axe()).toHaveNoViolations();
|
||||
const form = within(changeEmail).getByType("form");
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
|
||||
@@ -76,7 +76,9 @@ describe("with recently changed username", () => {
|
||||
const form = within(changeUsername).queryByType("form");
|
||||
const message = within(changeUsername).queryByText(
|
||||
"Your username has been changed in the last 14 days",
|
||||
{ exact: false }
|
||||
{
|
||||
exact: false,
|
||||
}
|
||||
);
|
||||
expect(form).toBeNull();
|
||||
expect(message).toBeTruthy();
|
||||
@@ -106,10 +108,13 @@ describe("with new username", () => {
|
||||
act(() => {
|
||||
editButton.props.onClick();
|
||||
});
|
||||
expect(await within(changeUsername).axe()).toHaveNoViolations();
|
||||
within(changeUsername).getByType("form");
|
||||
const message = within(changeUsername).queryByText(
|
||||
"Your username has been changed in the last 14 days",
|
||||
{ exact: false }
|
||||
{
|
||||
exact: false,
|
||||
}
|
||||
);
|
||||
expect(message).toBeNull();
|
||||
});
|
||||
|
||||
@@ -109,6 +109,8 @@ describe("delete account steps", () => {
|
||||
nextButton.props.onClick();
|
||||
});
|
||||
}
|
||||
|
||||
expect(await within(modal).axe()).toHaveNoViolations();
|
||||
const form = within(modal).getByType("form");
|
||||
const confirm = within(modal).getByTestID("confirm-page-confirmation");
|
||||
const password = within(modal).getByTestID("confirm-page-password");
|
||||
|
||||
@@ -87,6 +87,7 @@ it("renders profile", async () => {
|
||||
within(testRenderer.root).getByTestID("profile-commentHistory")
|
||||
);
|
||||
expect(within(commentHistory).toJSON()).toMatchSnapshot();
|
||||
expect(await within(commentHistory).axe()).toHaveNoViolations();
|
||||
});
|
||||
|
||||
it("loads more comments", async () => {
|
||||
|
||||
@@ -73,6 +73,7 @@ it("render notifications form", async () => {
|
||||
const container = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("profile-account-notifications")
|
||||
);
|
||||
expect(await within(container).axe()).toHaveNoViolations();
|
||||
const form = within(container).getByType("form");
|
||||
|
||||
// Get the form fields.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { toHaveNoViolations } from "jest-axe";
|
||||
|
||||
import expectAndFail from "./expectAndFail";
|
||||
|
||||
// Automatically unmock console.
|
||||
@@ -17,3 +19,5 @@ process.on("unhandledRejection", err => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
expect.extend(toHaveNoViolations);
|
||||
|
||||
@@ -43,7 +43,7 @@ const Icon: FunctionComponent<Props> = props => {
|
||||
return (
|
||||
<i
|
||||
className={rootClassName}
|
||||
aria-hidden="true"
|
||||
aria-hidden={rest["aria-label"] ? "false" : "true"}
|
||||
{...rest}
|
||||
ref={forwardRef}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user