diff --git a/.circleci/config.yml b/.circleci/config.yml
index fa497104e..de544eec2 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -88,7 +88,7 @@ jobs:
name: Perform testing
# We're running these tests in band to avoid errors where the circleci
# test runner runs out of RAM trying to run them all in parallel.
- command: npm run test -- --ci --runInBand --testResultsProcessor="jest-junit"
+ command: npm run test -- --ci --runInBand --reporters=default --reporters=jest-junit
- store_test_results:
path: reports/junit
- store_artifacts:
diff --git a/package-lock.json b/package-lock.json
index a0cc8d1aa..051507565 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17548,9 +17548,9 @@
}
},
"hyphenate-style-name": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz",
- "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es=",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz",
+ "integrity": "sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==",
"dev": true
},
"iconv-lite": {
@@ -27837,15 +27837,27 @@
"dev": true
},
"react": {
- "version": "16.8.6",
- "resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz",
- "integrity": "sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==",
+ "version": "16.9.0-alpha.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.9.0-alpha.0.tgz",
+ "integrity": "sha512-y4bu7rJvtnPPsIwOj7sp5Y2SqlOb0jFupfkdjWxxn8ZeqzUARgpR9wJBUVwW1/QosVdOblmApjo/j6iiAXnebA==",
"dev": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
- "scheduler": "^0.13.6"
+ "scheduler": "^0.14.0-alpha.0"
+ },
+ "dependencies": {
+ "scheduler": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.14.0.tgz",
+ "integrity": "sha512-9CgbS06Kki2f4R9FjLSITjZo5BZxPsryiRNyL3LpvrM9WxcVmhlqAOc9E+KQbeI2nqej4JIIbOsfdL51cNb4Iw==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
+ }
}
},
"react-codemirror2": {
@@ -28782,15 +28794,27 @@
}
},
"react-dom": {
- "version": "16.8.6",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz",
- "integrity": "sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==",
+ "version": "16.9.0-alpha.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.9.0-alpha.0.tgz",
+ "integrity": "sha512-BQ5gN42yIPuTnBvE6K9vSjNfDRpSNcYCs2sUx9XR5VaWKwlHTt3G6qIWK6zdXy8TYKb1+IxpsAI0RtbRdXQZ2A==",
"dev": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
- "scheduler": "^0.13.6"
+ "scheduler": "^0.14.0-alpha.0"
+ },
+ "dependencies": {
+ "scheduler": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.14.0.tgz",
+ "integrity": "sha512-9CgbS06Kki2f4R9FjLSITjZo5BZxPsryiRNyL3LpvrM9WxcVmhlqAOc9E+KQbeI2nqej4JIIbOsfdL51cNb4Iw==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
+ }
}
},
"react-error-overlay": {
@@ -29041,9 +29065,9 @@
"integrity": "sha512-d1ttgGGRrjvntUeStKOGO4tsJy2P7hQ+T98DzdTa8QFEx8//0+/IPc1TUtFk0GVTUQJXG66cQw7EknwDRmRLfg=="
},
"react-responsive": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-5.0.0.tgz",
- "integrity": "sha512-oEimZ0FTCC3/pjGDEBHOz06nWbBNDIbMGOdRYp6K9SBUmrqgNAX77hTiqvmRQeLyI97zz4F4kiaFRxFspDxE+w==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-7.0.0.tgz",
+ "integrity": "sha512-RukaKD+UI/MIR+P8eUgVGURfiCafRvvcVnq41scT0eEQWHwDGliH/OAlrwIr1oyz8aKLGroZa+U8mTZV5ihPfA==",
"dev": true,
"requires": {
"hyphenate-style-name": "^1.0.0",
@@ -29122,22 +29146,32 @@
"integrity": "sha512-rxlZtZk5t6Y3gqqpaZ1lxY3RqlQcBU5uGsSoZj/hbF3ZweDqPbFHDkczT4emAxeaw37OD96RAAoayFGFQZCdWg=="
},
"react-test-renderer": {
- "version": "16.8.6",
- "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.8.6.tgz",
- "integrity": "sha512-H2srzU5IWYT6cZXof6AhUcx/wEyJddQ8l7cLM/F7gDXYyPr4oq+vCIxJYXVGhId1J706sqziAjuOEjyNkfgoEw==",
+ "version": "16.9.0-alpha.0",
+ "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.9.0-alpha.0.tgz",
+ "integrity": "sha512-eDl0oVFo6PGY1wpYFs0ezBpZhOgVce5TSta9UPLanshTi4z8NhlM6IgO8KBdioQ5H5/pmyGxOVtpUxJOt19NAQ==",
"dev": true,
"requires": {
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
- "react-is": "^16.8.6",
- "scheduler": "^0.13.6"
+ "react-is": "^16.9.0-alpha.0",
+ "scheduler": "^0.14.0-alpha.0"
},
"dependencies": {
"react-is": {
- "version": "16.8.6",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz",
- "integrity": "sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==",
+ "version": "16.9.0-alpha.0",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0-alpha.0.tgz",
+ "integrity": "sha512-psl0ePLTFliYfwcbwvimLgTNN156ZdeWB4zvP7dV/6lTAqWMHFfidg/mSZ2fFgE1LMNN8ZJOLl2DfZ8yg+3ETA==",
"dev": true
+ },
+ "scheduler": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.14.0.tgz",
+ "integrity": "sha512-9CgbS06Kki2f4R9FjLSITjZo5BZxPsryiRNyL3LpvrM9WxcVmhlqAOc9E+KQbeI2nqej4JIIbOsfdL51cNb4Iw==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ }
}
}
},
diff --git a/package.json b/package.json
index 1512fceba..6fbdbf57c 100644
--- a/package.json
+++ b/package.json
@@ -286,16 +286,16 @@
"pstree.remy": "^1.1.6",
"pym.js": "^1.3.2",
"raw-loader": "^0.5.1",
- "react": "^16.8.6",
+ "react": "^16.9.0-alpha.0",
"react-copy-to-clipboard": "^5.0.1",
"react-dev-utils": "^9.0.0",
- "react-dom": "^16.8.6",
+ "react-dom": "^16.9.0-alpha.0",
"react-error-overlay": "^5.1.6",
"react-final-form": "4.0.2",
"react-popper": "^1.3.2",
"react-relay": "^4.0.0",
- "react-responsive": "^5.0.0",
- "react-test-renderer": "^16.8.6",
+ "react-responsive": "^7.0.0",
+ "react-test-renderer": "^16.9.0-alpha.0",
"react-timeago": "^4.1.9",
"react-transition-group": "^2.5.0",
"react-with-state-props": "^2.0.4",
diff --git a/src/core/client/account/test/resetPassword.spec.tsx b/src/core/client/account/test/resetPassword.spec.tsx
index 1389b3d08..77df5fccd 100644
--- a/src/core/client/account/test/resetPassword.spec.tsx
+++ b/src/core/client/account/test/resetPassword.spec.tsx
@@ -2,6 +2,7 @@ import sinon from "sinon";
import { GQLResolver } from "coral-framework/schema";
import {
+ act,
createAccessToken,
CreateTestRendererParams,
replaceHistoryLocation,
@@ -52,11 +53,13 @@ it("renders form", async () => {
})
.once();
- await waitForElement(() =>
- within(root).getByText("Reset your password", {
- exact: false,
- })
- );
+ await act(async () => {
+ await waitForElement(() =>
+ within(root).getByText("Reset your password", {
+ exact: false,
+ })
+ );
+ });
expect(within(root).toJSON()).toMatchSnapshot();
restMock.verify();
});
@@ -91,11 +94,13 @@ it("renders error from server", async () => {
})
);
- await waitForElement(() =>
- within(root).getByText(code, {
- exact: false,
- })
- );
+ await act(async () => {
+ await waitForElement(() =>
+ within(root).getByText(code, {
+ exact: false,
+ })
+ );
+ });
restMock.verify();
}
});
@@ -126,36 +131,42 @@ it("submits form", async () => {
})
.once();
- await waitForElement(() =>
- within(root).getByText("Reset your password", {
- exact: false,
- })
- );
-
+ await act(async () => {
+ await waitForElement(() =>
+ within(root).getByText("Reset your password", {
+ exact: false,
+ })
+ );
+ });
const form = within(root).getByType("form");
const textField = within(root).getByLabelText("Password");
// Submit an empty form.
- form.props.onSubmit();
+ act(() => {
+ form.props.onSubmit();
+ });
within(root).getByText("field is required", {
exact: false,
});
// Password too short.
- textField.props.onChange("test");
+ act(() => {
+ textField.props.onChange("test");
+ });
within(root).getByText("Password must contain at least 8 characters", {
exact: false,
});
// Submit valid form.
- textField.props.onChange("testtest");
- form.props.onSubmit();
-
- await waitForElement(() =>
- within(root).getByText("successfully", {
- exact: false,
- })
- );
+ await act(async () => {
+ textField.props.onChange("testtest");
+ form.props.onSubmit();
+ await waitForElement(() =>
+ within(root).getByText("successfully", {
+ exact: false,
+ })
+ );
+ });
restMock.verify();
});
diff --git a/src/core/client/admin/test/auth/accountCompletion.spec.tsx b/src/core/client/admin/test/auth/accountCompletion.spec.tsx
index a51eaa6af..3a7e96137 100644
--- a/src/core/client/admin/test/auth/accountCompletion.spec.tsx
+++ b/src/core/client/admin/test/auth/accountCompletion.spec.tsx
@@ -1,6 +1,7 @@
import { pureMerge } from "coral-common/utils";
import { GQLResolver } from "coral-framework/schema";
import {
+ act,
createAccessToken,
createResolversStub,
CreateTestRendererParams,
@@ -117,11 +118,13 @@ it("do not render createPassword view when local auth is disabled", async () =>
}),
});
- await wait(() =>
- expect(window.location.toString()).toBe(
- "http://localhost/admin/moderate/reported"
- )
- );
+ await act(async () => {
+ await wait(() =>
+ expect(window.location.toString()).toBe(
+ "http://localhost/admin/moderate/reported"
+ )
+ );
+ });
});
it("complete account", async () => {
@@ -137,9 +140,11 @@ it("complete account", async () => {
},
}),
});
- await wait(() =>
- expect(window.location.toString()).toBe(
- "http://localhost/admin/moderate/reported"
- )
- );
+ await act(async () => {
+ await wait(() =>
+ expect(window.location.toString()).toBe(
+ "http://localhost/admin/moderate/reported"
+ )
+ );
+ });
});
diff --git a/src/core/client/admin/test/auth/redirectLoggedIn.spec.tsx b/src/core/client/admin/test/auth/redirectLoggedIn.spec.tsx
index 879e6f330..baeacdfab 100644
--- a/src/core/client/admin/test/auth/redirectLoggedIn.spec.tsx
+++ b/src/core/client/admin/test/auth/redirectLoggedIn.spec.tsx
@@ -3,6 +3,7 @@ import {
QueryToModerationQueuesResolver,
} from "coral-framework/schema";
import {
+ act,
createAccessToken,
createQueryResolverStub,
createResolversStub,
@@ -55,11 +56,13 @@ async function createTestRenderer(
it("redirect when already logged in", async () => {
await createTestRenderer();
- await wait(() =>
- expect(window.location.toString()).toBe(
- "http://localhost/admin/moderate/reported"
- )
- );
+ await act(async () => {
+ await wait(() =>
+ expect(window.location.toString()).toBe(
+ "http://localhost/admin/moderate/reported"
+ )
+ );
+ });
});
it("redirect to redirectPath when already logged in", async () => {
@@ -68,9 +71,11 @@ it("redirect to redirectPath when already logged in", async () => {
localRecord.setValue("/admin/moderate/pending", "redirectPath");
},
});
- await wait(() =>
- expect(window.location.toString()).toBe(
- "http://localhost/admin/moderate/pending"
- )
- );
+ await act(async () => {
+ await wait(() =>
+ expect(window.location.toString()).toBe(
+ "http://localhost/admin/moderate/pending"
+ )
+ );
+ });
});
diff --git a/src/core/client/admin/test/auth/redirectLoggedOut.spec.tsx b/src/core/client/admin/test/auth/redirectLoggedOut.spec.tsx
index 3ee3a7518..fd5c1f081 100644
--- a/src/core/client/admin/test/auth/redirectLoggedOut.spec.tsx
+++ b/src/core/client/admin/test/auth/redirectLoggedOut.spec.tsx
@@ -5,6 +5,7 @@ import {
QueryToModerationQueuesResolver,
} from "coral-framework/schema";
import {
+ act,
createQueryResolverStub,
createResolversStub,
CreateTestRendererParams,
@@ -50,10 +51,12 @@ async function createTestRenderer(
it("redirect when not logged in", async () => {
const { context } = await createTestRenderer();
- await wait(() => {
- expect(lookup(context.relayEnvironment, LOCAL_ID)!.redirectPath).toBe(
- "/admin/moderate/reported"
- );
- expect(window.location.toString()).toBe("http://localhost/admin/login");
+ await act(async () => {
+ await wait(() => {
+ expect(lookup(context.relayEnvironment, LOCAL_ID)!.redirectPath).toBe(
+ "/admin/moderate/reported"
+ );
+ expect(window.location.toString()).toBe("http://localhost/admin/login");
+ });
});
});
diff --git a/src/core/client/admin/test/auth/signInWithEmail.spec.tsx b/src/core/client/admin/test/auth/signInWithEmail.spec.tsx
index 6753eaba2..d063246c8 100644
--- a/src/core/client/admin/test/auth/signInWithEmail.spec.tsx
+++ b/src/core/client/admin/test/auth/signInWithEmail.spec.tsx
@@ -3,6 +3,7 @@ import sinon from "sinon";
import { pureMerge } from "coral-common/utils";
import { GQLResolver } from "coral-framework/schema";
import {
+ act,
createAccessToken,
createResolversStub,
CreateTestRendererParams,
@@ -12,6 +13,7 @@ import {
within,
} from "coral-framework/testHelpers";
+import { ReactTestInstance } from "react-test-renderer";
import create from "../create";
import {
emptyModerationQueues,
@@ -47,10 +49,14 @@ async function createTestRenderer(
},
});
- const form = await waitForElement(() =>
- within(testRenderer.root).getByType("form")
- );
- return { testRenderer, form, context };
+ let form: ReactTestInstance;
+
+ await act(async () => {
+ form = await waitForElement(() =>
+ within(testRenderer.root).getByType("form")
+ );
+ });
+ return { testRenderer, form: form!, context };
}
it("renders sign in form", async () => {
@@ -150,12 +156,16 @@ it("submits form successfully", async () => {
const historyMock = sinon.mock(window.history);
- form.props.onSubmit();
+ act(() => {
+ form.props.onSubmit();
+ });
const submitButton = within(form).getByText("Sign in with Email", {
selector: "button",
});
expect(submitButton.props.disabled).toBe(true);
- await wait(() => expect(submitButton.props.disabled).toBe(false));
+ await act(async () => {
+ await wait(() => expect(submitButton.props.disabled).toBe(false));
+ });
expect(location.toString()).toMatchSnapshot();
restMock.verify();
historyMock.verify();
diff --git a/src/core/client/admin/test/community/community.spec.tsx b/src/core/client/admin/test/community/community.spec.tsx
index a0321605b..3e9773f51 100644
--- a/src/core/client/admin/test/community/community.spec.tsx
+++ b/src/core/client/admin/test/community/community.spec.tsx
@@ -8,6 +8,7 @@ import {
QueryToUsersResolver,
} from "coral-framework/schema";
import {
+ act,
createQueryResolverStub,
createResolversStub,
CreateTestRendererParams,
@@ -101,17 +102,14 @@ it("filter by role", async () => {
const selectField = within(container).getByLabelText("Search by role");
const commentersOption = within(selectField).getByText("Commenters");
- TestRenderer.act(() => {
+ await act(async () => {
selectField.props.onChange({
target: { value: commentersOption.props.value.toString() },
});
- // TODO: Fix act warnings until await Promise.resolve();
- // or whatever comes out at https://github.com/facebook/react/issues/14769
+ await waitForElement(() =>
+ within(container).getByText("We could not find anyone", { exact: false })
+ );
});
-
- await waitForElement(() =>
- within(container).getByText("We could not find anyone", { exact: false })
- );
});
it("can't change viewer role", async () => {
@@ -149,7 +147,7 @@ it("change user role", async () => {
selector: "tr",
});
- TestRenderer.act(() => {
+ act(() => {
within(userRow)
.getByLabelText("Change role")
.props.onClick();
@@ -159,7 +157,7 @@ it("change user role", async () => {
"A dropdown to change the user role"
);
- TestRenderer.act(() => {
+ act(() => {
within(popup)
.getByText("Staff", { selector: "button" })
.props.onClick();
@@ -223,13 +221,11 @@ it("load more", async () => {
}),
});
const loadMore = within(container).getByText("Load More");
- TestRenderer.act(() => {
+ await act(async () => {
loadMore.props.onClick();
+ // Wait for load more to disappear.
+ await waitUntilThrow(() => within(container).getByText("Load More"));
});
-
- // Wait for load more to disappear.
- await waitUntilThrow(() => within(container).getByText("Load More"));
-
// Make sure third user was added.
within(container).getByText(users.commenters[1].username!);
});
@@ -256,16 +252,15 @@ it("filter by search", async () => {
});
const form = findParentWithType(searchField, "form")!;
- TestRenderer.act(() => {
+ await act(async () => {
searchField.props.onChange({
target: { value: "search" },
});
form.props.onSubmit();
+ await waitForElement(() =>
+ within(container).getByText("could not find anyone", { exact: false })
+ );
});
-
- await waitForElement(() =>
- within(container).getByText("could not find anyone", { exact: false })
- );
});
it("filter by status", async () => {
@@ -293,17 +288,14 @@ it("filter by status", async () => {
);
const bannedOption = within(statusField).getByText("Banned");
- TestRenderer.act(() => {
+ await act(async () => {
statusField.props.onChange({
target: { value: bannedOption.props.value.toString() },
});
- // TODO: Fix act warnings until await Promise.resolve();
- // or whatever comes out at https://github.com/facebook/react/issues/14769
+ await waitForElement(() =>
+ within(container).getByText("We could not find anyone", { exact: false })
+ );
});
-
- await waitForElement(() =>
- within(container).getByText("We could not find anyone", { exact: false })
- );
});
it("can't change staff, moderator and admin status", async () => {
@@ -373,9 +365,11 @@ it("ban user", async () => {
expect(within(modal).toJSON()).toMatchSnapshot();
- within(modal)
- .getByText("Ban User")
- .props.onClick();
+ TestRenderer.act(() => {
+ within(modal)
+ .getByText("Ban User")
+ .props.onClick();
+ });
within(userRow).getByText("Banned");
expect(resolvers.Mutation!.banUser!.called).toBe(true);
});
diff --git a/src/core/client/admin/test/moderate/__snapshots__/moderate.spec.tsx.snap b/src/core/client/admin/test/moderate/__snapshots__/moderate.spec.tsx.snap
index a97508d3b..1da5240e6 100644
--- a/src/core/client/admin/test/moderate/__snapshots__/moderate.spec.tsx.snap
+++ b/src/core/client/admin/test/moderate/__snapshots__/moderate.spec.tsx.snap
@@ -1196,27 +1196,6 @@ exports[`reported queue rejects comment in reported queue: dangling 1`] = `
`;
-exports[`reported queue renders empty reported queue 1`] = `
-
-
-
-
- Nicely done! There are no more reported comments to moderate.
-
-
-
-
-`;
-
exports[`reported queue renders reported queue with comments 1`] = `
{
const openSearchBar = async (testRenderer: ReactTestRenderer) => {
- const searchBar = await waitForElement(() =>
- within(testRenderer.root).getByTestID("moderate-searchBar-container")
+ await act(async () => {
+ await waitForElement(() =>
+ within(testRenderer.root).getByTestID("moderate-searchBar-container")
+ );
+ });
+ const searchBar = within(testRenderer.root).getByTestID(
+ "moderate-searchBar-container"
);
const textField = within(searchBar).getByLabelText(
"Search or jump to story..."
);
const form = findParentWithType(textField, "form")!;
- textField.props.onFocus({});
+ act(() => textField.props.onFocus({}));
return { searchBar, textField, form };
};
describe("all stories", () => {
it("renders search bar", async () => {
- const { testRenderer } = await createTestRenderer();
- const searchBar = await waitForElement(() =>
- within(testRenderer.root).getByTestID("moderate-searchBar-container")
- );
- expect(within(searchBar).toJSON()).toMatchSnapshot();
+ let searchBar: ReactTestInstance;
+ await act(async () => {
+ const { testRenderer } = await createTestRenderer();
+ searchBar = await waitForElement(() =>
+ within(testRenderer.root).getByTestID("moderate-searchBar-container")
+ );
+ });
+ expect(within(searchBar!).toJSON()).toMatchSnapshot();
});
describe("active", () => {
@@ -109,17 +118,21 @@ describe("search bar", () => {
);
expect(within(searchBar).toJSON()).toMatchSnapshot();
- // Search for sth.
- textField.props.onChange(query);
- form.props.onSubmit();
+ await act(async () => {
+ // Search for sth.
+ textField.props.onChange(query);
+ form.props.onSubmit();
- // Ensure no results message is shown.
- await wait(() =>
- within(searchBar).getByText("No results", { exact: false })
- );
+ // Ensure no results message is shown.
+ await wait(() =>
+ within(searchBar).getByText("No results", { exact: false })
+ );
+ });
- // Blurring should close the listbox.
- textField.props.onBlur({});
+ act(() => {
+ // Blurring should close the listbox.
+ textField.props.onBlur({});
+ });
expect(within(searchBar).queryByText("No results")).toBeNull();
});
it("search with actual results", async () => {
@@ -142,24 +155,28 @@ describe("search bar", () => {
testRenderer
);
- // Search for sth.
- textField.props.onChange(query);
- form.props.onSubmit();
-
const story = storyConnection.edges[0].node;
- // Find the story in the search results.
- const storyOption = findParentWithType(
- await waitForElement(() =>
- within(searchBar).getByText(story.metadata!.title!, {
- exact: false,
- })
- ),
- "li"
- )!;
+ let storyOption: ReactTestInstance;
+
+ await act(async () => {
+ // Search for sth.
+ textField.props.onChange(query);
+ form.props.onSubmit();
+
+ // Find the story in the search results.
+ storyOption = findParentWithType(
+ await waitForElement(() =>
+ within(searchBar).getByText(story.metadata!.title!, {
+ exact: false,
+ })
+ ),
+ "li"
+ )!;
+ });
// Go to story.
- storyOption.props.onClick({ button: 0, preventDefault: noop });
+ storyOption!.props.onClick({ button: 0, preventDefault: noop });
// Expect a routing request was made to the right url.
expect(transitionControl.history[0].pathname).toBe(
@@ -188,22 +205,25 @@ describe("search bar", () => {
testRenderer
);
- // Search for sth.
- textField.props.onChange(query);
- form.props.onSubmit();
+ let seeAllOption: ReactTestInstance;
+ await act(async () => {
+ // Search for sth.
+ textField.props.onChange(query);
+ form.props.onSubmit();
- // Find see all options in the search results.
- const seeAllOption = findParentWithType(
- await waitForElement(() =>
- within(searchBar).getByText("See all results", { exact: false })
- ),
- "li"
- )!;
+ // Find see all options in the search results.
+ seeAllOption = findParentWithType(
+ await waitForElement(() =>
+ within(searchBar).getByText("See all results", { exact: false })
+ ),
+ "li"
+ )!;
+ });
- expect(within(seeAllOption).toJSON()).toMatchSnapshot();
+ expect(within(seeAllOption!).toJSON()).toMatchSnapshot();
// Go to story.
- seeAllOption.props.onClick({ button: 0, preventDefault: noop });
+ seeAllOption!.props.onClick({ button: 0, preventDefault: noop });
// Expect a routing request was made to the right url.
expect(transitionControl.history[0].pathname).toBe("/admin/stories");
@@ -218,20 +238,22 @@ describe("search bar", () => {
);
});
it("renders search bar", async () => {
- const { testRenderer } = await createTestRenderer({
- resolvers: createResolversStub
({
- Query: {
- story: () => stories[0],
- },
- }),
+ await act(async () => {
+ const { testRenderer } = await createTestRenderer({
+ resolvers: createResolversStub({
+ Query: {
+ story: () => stories[0],
+ },
+ }),
+ });
+ const searchBar = await waitForElement(() =>
+ within(testRenderer.root).getByTestID("moderate-searchBar-container")
+ );
+ const textField = within(searchBar).getByLabelText(
+ "Search or jump to story..."
+ );
+ expect(textField.props.placeholder).toBe(stories[0].metadata!.title);
});
- const searchBar = await waitForElement(() =>
- within(testRenderer.root).getByTestID("moderate-searchBar-container")
- );
- const textField = within(searchBar).getByLabelText(
- "Search or jump to story..."
- );
- expect(textField.props.placeholder).toBe(stories[0].metadata!.title);
});
it("shows moderate all option", async () => {
const {
@@ -266,46 +288,58 @@ describe("search bar", () => {
describe("tab bar", () => {
it("renders tab bar (empty queues)", async () => {
- const { testRenderer } = await createTestRenderer();
- const { getByTestID } = within(testRenderer.root);
- await waitForElement(() => getByTestID("moderate-container"));
- expect(toJSON(getByTestID("moderate-tabBar-container"))).toMatchSnapshot();
+ await act(async () => {
+ const { testRenderer } = await createTestRenderer();
+ const { getByTestID } = within(testRenderer.root);
+ await waitForElement(() => getByTestID("moderate-container"));
+ expect(
+ toJSON(getByTestID("moderate-tabBar-container"))
+ ).toMatchSnapshot();
+ });
});
it("should not show moderate story link in comment cards", async () => {
- const { testRenderer } = await createTestRenderer();
- const { getByTestID } = within(testRenderer.root);
- await waitForElement(() => getByTestID("moderate-container"));
- expect(within(testRenderer.root).queryByText("Moderate Story")).toBeNull();
+ await act(async () => {
+ const { testRenderer } = await createTestRenderer();
+ const { getByTestID } = within(testRenderer.root);
+ await waitForElement(() => getByTestID("moderate-container"));
+ expect(
+ within(testRenderer.root).queryByText("Moderate Story")
+ ).toBeNull();
+ });
});
});
describe("moderating specific story", () => {
it("passes storyID to the endpoints", async () => {
replaceHistoryLocation(`http://localhost/admin/moderate/${stories[0].id}`);
- await createTestRenderer({
- resolvers: createResolversStub({
- Query: {
- moderationQueues: ({ variables }) => {
- expectAndFail(variables.storyID).toBe(stories[0].id);
- return emptyModerationQueues;
+ await act(async () => {
+ await createTestRenderer({
+ resolvers: createResolversStub({
+ Query: {
+ moderationQueues: ({ variables }) => {
+ expectAndFail(variables.storyID).toBe(stories[0].id);
+ return emptyModerationQueues;
+ },
+ comments: ({ variables }) => {
+ expectAndFail(variables.storyID).toBe(stories[0].id);
+ return emptyRejectedComments;
+ },
},
- comments: ({ variables }) => {
- expectAndFail(variables.storyID).toBe(stories[0].id);
- return emptyRejectedComments;
- },
- },
- }),
+ }),
+ });
});
});
});
describe("reported queue", () => {
it("renders empty reported queue", async () => {
- const { testRenderer } = await createTestRenderer();
- const { getByTestID } = within(testRenderer.root);
-
- await waitForElement(() => getByTestID("moderate-container"));
- expect(toJSON(getByTestID("moderate-main-container"))).toMatchSnapshot();
+ await act(async () => {
+ const { testRenderer } = await createTestRenderer();
+ const { getByText } = within(testRenderer.root);
+ await waitForElement(() =>
+ getByText("no more reported", { exact: false })
+ );
+ });
});
it("renders empty pending queue", async () => {
@@ -334,142 +368,192 @@ describe("reported queue", () => {
});
it("renders reported queue with comments", async () => {
- const { testRenderer } = await createTestRenderer({
- resolvers: createResolversStub({
- Query: {
- moderationQueues: () =>
- pureMerge(emptyModerationQueues, {
- reported: {
- count: 2,
- comments: createQueryResolverStub<
- ModerationQueueToCommentsResolver
- >(({ variables }) => {
- expectAndFail(variables).toEqual({ first: 5 });
- return {
- edges: [
- {
- node: reportedComments[0],
- cursor: reportedComments[0].createdAt,
+ await act(async () => {
+ const { testRenderer } = await createTestRenderer({
+ resolvers: createResolversStub({
+ Query: {
+ moderationQueues: () =>
+ pureMerge(emptyModerationQueues, {
+ reported: {
+ count: 2,
+ comments: createQueryResolverStub<
+ ModerationQueueToCommentsResolver
+ >(({ variables }) => {
+ expectAndFail(variables).toEqual({ first: 5 });
+ return {
+ edges: [
+ {
+ node: reportedComments[0],
+ cursor: reportedComments[0].createdAt,
+ },
+ {
+ node: reportedComments[1],
+ cursor: reportedComments[1].createdAt,
+ },
+ ],
+ pageInfo: {
+ endCursor: reportedComments[1].createdAt,
+ hasNextPage: false,
},
- {
- node: reportedComments[1],
- cursor: reportedComments[1].createdAt,
- },
- ],
- pageInfo: {
- endCursor: reportedComments[1].createdAt,
- hasNextPage: false,
- },
- };
- }) as any,
- },
- }),
- },
- }),
+ };
+ }) as any,
+ },
+ }),
+ },
+ }),
+ });
+ const { getByTestID } = within(testRenderer.root);
+ await waitForElement(() => getByTestID("moderate-container"));
+ expect(toJSON(getByTestID("moderate-main-container"))).toMatchSnapshot();
});
- const { getByTestID } = within(testRenderer.root);
- await waitForElement(() => getByTestID("moderate-container"));
- expect(toJSON(getByTestID("moderate-main-container"))).toMatchSnapshot();
});
it("renders reported queue with comments", async () => {
- const { testRenderer } = await createTestRenderer({
- resolvers: createResolversStub({
- Query: {
- moderationQueues: () =>
- pureMerge(emptyModerationQueues, {
- reported: {
- count: 2,
- comments: createQueryResolverStub<
- ModerationQueueToCommentsResolver
- >(({ variables }) => {
- expectAndFail(variables).toEqual({ first: 5 });
- return {
- edges: [
- {
- node: reportedComments[0],
- cursor: reportedComments[0].createdAt,
+ await act(async () => {
+ const { testRenderer } = await createTestRenderer({
+ resolvers: createResolversStub({
+ Query: {
+ moderationQueues: () =>
+ pureMerge(emptyModerationQueues, {
+ reported: {
+ count: 2,
+ comments: createQueryResolverStub<
+ ModerationQueueToCommentsResolver
+ >(({ variables }) => {
+ expectAndFail(variables).toEqual({ first: 5 });
+ return {
+ edges: [
+ {
+ node: reportedComments[0],
+ cursor: reportedComments[0].createdAt,
+ },
+ {
+ node: reportedComments[1],
+ cursor: reportedComments[1].createdAt,
+ },
+ ],
+ pageInfo: {
+ endCursor: reportedComments[1].createdAt,
+ hasNextPage: false,
},
- {
- node: reportedComments[1],
- cursor: reportedComments[1].createdAt,
- },
- ],
- pageInfo: {
- endCursor: reportedComments[1].createdAt,
- hasNextPage: false,
- },
- };
- }),
- },
- }),
- },
- }),
+ };
+ }),
+ },
+ }),
+ },
+ }),
+ });
+ const { getByTestID } = within(testRenderer.root);
+ await waitForElement(() => getByTestID("moderate-container"));
+ expect(toJSON(getByTestID("moderate-main-container"))).toMatchSnapshot();
});
- const { getByTestID } = within(testRenderer.root);
- await waitForElement(() => getByTestID("moderate-container"));
- expect(toJSON(getByTestID("moderate-main-container"))).toMatchSnapshot();
});
it("show details of comment with flags", async () => {
- const { testRenderer } = await createTestRenderer({
- resolvers: createResolversStub({
- Query: {
- moderationQueues: () =>
- pureMerge(emptyModerationQueues, {
- reported: {
- count: 1,
- comments: createQueryResolverStub<
- ModerationQueueToCommentsResolver
- >(({ variables }) => {
- expectAndFail(variables).toEqual({ first: 5 });
- return {
- edges: [
- {
- node: reportedComments[0],
- cursor: reportedComments[0].createdAt,
+ await act(async () => {
+ const { testRenderer } = await createTestRenderer({
+ resolvers: createResolversStub({
+ Query: {
+ moderationQueues: () =>
+ pureMerge(emptyModerationQueues, {
+ reported: {
+ count: 1,
+ comments: createQueryResolverStub<
+ ModerationQueueToCommentsResolver
+ >(({ variables }) => {
+ expectAndFail(variables).toEqual({ first: 5 });
+ return {
+ edges: [
+ {
+ node: reportedComments[0],
+ cursor: reportedComments[0].createdAt,
+ },
+ ],
+ pageInfo: {
+ endCursor: reportedComments[0].createdAt,
+ hasNextPage: false,
},
- ],
- pageInfo: {
- endCursor: reportedComments[0].createdAt,
- hasNextPage: false,
- },
- };
- }),
- },
- }),
- },
- }),
- });
- const { getByTestID } = within(testRenderer.root);
- const reported = await waitForElement(() =>
- getByTestID(`moderate-comment-${reportedComments[0].id}`)
- );
- expect(
- within(reported).queryByText(
+ };
+ }),
+ },
+ }),
+ },
+ }),
+ });
+ const { getByTestID } = within(testRenderer.root);
+ const reported = await waitForElement(() =>
+ getByTestID(`moderate-comment-${reportedComments[0].id}`)
+ );
+ expect(
+ within(reported).queryByText(
+ reportedComments[0].flags.nodes[0].additionalDetails!
+ )
+ ).toBeNull();
+ within(reported)
+ .getByText("Details", { selector: "button" })
+ .props.onClick();
+ within(reported).getByText(
reportedComments[0].flags.nodes[0].additionalDetails!
- )
- ).toBeNull();
- within(reported)
- .getByText("Details", { selector: "button" })
- .props.onClick();
- within(reported).getByText(
- reportedComments[0].flags.nodes[0].additionalDetails!
- );
+ );
+ });
});
it("shows a moderate story", async () => {
- const {
- testRenderer,
- context: { transitionControl },
- } = await createTestRenderer({
- resolvers: createResolversStub({
- Query: {
- moderationQueues: () =>
- pureMerge(emptyModerationQueues, {
- reported: {
- count: 2,
- comments: createQueryResolverStub<
- ModerationQueueToCommentsResolver
- >(({ variables }) => {
+ await act(async () => {
+ const {
+ testRenderer,
+ context: { transitionControl },
+ } = await createTestRenderer({
+ resolvers: createResolversStub({
+ Query: {
+ moderationQueues: () =>
+ pureMerge(emptyModerationQueues, {
+ reported: {
+ count: 2,
+ comments: createQueryResolverStub<
+ ModerationQueueToCommentsResolver
+ >(({ variables }) => {
+ expectAndFail(variables).toEqual({ first: 5 });
+ return {
+ edges: [
+ {
+ node: reportedComments[0],
+ cursor: reportedComments[0].createdAt,
+ },
+ {
+ node: reportedComments[1],
+ cursor: reportedComments[1].createdAt,
+ },
+ ],
+ pageInfo: {
+ endCursor: reportedComments[1].createdAt,
+ hasNextPage: false,
+ },
+ };
+ }) as any,
+ },
+ }),
+ },
+ }),
+ });
+ const moderateStory = await waitForElement(
+ () => within(testRenderer.root).getAllByText("Moderate Story")[0]
+ );
+ transitionControl.allowTransition = false;
+ moderateStory.props.onClick({});
+ // Expect a routing request was made to the right url.
+ expect(transitionControl.history[0].pathname).toBe(
+ `/admin/moderate/${reportedComments[0].story.id}`
+ );
+ });
+ });
+ it("renders reported queue with comments and load more", async () => {
+ await act(async () => {
+ const moderationQueuesStub = pureMerge(emptyModerationQueues, {
+ reported: {
+ count: 2,
+ comments: createQueryResolverStub(
+ ({ variables, callCount }) => {
+ switch (callCount) {
+ case 0:
expectAndFail(variables).toEqual({ first: 5 });
return {
edges: [
@@ -484,273 +568,237 @@ describe("reported queue", () => {
],
pageInfo: {
endCursor: reportedComments[1].createdAt,
+ hasNextPage: true,
+ },
+ };
+ default:
+ expectAndFail(variables).toEqual({
+ first: 10,
+ after: reportedComments[1].createdAt,
+ });
+ return {
+ edges: [
+ {
+ node: reportedComments[2],
+ cursor: reportedComments[2].createdAt,
+ },
+ ],
+ pageInfo: {
+ endCursor: reportedComments[2].createdAt,
hasNextPage: false,
},
};
- }) as any,
- },
- }),
- },
- }),
- });
- const moderateStory = await waitForElement(
- () => within(testRenderer.root).getAllByText("Moderate Story")[0]
- );
- transitionControl.allowTransition = false;
- moderateStory.props.onClick({});
- // Expect a routing request was made to the right url.
- expect(transitionControl.history[0].pathname).toBe(
- `/admin/moderate/${reportedComments[0].story.id}`
- );
- });
- it("renders reported queue with comments and load more", async () => {
- const moderationQueuesStub = pureMerge(emptyModerationQueues, {
- reported: {
- count: 2,
- comments: createQueryResolverStub(
- ({ variables, callCount }) => {
- switch (callCount) {
- case 0:
- expectAndFail(variables).toEqual({ first: 5 });
- return {
- edges: [
- {
- node: reportedComments[0],
- cursor: reportedComments[0].createdAt,
- },
- {
- node: reportedComments[1],
- cursor: reportedComments[1].createdAt,
- },
- ],
- pageInfo: {
- endCursor: reportedComments[1].createdAt,
- hasNextPage: true,
- },
- };
- default:
- expectAndFail(variables).toEqual({
- first: 10,
- after: reportedComments[1].createdAt,
- });
- return {
- edges: [
- {
- node: reportedComments[2],
- cursor: reportedComments[2].createdAt,
- },
- ],
- pageInfo: {
- endCursor: reportedComments[2].createdAt,
- hasNextPage: false,
- },
- };
+ }
}
- }
- ) as any,
- },
- });
-
- const { testRenderer } = await createTestRenderer({
- resolvers: createResolversStub({
- Query: {
- moderationQueues: () => moderationQueuesStub,
+ ) as any,
},
- }),
+ });
+
+ const { testRenderer } = await createTestRenderer({
+ resolvers: createResolversStub({
+ Query: {
+ moderationQueues: () => moderationQueuesStub,
+ },
+ }),
+ });
+ const moderateContainer = await waitForElement(() =>
+ within(testRenderer.root).getByTestID("moderate-container")
+ );
+
+ const { getByText, getAllByTestID, getByTestID } = within(
+ moderateContainer
+ );
+
+ // Get previous count of comments.
+ const previousCount = getAllByTestID(/^moderate-comment-.*$/).length;
+
+ const loadMore = await waitForElement(() => getByText("Load More"));
+ loadMore.props.onClick();
+
+ // Wait for load more to disappear.
+ await waitUntilThrow(() => getByText("Load More"));
+
+ // Verify we have one more item now.
+ const comments = getAllByTestID(/^moderate-comment-.*$/);
+ expect(comments.length).toBe(previousCount + 1);
+
+ // Verify last one added was our new one
+ expect(comments[comments.length - 1].props["data-testid"]).toBe(
+ `moderate-comment-${reportedComments[2].id}`
+ );
+
+ // Snapshot of added comment.
+ expect(
+ toJSON(getByTestID(`moderate-comment-${reportedComments[2].id}`))
+ ).toMatchSnapshot();
});
- const moderateContainer = await waitForElement(() =>
- within(testRenderer.root).getByTestID("moderate-container")
- );
-
- const { getByText, getAllByTestID, getByTestID } = within(
- moderateContainer
- );
-
- // Get previous count of comments.
- const previousCount = getAllByTestID(/^moderate-comment-.*$/).length;
-
- const loadMore = await waitForElement(() => getByText("Load More"));
- loadMore.props.onClick();
-
- // Wait for load more to disappear.
- await waitUntilThrow(() => getByText("Load More"));
-
- // Verify we have one more item now.
- const comments = getAllByTestID(/^moderate-comment-.*$/);
- expect(comments.length).toBe(previousCount + 1);
-
- // Verify last one added was our new one
- expect(comments[comments.length - 1].props["data-testid"]).toBe(
- `moderate-comment-${reportedComments[2].id}`
- );
-
- // Snapshot of added comment.
- expect(
- toJSON(getByTestID(`moderate-comment-${reportedComments[2].id}`))
- ).toMatchSnapshot();
});
it("approves comment in reported queue", async () => {
- const approveCommentStub = createMutationResolverStub<
- MutationToApproveCommentResolver
- >(({ variables }) => {
- expectAndFail(variables).toMatchObject({
- commentID: reportedComments[0].id,
- commentRevisionID: reportedComments[0].revision.id,
+ await act(async () => {
+ const approveCommentStub = createMutationResolverStub<
+ MutationToApproveCommentResolver
+ >(({ variables }) => {
+ expectAndFail(variables).toMatchObject({
+ commentID: reportedComments[0].id,
+ commentRevisionID: reportedComments[0].revision.id,
+ });
+ return {
+ comment: {
+ id: reportedComments[0].id,
+ status: GQLCOMMENT_STATUS.APPROVED,
+ },
+ moderationQueues: pureMerge(emptyModerationQueues, {
+ reported: {
+ count: 1,
+ },
+ }),
+ };
});
- return {
- comment: {
- id: reportedComments[0].id,
- status: GQLCOMMENT_STATUS.APPROVED,
+
+ const moderationQueuesStub = pureMerge(emptyModerationQueues, {
+ reported: {
+ count: 2,
+ comments: createQueryResolverStub(
+ ({ variables }) => {
+ expectAndFail(variables).toEqual({ first: 5 });
+ return {
+ edges: [
+ {
+ node: reportedComments[0],
+ cursor: reportedComments[0].createdAt,
+ },
+ {
+ node: reportedComments[1],
+ cursor: reportedComments[1].createdAt,
+ },
+ ],
+ pageInfo: {
+ endCursor: reportedComments[1].createdAt,
+ hasNextPage: false,
+ },
+ };
+ }
+ ) as any,
},
- moderationQueues: pureMerge(emptyModerationQueues, {
- reported: {
- count: 1,
+ });
+
+ const { testRenderer } = await createTestRenderer({
+ resolvers: createResolversStub({
+ Query: {
+ moderationQueues: () => moderationQueuesStub,
+ },
+ Mutation: {
+ approveComment: approveCommentStub,
},
}),
- };
+ });
+
+ const testID = `moderate-comment-${reportedComments[0].id}`;
+ const { getByTestID } = within(testRenderer.root);
+ const comment = await waitForElement(() => getByTestID(testID));
+
+ const ApproveButton = await waitForElement(() =>
+ within(comment).getByLabelText("Approve")
+ );
+ ApproveButton.props.onClick();
+
+ // Snapshot dangling state of comment.
+ expect(toJSON(comment)).toMatchSnapshot("dangling");
+
+ // Wait until comment is gone.
+ await waitUntilThrow(() => getByTestID(testID));
+
+ expect(approveCommentStub.called).toBe(true);
+
+ // Count should have been updated.
+ expect(
+ toJSON(getByTestID("moderate-navigation-reported-count"))
+ ).toMatchSnapshot("count should be 1");
});
-
- const moderationQueuesStub = pureMerge(emptyModerationQueues, {
- reported: {
- count: 2,
- comments: createQueryResolverStub(
- ({ variables }) => {
- expectAndFail(variables).toEqual({ first: 5 });
- return {
- edges: [
- {
- node: reportedComments[0],
- cursor: reportedComments[0].createdAt,
- },
- {
- node: reportedComments[1],
- cursor: reportedComments[1].createdAt,
- },
- ],
- pageInfo: {
- endCursor: reportedComments[1].createdAt,
- hasNextPage: false,
- },
- };
- }
- ) as any,
- },
- });
-
- const { testRenderer } = await createTestRenderer({
- resolvers: createResolversStub({
- Query: {
- moderationQueues: () => moderationQueuesStub,
- },
- Mutation: {
- approveComment: approveCommentStub,
- },
- }),
- });
-
- const testID = `moderate-comment-${reportedComments[0].id}`;
- const { getByTestID } = within(testRenderer.root);
- const comment = await waitForElement(() => getByTestID(testID));
-
- const ApproveButton = await waitForElement(() =>
- within(comment).getByLabelText("Approve")
- );
- ApproveButton.props.onClick();
-
- // Snapshot dangling state of comment.
- expect(toJSON(comment)).toMatchSnapshot("dangling");
-
- // Wait until comment is gone.
- await waitUntilThrow(() => getByTestID(testID));
-
- expect(approveCommentStub.called).toBe(true);
-
- // Count should have been updated.
- expect(
- toJSON(getByTestID("moderate-navigation-reported-count"))
- ).toMatchSnapshot("count should be 1");
});
it("rejects comment in reported queue", async () => {
- const rejectCommentStub = createMutationResolverStub<
- MutationToRejectCommentResolver
- >(({ variables }) => {
- expectAndFail(variables).toMatchObject({
- commentID: reportedComments[0].id,
- commentRevisionID: reportedComments[0].revision.id,
+ await act(async () => {
+ const rejectCommentStub = createMutationResolverStub<
+ MutationToRejectCommentResolver
+ >(({ variables }) => {
+ expectAndFail(variables).toMatchObject({
+ commentID: reportedComments[0].id,
+ commentRevisionID: reportedComments[0].revision.id,
+ });
+ return {
+ comment: {
+ id: reportedComments[0].id,
+ status: GQLCOMMENT_STATUS.REJECTED,
+ },
+ moderationQueues: pureMerge(emptyModerationQueues, {
+ reported: {
+ count: 1,
+ },
+ }),
+ };
});
- return {
- comment: {
- id: reportedComments[0].id,
- status: GQLCOMMENT_STATUS.REJECTED,
- },
- moderationQueues: pureMerge(emptyModerationQueues, {
- reported: {
- count: 1,
+
+ const { testRenderer } = await createTestRenderer({
+ resolvers: createResolversStub({
+ Query: {
+ moderationQueues: () =>
+ pureMerge(emptyModerationQueues, {
+ reported: {
+ count: 2,
+ comments: createQueryResolverStub<
+ ModerationQueueToCommentsResolver
+ >(({ variables }) => {
+ expectAndFail(variables).toEqual({ first: 5 });
+ return {
+ edges: [
+ {
+ node: reportedComments[0],
+ cursor: reportedComments[0].createdAt,
+ },
+ {
+ node: reportedComments[1],
+ cursor: reportedComments[1].createdAt,
+ },
+ ],
+ pageInfo: {
+ endCursor: reportedComments[1].createdAt,
+ hasNextPage: false,
+ },
+ };
+ }) as any,
+ },
+ }),
+ },
+ Mutation: {
+ rejectComment: rejectCommentStub,
},
}),
- };
+ });
+
+ const testID = `moderate-comment-${reportedComments[0].id}`;
+ const { getByTestID } = within(testRenderer.root);
+ const comment = await waitForElement(() => getByTestID(testID));
+
+ const RejectButton = await waitForElement(() =>
+ within(comment).getByLabelText("Reject")
+ );
+ RejectButton.props.onClick();
+
+ // Snapshot dangling state of comment.
+ expect(toJSON(comment)).toMatchSnapshot("dangling");
+
+ // Wait until comment is gone.
+ await waitUntilThrow(() => getByTestID(testID));
+
+ expect(rejectCommentStub.called).toBe(true);
+
+ // Count should have been updated.
+ expect(
+ toJSON(getByTestID("moderate-navigation-reported-count"))
+ ).toMatchSnapshot("count should be 1");
});
-
- const { testRenderer } = await createTestRenderer({
- resolvers: createResolversStub({
- Query: {
- moderationQueues: () =>
- pureMerge(emptyModerationQueues, {
- reported: {
- count: 2,
- comments: createQueryResolverStub<
- ModerationQueueToCommentsResolver
- >(({ variables }) => {
- expectAndFail(variables).toEqual({ first: 5 });
- return {
- edges: [
- {
- node: reportedComments[0],
- cursor: reportedComments[0].createdAt,
- },
- {
- node: reportedComments[1],
- cursor: reportedComments[1].createdAt,
- },
- ],
- pageInfo: {
- endCursor: reportedComments[1].createdAt,
- hasNextPage: false,
- },
- };
- }) as any,
- },
- }),
- },
- Mutation: {
- rejectComment: rejectCommentStub,
- },
- }),
- });
-
- const testID = `moderate-comment-${reportedComments[0].id}`;
- const { getByTestID } = within(testRenderer.root);
- const comment = await waitForElement(() => getByTestID(testID));
-
- const RejectButton = await waitForElement(() =>
- within(comment).getByLabelText("Reject")
- );
- RejectButton.props.onClick();
-
- // Snapshot dangling state of comment.
- expect(toJSON(comment)).toMatchSnapshot("dangling");
-
- // Wait until comment is gone.
- await waitUntilThrow(() => getByTestID(testID));
-
- expect(rejectCommentStub.called).toBe(true);
-
- // Count should have been updated.
- expect(
- toJSON(getByTestID("moderate-navigation-reported-count"))
- ).toMatchSnapshot("count should be 1");
});
});
diff --git a/src/core/client/admin/test/stories/stories.spec.tsx b/src/core/client/admin/test/stories/stories.spec.tsx
index 65a7d876f..824993ba4 100644
--- a/src/core/client/admin/test/stories/stories.spec.tsx
+++ b/src/core/client/admin/test/stories/stories.spec.tsx
@@ -1,8 +1,8 @@
import { noop } from "lodash";
-import TestRenderer from "react-test-renderer";
import { pureMerge } from "coral-common/utils";
import {
+ act,
createMutationResolverStub,
createResolversStub,
CreateTestRendererParams,
@@ -92,10 +92,11 @@ it("goes to moderation when clicking on title", async () => {
transitionControl.allowTransition = false;
const story = storyConnection.edges[0].node;
- within(container)
- .getByText(story.metadata!.title!)
- .props.onClick({ button: 0, preventDefault: noop });
-
+ act(() => {
+ within(container)
+ .getByText(story.metadata!.title!)
+ .props.onClick({ button: 0, preventDefault: noop });
+ });
// Expect a routing request was made to the right url.
expect(transitionControl.history[0].pathname).toBe(
`/admin/moderate/${story.id}`
@@ -122,17 +123,14 @@ it("filter by status", async () => {
const selectField = within(container).getByLabelText("Search by status");
const closedOption = within(selectField).getByText("Closed Stories");
- TestRenderer.act(() => {
+ await act(async () => {
selectField.props.onChange({
target: { value: closedOption.props.value.toString() },
});
- // TODO: Fix act warnings until await Promise.resolve();
- // or whatever comes out at https://github.com/facebook/react/issues/14769
+ await waitForElement(() =>
+ within(container).getByText("could not find any", { exact: false })
+ );
});
-
- await waitForElement(() =>
- within(container).getByText("could not find any", { exact: false })
- );
});
it("change story status", async () => {
@@ -185,11 +183,11 @@ it("change story status", async () => {
);
/** CLOSE STORY */
- TestRenderer.act(() => {
+ act(() => {
changeStatusButton.props.onClick();
});
- TestRenderer.act(() => {
+ act(() => {
within(popup)
.getByText("Closed", { selector: "button" })
.props.onClick();
@@ -199,11 +197,11 @@ it("change story status", async () => {
expect(closeStory.called).toBe(true);
/** OPEN STORY */
- TestRenderer.act(() => {
+ act(() => {
changeStatusButton.props.onClick();
});
- TestRenderer.act(() => {
+ act(() => {
within(popup)
.getByText("Open", { selector: "button" })
.props.onClick();
@@ -244,13 +242,12 @@ it("load more", async () => {
}),
});
const loadMore = within(container).getByText("Load More");
- TestRenderer.act(() => {
+ await act(async () => {
loadMore.props.onClick();
+ // Wait for load more to disappear.
+ await waitUntilThrow(() => within(container).getByText("Load More"));
});
- // Wait for load more to disappear.
- await waitUntilThrow(() => within(container).getByText("Load More"));
-
// Make sure third user was added.
within(container).getByText(stories[2].metadata!.title!);
});
@@ -278,16 +275,15 @@ it("filter by search", async () => {
);
const form = findParentWithType(searchField, "form")!;
- TestRenderer.act(() => {
+ await act(async () => {
searchField.props.onChange({
target: { value: "search" },
});
form.props.onSubmit();
+ await waitForElement(() =>
+ within(container).getByText("could not find any", { exact: false })
+ );
});
-
- await waitForElement(() =>
- within(container).getByText("could not find any", { exact: false })
- );
});
it("use searchFilter from url", async () => {
diff --git a/src/core/client/auth/test/forgotPassword.spec.tsx b/src/core/client/auth/test/forgotPassword.spec.tsx
index 7cebfed52..3d39552b7 100644
--- a/src/core/client/auth/test/forgotPassword.spec.tsx
+++ b/src/core/client/auth/test/forgotPassword.spec.tsx
@@ -1,9 +1,9 @@
-import { act } from "react-test-renderer";
import sinon from "sinon";
import { pureMerge } from "coral-common/utils";
import { GQLResolver } from "coral-framework/schema";
import {
+ act,
createResolversStub,
CreateTestRendererParams,
wait,
@@ -134,14 +134,14 @@ it("submits form successfully", async () => {
})
.once();
- act(() => {
+ await act(async () => {
emailField.props.onChange("hans@test.com");
form!.props.onSubmit();
+ await waitForElement(() =>
+ within(testRenderer.root).getByText("Check Your Email", { exact: false })
+ );
});
- await waitForElement(() =>
- within(testRenderer.root).getByText("Check Your Email", { exact: false })
- );
within(testRenderer.root)
.getByText("Close")
.props.onClick();
diff --git a/src/core/client/framework/testHelpers/act.ts b/src/core/client/framework/testHelpers/act.ts
new file mode 100644
index 000000000..38dfbf01f
--- /dev/null
+++ b/src/core/client/framework/testHelpers/act.ts
@@ -0,0 +1,7 @@
+import TestRenderer from "react-test-renderer";
+
+export default function act(
+ callback: () => Promise | void | undefined
+): Promise | void {
+ return TestRenderer.act(callback as any) as any;
+}
diff --git a/src/core/client/framework/testHelpers/index.ts b/src/core/client/framework/testHelpers/index.ts
index 7a9b9d109..62225877d 100644
--- a/src/core/client/framework/testHelpers/index.ts
+++ b/src/core/client/framework/testHelpers/index.ts
@@ -10,6 +10,7 @@ export {
} from "./removeFragmentRefs";
export { default as createUUIDGenerator } from "./createUUIDGenerator";
export * from "./denormalize";
+export { default as act } from "./act";
export { default as limitSnapshotTo } from "./limitSnapshotTo";
export { default as within } from "./within";
export { default as wait } from "./wait";
diff --git a/src/core/client/stream/test/comments/stream/ignoreUser.spec.tsx b/src/core/client/stream/test/comments/stream/ignoreUser.spec.tsx
index cc74aafce..fff29dbc4 100644
--- a/src/core/client/stream/test/comments/stream/ignoreUser.spec.tsx
+++ b/src/core/client/stream/test/comments/stream/ignoreUser.spec.tsx
@@ -1,6 +1,7 @@
import { pureMerge } from "coral-common/utils";
import { GQLResolver } from "coral-framework/schema";
import {
+ act,
createResolversStub,
CreateTestRendererParams,
waitForElement,
@@ -69,23 +70,29 @@ it("ignore user", async () => {
const username = within(comment).getByText(firstCommentAuthor.username!, {
selector: "button",
});
- username.props.onClick();
+ act(() => {
+ username.props.onClick();
+ });
const ignoreButton = within(comment).getByText("Ignore", {
selector: "button",
});
- ignoreButton.props.onClick();
+ act(() => {
+ ignoreButton.props.onClick();
+ });
within(comment).getByText("Cancel", {
selector: "button",
});
- within(comment)
- .getByText("Ignore", {
- selector: "button",
- })
- .props.onClick();
- // Check for a tombstone
- await waitForElement(() =>
- within(tabPane).getByText("This comment is hidden", { exact: false })
- );
+ await act(async () => {
+ within(comment)
+ .getByText("Ignore", {
+ selector: "button",
+ })
+ .props.onClick();
+ // Check for a tombstone
+ await waitForElement(() =>
+ within(tabPane).getByText("This comment is hidden", { exact: false })
+ );
+ });
});
it("render stream with ignored user", async () => {
diff --git a/src/core/client/ui/components/MatchMedia/__snapshots__/MatchMedia.spec.tsx.snap b/src/core/client/ui/components/MatchMedia/__snapshots__/MatchMedia.spec.tsx.snap
index 88670e33f..516f3ae04 100644
--- a/src/core/client/ui/components/MatchMedia/__snapshots__/MatchMedia.spec.tsx.snap
+++ b/src/core/client/ui/components/MatchMedia/__snapshots__/MatchMedia.spec.tsx.snap
@@ -1,38 +1,35 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`map new speech prop to older aural prop 1`] = `
-
Hello World
-
+
`;
exports[`renders correctly 1`] = `
-
Hello World
-
+
`;
exports[`renders less than and great than correctly 1`] = `
-
Hello World
-
+
`;