mirror of
https://github.com/wassname/talk.git
synced 2026-07-31 12:50:48 +08:00
[CORL-729] Upgrade Final Form & improve tests (#2735)
* CORL-729 Upgrade final form, fix and improve tests This is a squashed rebase from these commits: a300b31c23ab11e5e6f0668bc03ece7697360aaa feat: error on optimisic response warnings during test dd8a9776865ec41d346e23ae0743d0d4fb0caa21 fix: turn off @typescript-eslint/prefer-regexp-exec rule b995daacf1722cace60d755e672cb6a3a20d6bc2 feat: mute false warnings in test e44f9e28307cd63a82c1fb7ac013667dd7b7bc46 fix: wrap remaining tests with act afbd4329b97f3dbc9f873ea4ff234d98bb651ccf feat: fail when act(async () => ...) without await warnings 51dfb60b7d75411ba2e1a28db33f4aba5cf84de1 feat: fail tests with act warnings 97f93546ed8113e207882411eb4cdb7675b0796c fix: mock window.resizeTo globally in tests 850958b8c4d2fc0aca67ae580296433af223f8ab fix: more tests with act 24c05ab88e9a416e4962acc3f20f2c764ba07657 fix: wrap charCountEditComment test in acts ed590b82d147470bba74055dc682e6b70d2e76fb fix signInWithEmail 4a2b9402cb6ce9565d99ae1a950eaa422ff603c3 fix: PostCommentFormContainer 815ebe6ef364d954d4bd0a35495934c9d014170b fix: use final form initialize instead of reset and remove obsolete d3101f2112ed3ffe8d06609620e31e6655d2cf6d Merge branch 'feature/CORL-729-final-form' of https://github.com/coralproject/talk into feature/CORL-729-final-form a0658da610a5f39b6fae78ffb8dd291b22d54e50 fix: addEmailAddress 60f7fc99a44dfa49dfd401a0ef49c60973b3e8e3 fix: use proper act pattern in renderConfigure.spec.tsx d66bdfc2245c2b1ee03a1b3a3a56f1d5ba14ddc4 Stop propagation of Modal content click events (#2706) ec6689594136e22a5b9f05ea284162702dc4955d fix: use proper act pattern in createUsername.spec.tsx ef239496964a5f9a91ee1c4424ad81537c4f47fe fix: stream configuration c7e06a0c6aef6b299c41392af81f8a20855028bf fix: user proper act pattern in streamConfiguration 9712e659e394a898500ed649464ff14d4870e589 Merge branch 'feature/CORL-729-final-form' of https://github.com/coralproject/talk into feature/CORL-729-final-form 9e5cfbaf3593615b457055de23f187fa07edd4c4 fix: signIn test 99b44a4a1bbb7ff2cd44c6821ad33b80f90c4a99 fix: user proper act pattern in stories.spec.tsx ed7c1a92f93ab9aaa85ff92837b0ed21560cb358 fix: user proper act pattern in addEmailAddress a04b392cb2148b9a24791b062027796c409d053e fix: remove obsolete snapshots 59df67c0f9b9d26c74e2cca7d333f5868b0b202d fix: signUp test 7656f179df95b4cd96b37afbc88a1c3a2944fdf4 fix: use proper act pattern on createPassword 85246fbf1f9ab49ad3a09c11ab79bf537059b548 fix: use correct act() pattern in createUsername.spec.tsx d5239373a2d1bbed0bfe8c1ca62ef6a70ef5c7d9 fix: the correct way to use act on form submit :-) d84ecd168354f4acb422a5ddb725fb8faf9c3184 fix: moderation test d8df62ab1a6486144684ff917c47e6e375ffbe03 fix: reportComment test 2756e3184bb292168e8d34e201f340c3799941e6 fix: auth tests a28695dbdd313a7bc3dade9ac1f92d6ef0061526 Properly handle final-form actions in tests 2fafc8ea3458c5b15b66f3d65f0947672dd1a516 Update snapshots now that final form isn't overwriting props 1f9bbaec8678a7653124898ba4a2e84ddc1ef243 fix: prevent final form from overwriting field props f6c66c003d1917db2dcb3f757e8a303266c381fa fix: prevent final form fields overwrite out props 48d1fc7318ee4ba7bf72839127e9a0b1487c1729 chore: rename translation string 728373da5728a4e7c039bd0c3a3cf0037e9f5177 fix: purge relay metadata from request 7cdea925087a6b9b6e318bbb1b31b798be87dc2f fix: radiobuttons 9735bae79222219a81a28d458976a596201b650b chore: revert obsolete checks 0b556e1693584430a5814e81d87b0f233efd1a30 fix: refactor admin configure b245afc7b196035bcb454e031c966e63c77ce522 fix: implement withForm HOC 5787400051211f5d2e1773d7207f32b66b02a2a1 Update the Configure page form state to properly load form values 8c2af3e22a96a3d2e50e7f06fb45d1fb79cf0c8e Replace form.reset() with setTimeout(form.reset) 27d9c90e3f0166cc2db45db461619be15a3cb950 Update radio buttons and on/off fields to work with final-form updates b852dd14af85b14ff8e0d2823e1e83bf278b29b9 Replace any on OnSubmit with typed form submission interfaces f049a70aaf4872825ac3b2aa62dc5cb7f945290a (f) Preliminarily get Coral compiling with latest final-form libraries * feat: act is now actAndReturn * fix: print original filename and line number in custom console impl * feat: trace process warnings * fix: server warnings about potentially memory leak with too many listeners
This commit is contained in:
@@ -563,7 +563,7 @@ exports[`successfully sets email 1`] = `
|
||||
onFocus={[Function]}
|
||||
placeholder="Email Address"
|
||||
type="text"
|
||||
value=""
|
||||
value="hans@test.com"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -589,7 +589,7 @@ exports[`successfully sets email 1`] = `
|
||||
onFocus={[Function]}
|
||||
placeholder="Confirm Email Address"
|
||||
type="text"
|
||||
value=""
|
||||
value="hans@test.com"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -466,7 +466,7 @@ we require users to create a password.
|
||||
placeholder="Password"
|
||||
spellCheck={false}
|
||||
type="password"
|
||||
value=""
|
||||
value="secretpassword"
|
||||
/>
|
||||
<div
|
||||
className="PasswordField-icon"
|
||||
|
||||
@@ -362,7 +362,7 @@ exports[`successfully sets username 1`] = `
|
||||
onFocus={[Function]}
|
||||
placeholder="Username"
|
||||
type="text"
|
||||
value=""
|
||||
value="hans"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
act,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
replaceHistoryLocation,
|
||||
@@ -42,35 +43,50 @@ async function createTestRenderer(
|
||||
},
|
||||
});
|
||||
|
||||
const container = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("completeAccountBox")
|
||||
);
|
||||
const form = within(container).getByType("form");
|
||||
const emailAddressField = within(form).getByLabelText("Email Address");
|
||||
const confirmEmailAddressField = within(form).getByLabelText(
|
||||
"Confirm Email Address"
|
||||
);
|
||||
return await act(async () => {
|
||||
const container = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("completeAccountBox")
|
||||
);
|
||||
const form = within(container).getByType("form");
|
||||
const emailAddressField = within(form).getByLabelText("Email Address");
|
||||
const confirmEmailAddressField = within(form).getByLabelText(
|
||||
"Confirm Email Address"
|
||||
);
|
||||
|
||||
return {
|
||||
context,
|
||||
testRenderer,
|
||||
form,
|
||||
root: testRenderer.root,
|
||||
emailAddressField,
|
||||
confirmEmailAddressField,
|
||||
container,
|
||||
};
|
||||
return {
|
||||
context,
|
||||
testRenderer,
|
||||
form,
|
||||
root: testRenderer.root,
|
||||
emailAddressField,
|
||||
confirmEmailAddressField,
|
||||
container,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
it("renders addEmailAddress view", async () => {
|
||||
const { root } = await createTestRenderer();
|
||||
expect(toJSON(root)).toMatchSnapshot();
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(toJSON(root)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("shows error when submitting empty form", async () => {
|
||||
const { form } = await createTestRenderer();
|
||||
form.props.onSubmit();
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("checks for invalid email", async () => {
|
||||
@@ -79,19 +95,42 @@ it("checks for invalid email", async () => {
|
||||
emailAddressField,
|
||||
confirmEmailAddressField,
|
||||
} = await createTestRenderer();
|
||||
emailAddressField.props.onChange({ target: { value: "invalid-email" } });
|
||||
confirmEmailAddressField.props.onChange({
|
||||
target: { value: "invalid-confirmation-email" },
|
||||
|
||||
act(() =>
|
||||
emailAddressField.props.onChange({ target: { value: "invalid-email" } })
|
||||
);
|
||||
act(() =>
|
||||
confirmEmailAddressField.props.onChange({
|
||||
target: { value: "invalid-confirmation-email" },
|
||||
})
|
||||
);
|
||||
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
form.props.onSubmit();
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("accepts valid email", async () => {
|
||||
const { form, emailAddressField } = await createTestRenderer();
|
||||
emailAddressField.props.onChange({ target: { value: "hans@test.com" } });
|
||||
form.props.onSubmit();
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
|
||||
act(() =>
|
||||
emailAddressField.props.onChange({ target: { value: "hans@test.com" } })
|
||||
);
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("shows server error", async () => {
|
||||
@@ -116,18 +155,25 @@ it("shows server error", async () => {
|
||||
i => i.type === "button" && i.props.type === "submit"
|
||||
);
|
||||
|
||||
emailAddressField.props.onChange({ target: { value: email } });
|
||||
confirmEmailAddressField.props.onChange({
|
||||
target: { value: email },
|
||||
});
|
||||
act(() => emailAddressField.props.onChange({ target: { value: email } }));
|
||||
act(() =>
|
||||
confirmEmailAddressField.props.onChange({
|
||||
target: { value: email },
|
||||
})
|
||||
);
|
||||
|
||||
form.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
expect(emailAddressField.props.disabled).toBe(true);
|
||||
expect(confirmEmailAddressField.props.disabled).toBe(true);
|
||||
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(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -160,17 +206,25 @@ it("successfully sets email", async () => {
|
||||
i => i.type === "button" && i.props.type === "submit"
|
||||
);
|
||||
|
||||
emailAddressField.props.onChange({ target: { value: email } });
|
||||
confirmEmailAddressField.props.onChange({
|
||||
target: { value: email },
|
||||
});
|
||||
act(() => emailAddressField.props.onChange({ target: { value: email } }));
|
||||
act(() =>
|
||||
confirmEmailAddressField.props.onChange({
|
||||
target: { value: email },
|
||||
})
|
||||
);
|
||||
|
||||
form.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
expect(emailAddressField.props.disabled).toBe(true);
|
||||
expect(confirmEmailAddressField.props.disabled).toBe(true);
|
||||
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(toJSON(form)).toMatchSnapshot();
|
||||
expect(resolvers.Mutation!.setEmail!.called).toBe(true);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
act,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
replaceHistoryLocation,
|
||||
@@ -42,50 +43,71 @@ async function createTestRenderer(
|
||||
},
|
||||
});
|
||||
|
||||
const container = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("completeAccountBox")
|
||||
);
|
||||
const form = within(container).getByType("form");
|
||||
const passwordField = within(form).getByLabelText("Password");
|
||||
return await act(async () => {
|
||||
const container = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("completeAccountBox")
|
||||
);
|
||||
const form = within(container).getByType("form");
|
||||
const passwordField = within(form).getByLabelText("Password");
|
||||
|
||||
return {
|
||||
context,
|
||||
testRenderer,
|
||||
form,
|
||||
root: testRenderer.root,
|
||||
passwordField,
|
||||
container,
|
||||
};
|
||||
return {
|
||||
context,
|
||||
testRenderer,
|
||||
form,
|
||||
root: testRenderer.root,
|
||||
passwordField,
|
||||
container,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
it("renders createPassword view", async () => {
|
||||
const { root } = await createTestRenderer();
|
||||
expect(toJSON(root)).toMatchSnapshot();
|
||||
|
||||
await act(async () => {
|
||||
await wait(async () => {
|
||||
expect(toJSON(root)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("shows error when submitting empty form", async () => {
|
||||
const { form } = await createTestRenderer();
|
||||
form.props.onSubmit();
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(async () => {
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("checks for invalid password", async () => {
|
||||
const { form, passwordField } = await createTestRenderer();
|
||||
passwordField.props.onChange({ target: { value: "x" } });
|
||||
form.props.onSubmit();
|
||||
|
||||
act(() => passwordField.props.onChange({ target: { value: "x" } }));
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {});
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("shows server error", async () => {
|
||||
const password = "secretpassword";
|
||||
const resolvers = createResolversStub<GQLResolver>({
|
||||
Mutation: {
|
||||
setPassword: () => {
|
||||
throw new Error("server error");
|
||||
const resolvers = await act(async () => {
|
||||
return createResolversStub<GQLResolver>({
|
||||
Mutation: {
|
||||
setPassword: () => {
|
||||
throw new Error("server error");
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
const { form, passwordField } = await createTestRenderer({
|
||||
resolvers,
|
||||
muteNetworkErrors: true,
|
||||
@@ -94,33 +116,38 @@ it("shows server error", async () => {
|
||||
i => i.type === "button" && i.props.type === "submit"
|
||||
);
|
||||
|
||||
passwordField.props.onChange({ target: { value: password } });
|
||||
act(() => passwordField.props.onChange({ target: { value: password } }));
|
||||
|
||||
form.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
expect(passwordField.props.disabled).toBe(true);
|
||||
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(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("successfully sets password", async () => {
|
||||
const password = "secretpassword";
|
||||
const resolvers = createResolversStub<GQLResolver>({
|
||||
Mutation: {
|
||||
setPassword: ({ variables }) => {
|
||||
expectAndFail(variables).toEqual({
|
||||
password,
|
||||
});
|
||||
return {
|
||||
user: {
|
||||
id: "me",
|
||||
profiles: [],
|
||||
},
|
||||
};
|
||||
const resolvers = await act(async () => {
|
||||
return createResolversStub<GQLResolver>({
|
||||
Mutation: {
|
||||
setPassword: ({ variables }) => {
|
||||
expectAndFail(variables).toEqual({
|
||||
password,
|
||||
});
|
||||
return {
|
||||
user: {
|
||||
id: "me",
|
||||
profiles: [],
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
const { form, passwordField } = await createTestRenderer({
|
||||
resolvers,
|
||||
@@ -129,14 +156,17 @@ it("successfully sets password", async () => {
|
||||
i => i.type === "button" && i.props.type === "submit"
|
||||
);
|
||||
|
||||
passwordField.props.onChange({ target: { value: password } });
|
||||
act(() => passwordField.props.onChange({ target: { value: password } }));
|
||||
|
||||
form.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
expect(passwordField.props.disabled).toBe(true);
|
||||
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(toJSON(form)).toMatchSnapshot();
|
||||
expect(resolvers.Mutation!.setPassword!.called).toBe(true);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
act,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
replaceHistoryLocation,
|
||||
@@ -35,38 +36,61 @@ async function createTestRenderer(
|
||||
}
|
||||
},
|
||||
});
|
||||
const container = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("completeAccountBox")
|
||||
);
|
||||
const form = within(container).getByType("form");
|
||||
const usernameField = within(form).getByLabelText("Username");
|
||||
|
||||
return {
|
||||
context,
|
||||
testRenderer,
|
||||
form,
|
||||
root: testRenderer.root,
|
||||
usernameField,
|
||||
container,
|
||||
};
|
||||
return await act(async () => {
|
||||
const container = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("completeAccountBox")
|
||||
);
|
||||
const form = within(container).getByType("form");
|
||||
const usernameField = within(form).getByLabelText("Username");
|
||||
|
||||
return {
|
||||
context,
|
||||
testRenderer,
|
||||
form,
|
||||
root: testRenderer.root,
|
||||
usernameField,
|
||||
container,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
it("renders createUsername view", async () => {
|
||||
const { root } = await createTestRenderer();
|
||||
expect(toJSON(root)).toMatchSnapshot();
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(toJSON(root)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("shows error when submitting empty form", async () => {
|
||||
const { form } = await createTestRenderer();
|
||||
form.props.onSubmit();
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("checks for invalid username", async () => {
|
||||
const { form, usernameField } = await createTestRenderer();
|
||||
usernameField.props.onChange({ target: { value: "x" } });
|
||||
form.props.onSubmit();
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
|
||||
act(() => usernameField.props.onChange({ target: { value: "x" } }));
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("shows server error", async () => {
|
||||
@@ -86,14 +110,19 @@ it("shows server error", async () => {
|
||||
i => i.type === "button" && i.props.type === "submit"
|
||||
);
|
||||
|
||||
usernameField.props.onChange({ target: { value: username } });
|
||||
act(() => usernameField.props.onChange({ target: { value: username } }));
|
||||
|
||||
form.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
expect(usernameField.props.disabled).toBe(true);
|
||||
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(toJSON(form)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -122,14 +151,19 @@ it("successfully sets username", async () => {
|
||||
i => i.type === "button" && i.props.type === "submit"
|
||||
);
|
||||
|
||||
usernameField.props.onChange({ target: { value: username } });
|
||||
act(() => usernameField.props.onChange({ target: { value: username } }));
|
||||
|
||||
form.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
expect(usernameField.props.disabled).toBe(true);
|
||||
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(toJSON(form)).toMatchSnapshot();
|
||||
expect(resolvers.Mutation!.setUsername!.called).toBe(true);
|
||||
});
|
||||
|
||||
@@ -49,7 +49,6 @@ async function createTestRenderer(
|
||||
});
|
||||
|
||||
let form: ReactTestInstance;
|
||||
|
||||
await act(async () => {
|
||||
form = await waitForElement(() =>
|
||||
within(testRenderer.root).getByType("form")
|
||||
@@ -60,50 +59,96 @@ async function createTestRenderer(
|
||||
|
||||
it("renders sign in form", async () => {
|
||||
const { testRenderer } = await createTestRenderer();
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("shows error when submitting empty form", async () => {
|
||||
const { form } = await createTestRenderer();
|
||||
form.props.onSubmit();
|
||||
expect(within(form).toJSON()).toMatchSnapshot();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(within(form).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("checks for invalid email", async () => {
|
||||
const { form } = await createTestRenderer();
|
||||
within(form)
|
||||
.getByLabelText("Email Address")
|
||||
.props.onChange({ target: { value: "invalid-email" } });
|
||||
form.props.onSubmit();
|
||||
expect(within(form).toJSON()).toMatchSnapshot();
|
||||
|
||||
act(() => {
|
||||
within(form)
|
||||
.getByLabelText("Email Address")
|
||||
.props.onChange({ target: { value: "invalid-email" } });
|
||||
});
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(within(form).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("accepts valid email", async () => {
|
||||
const { form } = await createTestRenderer();
|
||||
within(form)
|
||||
.getByLabelText("Email Address")
|
||||
.props.onChange({ target: { value: "hans@test.com" } });
|
||||
form.props.onSubmit();
|
||||
expect(within(form).toJSON()).toMatchSnapshot();
|
||||
|
||||
act(() => {
|
||||
within(form)
|
||||
.getByLabelText("Email Address")
|
||||
.props.onChange({ target: { value: "hans@test.com" } });
|
||||
});
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(within(form).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("accepts correct password", async () => {
|
||||
const { form } = await createTestRenderer();
|
||||
within(form)
|
||||
.getByLabelText("Password")
|
||||
.props.onChange({ target: { value: "testtest" } });
|
||||
form.props.onSubmit();
|
||||
expect(within(form).toJSON()).toMatchSnapshot();
|
||||
|
||||
act(() => {
|
||||
within(form)
|
||||
.getByLabelText("Password")
|
||||
.props.onChange({ target: { value: "testtest" } });
|
||||
});
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(within(form).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("shows server error", async () => {
|
||||
const { form, context } = await createTestRenderer();
|
||||
within(form)
|
||||
.getByLabelText("Email Address")
|
||||
.props.onChange({ target: { value: "hans@test.com" } });
|
||||
within(form)
|
||||
.getByLabelText("Password")
|
||||
.props.onChange({ target: { value: "testtest" } });
|
||||
act(() => {
|
||||
within(form)
|
||||
.getByLabelText("Email Address")
|
||||
.props.onChange({ target: { value: "hans@test.com" } });
|
||||
});
|
||||
act(() => {
|
||||
within(form)
|
||||
.getByLabelText("Password")
|
||||
.props.onChange({ target: { value: "testtest" } });
|
||||
});
|
||||
|
||||
const error = new Error("Server Error");
|
||||
const restMock = sinon.mock(context.rest);
|
||||
@@ -119,24 +164,34 @@ it("shows server error", async () => {
|
||||
.once()
|
||||
.throws(error);
|
||||
|
||||
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(within(form).toJSON()).toMatchSnapshot();
|
||||
restMock.verify();
|
||||
});
|
||||
|
||||
it("submits form successfully", async () => {
|
||||
const { form, context } = await createTestRenderer();
|
||||
within(form)
|
||||
.getByLabelText("Email Address")
|
||||
.props.onChange({ target: { value: "hans@test.com" } });
|
||||
within(form)
|
||||
.getByLabelText("Password")
|
||||
.props.onChange({ target: { value: "testtest" } });
|
||||
act(() => {
|
||||
within(form)
|
||||
.getByLabelText("Email Address")
|
||||
.props.onChange({ target: { value: "hans@test.com" } });
|
||||
});
|
||||
act(() => {
|
||||
within(form)
|
||||
.getByLabelText("Password")
|
||||
.props.onChange({ target: { value: "testtest" } });
|
||||
});
|
||||
|
||||
const accessToken = createAccessToken();
|
||||
|
||||
@@ -162,6 +217,7 @@ it("submits form successfully", async () => {
|
||||
selector: "button",
|
||||
});
|
||||
expect(submitButton.props.disabled).toBe(true);
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => expect(submitButton.props.disabled).toBe(false));
|
||||
});
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
createQueryResolverStub,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
findParentWithType,
|
||||
replaceHistoryLocation,
|
||||
wait,
|
||||
waitForElement,
|
||||
@@ -344,7 +343,7 @@ it("filter by search", async () => {
|
||||
const searchField = within(container).getByLabelText("Search by username", {
|
||||
exact: false,
|
||||
});
|
||||
const form = findParentWithType(searchField, "form")!;
|
||||
const form = within(searchField).getParentByType("form");
|
||||
|
||||
await act(async () => {
|
||||
searchField.props.onChange({
|
||||
|
||||
@@ -300,7 +300,7 @@ When disabled, users will have to refresh the page to see new comments.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -324,7 +324,7 @@ When disabled, users will have to refresh the page to see new comments.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -457,7 +457,7 @@ https://domain.com).
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -481,7 +481,7 @@ https://domain.com).
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -525,7 +525,7 @@ https://domain.com).
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -549,7 +549,7 @@ https://domain.com).
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -259,7 +259,7 @@ reactions, be reported, and be shared.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -283,7 +283,7 @@ reactions, be reported, and be shared.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -373,7 +373,7 @@ reactions, be reported, and be shared.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -397,7 +397,7 @@ reactions, be reported, and be shared.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -505,7 +505,7 @@ Blank spaces at the beginning and the end of a comment will be trimmed.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -529,7 +529,7 @@ Blank spaces at the beginning and the end of a comment will be trimmed.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -782,7 +782,7 @@ moderation panel.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -806,7 +806,7 @@ moderation panel.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
|
||||
@@ -167,7 +167,7 @@ approved by a moderator.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -191,7 +191,7 @@ approved by a moderator.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -226,7 +226,7 @@ approved by a moderator.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -250,7 +250,7 @@ approved by a moderator.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -366,7 +366,7 @@ apply to Staff comments.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -390,7 +390,7 @@ apply to Staff comments.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -520,7 +520,7 @@ If approved by a moderator, the comment will be published.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -544,7 +544,7 @@ If approved by a moderator, the comment will be published.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -686,22 +686,24 @@ improve the API over time.
|
||||
className="Box-root Flex-root RadioButton-root Flex-flex Flex-alignCenter"
|
||||
>
|
||||
<input
|
||||
checked={false}
|
||||
checked={true}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="integrations.perspective.doNotStore-allow"
|
||||
id="integrations.perspective.doNotStore-true"
|
||||
name="integrations.perspective.doNotStore"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="integrations.perspective.doNotStore-allow"
|
||||
htmlFor="integrations.perspective.doNotStore-true"
|
||||
>
|
||||
Allow
|
||||
<span>
|
||||
Allow
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
@@ -711,19 +713,21 @@ improve the API over time.
|
||||
checked={false}
|
||||
className="RadioButton-input"
|
||||
disabled={false}
|
||||
id="integrations.perspective.doNotStore-dontAllow"
|
||||
id="integrations.perspective.doNotStore-false"
|
||||
name="integrations.perspective.doNotStore"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
htmlFor="integrations.perspective.doNotStore-dontAllow"
|
||||
htmlFor="integrations.perspective.doNotStore-false"
|
||||
>
|
||||
Don't allow
|
||||
<span>
|
||||
Don't allow
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -894,7 +898,7 @@ If approved by a moderator, the comment will be published.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={true}
|
||||
value="true"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
@@ -918,7 +922,7 @@ If approved by a moderator, the comment will be published.
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
type="radio"
|
||||
value={false}
|
||||
value="false"
|
||||
/>
|
||||
<label
|
||||
className="RadioButton-label"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
act,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
replaceHistoryLocation,
|
||||
@@ -84,20 +85,24 @@ it("change custom css", async () => {
|
||||
const customCSSField = within(advancedContainer).getByLabelText("Custom CSS");
|
||||
|
||||
// Let's change the customCSS field.
|
||||
customCSSField.props.onChange("./custom.css");
|
||||
act(() => customCSSField.props.onChange("./custom.css"));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(customCSSField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(customCSSField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(customCSSField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
@@ -128,16 +133,20 @@ it("remove custom css", async () => {
|
||||
const customCSSField = within(advancedContainer).getByLabelText("Custom CSS");
|
||||
|
||||
// Let's change the customCSS field.
|
||||
customCSSField.props.onChange("");
|
||||
act(() => customCSSField.props.onChange(""));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -191,20 +200,24 @@ it("change permitted domains to be empty", async () => {
|
||||
);
|
||||
|
||||
// Let's change the permitted domains.
|
||||
permittedDomainsField.props.onChange("");
|
||||
act(() => permittedDomainsField.props.onChange(""));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(permittedDomainsField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(permittedDomainsField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(permittedDomainsField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
@@ -238,22 +251,28 @@ it("change permitted domains to include more domains", async () => {
|
||||
);
|
||||
|
||||
// Let's change the permitted domains.
|
||||
permittedDomainsField.props.onChange(
|
||||
"http://localhost:8080, http://localhost:3000"
|
||||
act(() =>
|
||||
permittedDomainsField.props.onChange(
|
||||
"http://localhost:8080, http://localhost:3000"
|
||||
)
|
||||
);
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(permittedDomainsField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(permittedDomainsField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(permittedDomainsField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { cloneDeep } from "lodash";
|
||||
import { ReactTestInstance } from "react-test-renderer";
|
||||
import sinon from "sinon";
|
||||
|
||||
import { pureMerge, timeout } from "coral-common/utils";
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
act,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
limitSnapshotTo,
|
||||
findParentWithType,
|
||||
replaceHistoryLocation,
|
||||
wait,
|
||||
waitForElement,
|
||||
within,
|
||||
} from "coral-framework/testHelpers";
|
||||
@@ -16,20 +17,6 @@ import {
|
||||
import create from "../create";
|
||||
import { settingsWithEmptyAuth, users } from "../fixtures";
|
||||
|
||||
/**
|
||||
* This is depreacted, do not use it anymore.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
const deprecatedInputPredicate = (nameOrID: string) => (
|
||||
n: ReactTestInstance
|
||||
) => {
|
||||
return (
|
||||
[n.props.name, n.props.id].includes(nameOrID) &&
|
||||
["input", "button"].includes(n.type as string)
|
||||
);
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
replaceHistoryLocation("http://localhost/admin/configure/auth");
|
||||
});
|
||||
@@ -94,35 +81,50 @@ it("regenerate sso key", async () => {
|
||||
},
|
||||
}),
|
||||
});
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.sso.enabled"))
|
||||
.props.onChange({});
|
||||
const container = within(testRenderer.root).getByTestID("configure-auth-sso");
|
||||
act(() => {
|
||||
within(container)
|
||||
.getByLabelText("Enabled")
|
||||
.props.onChange({});
|
||||
});
|
||||
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("configure-auth-sso-regenerate"))
|
||||
.props.onClick();
|
||||
act(() => {
|
||||
within(container)
|
||||
.getByText("Regenerate", { selector: "button" })
|
||||
.props.onClick();
|
||||
});
|
||||
|
||||
await timeout();
|
||||
|
||||
expect(
|
||||
limitSnapshotTo("configure-auth-sso-key", testRenderer.toJSON())
|
||||
).toMatchSnapshot();
|
||||
await wait(() =>
|
||||
expect(within(container).getByLabelText("Key").props.value).toBe(
|
||||
"==GENERATED_KEY=="
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it("prevents admin lock out", async () => {
|
||||
const { testRenderer } = await createTestRenderer();
|
||||
|
||||
const container = within(testRenderer.root).getByTestID(
|
||||
"configure-auth-local"
|
||||
);
|
||||
|
||||
// Let's disable local auth.
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.local.enabled"))
|
||||
.props.onChange();
|
||||
act(() => {
|
||||
within(container)
|
||||
.getByLabelText("Enabled")
|
||||
.props.onChange();
|
||||
});
|
||||
|
||||
// Send form
|
||||
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
|
||||
await timeout();
|
||||
expect(
|
||||
limitSnapshotTo("configure-auth-submitError", testRenderer.toJSON())
|
||||
).toMatchSnapshot();
|
||||
await act(async () =>
|
||||
findParentWithType(container, "form")!.props.onSubmit()
|
||||
);
|
||||
await waitForElement(() =>
|
||||
within(testRenderer.root).getByText(
|
||||
"Please enable at least one authentication integration",
|
||||
{ exact: false }
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it("prevents stream lock out", async () => {
|
||||
@@ -151,36 +153,35 @@ it("prevents stream lock out", async () => {
|
||||
const stubContinue = sinon.stub().returns(true);
|
||||
const stubCancel = sinon.stub().returns(false);
|
||||
|
||||
const container = within(testRenderer.root).getByTestID(
|
||||
"configure-auth-local"
|
||||
);
|
||||
const streamTarget = within(container).getByLabelText("Comment Stream");
|
||||
const form = findParentWithType(container, "form")!;
|
||||
const saveChanges = within(testRenderer.root).getByText("Save Changes", {
|
||||
selector: "button",
|
||||
});
|
||||
|
||||
try {
|
||||
window.confirm = stubCancel;
|
||||
// Let's disable stream target in local auth.
|
||||
testRenderer.root
|
||||
.find(
|
||||
deprecatedInputPredicate("auth.integrations.local.targetFilter.stream")
|
||||
)
|
||||
.props.onChange();
|
||||
act(() => streamTarget.props.onChange());
|
||||
|
||||
// Send form
|
||||
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
|
||||
await act(async () => await form.props.onSubmit());
|
||||
|
||||
// Submit button should not be disabled because we canceled the submit.
|
||||
expect(
|
||||
testRenderer.root.findByProps({
|
||||
"data-testid": "configure-sideBar-saveChanges",
|
||||
}).props.disabled
|
||||
).toBe(true);
|
||||
expect(stubCancel.calledOnce).toBe(true);
|
||||
wait(() => expect(saveChanges.props.disabled).toBe(true));
|
||||
wait(() => {
|
||||
expect(stubCancel.calledOnce).toBe(true);
|
||||
});
|
||||
|
||||
window.confirm = stubContinue;
|
||||
// Let's enable stream target in local auth.
|
||||
testRenderer.root
|
||||
.find(
|
||||
deprecatedInputPredicate("auth.integrations.local.targetFilter.stream")
|
||||
)
|
||||
.props.onChange();
|
||||
act(() => streamTarget.props.onChange());
|
||||
|
||||
// Send form
|
||||
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
|
||||
await act(async () => await form.props.onSubmit());
|
||||
|
||||
expect(stubContinue.calledOnce).toBe(true);
|
||||
} finally {
|
||||
@@ -248,96 +249,108 @@ it("change settings", async () => {
|
||||
}),
|
||||
});
|
||||
|
||||
const facebookContainer = within(testRenderer.root).getByTestID(
|
||||
"configure-auth-facebook-container"
|
||||
);
|
||||
const facebookEnabled = within(facebookContainer).getByLabelText("Enabled");
|
||||
|
||||
const oidcContainer = within(testRenderer.root).getByTestID(
|
||||
"configure-auth-oidc-container"
|
||||
);
|
||||
const oidcEnabled = within(oidcContainer).getByLabelText("Enabled");
|
||||
|
||||
const form = findParentWithType(facebookContainer, "form")!;
|
||||
const saveChanges = within(testRenderer.root).getByText("Save Changes", {
|
||||
selector: "button",
|
||||
});
|
||||
|
||||
// Let's change some facebook settings.
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.facebook.enabled"))
|
||||
.props.onChange({});
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.facebook.clientID"))
|
||||
.props.onChange("myClientID");
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.facebook.clientSecret"))
|
||||
.props.onChange("myClientSecret");
|
||||
expect(
|
||||
limitSnapshotTo("configure-auth-facebook-container", testRenderer.toJSON())
|
||||
).toMatchSnapshot("enable facebook configure box");
|
||||
act(() => facebookEnabled.props.onChange({}));
|
||||
act(() =>
|
||||
within(facebookContainer)
|
||||
.getByLabelText("Client ID", { exact: false })
|
||||
.props.onChange("myClientID")
|
||||
);
|
||||
act(() =>
|
||||
within(facebookContainer)
|
||||
.getByLabelText("Client secret", { exact: false })
|
||||
.props.onChange("myClientSecret")
|
||||
);
|
||||
|
||||
// Send form
|
||||
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
|
||||
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
// Submit button should be disabled.
|
||||
expect(
|
||||
testRenderer.root.findByProps({
|
||||
"data-testid": "configure-sideBar-saveChanges",
|
||||
}).props.disabled
|
||||
).toBe(true);
|
||||
|
||||
expect(saveChanges.props.disabled).toBe(true);
|
||||
// Disable other fields while submitting
|
||||
// We are only testing for one here right now..
|
||||
expect(
|
||||
testRenderer.root.find(
|
||||
deprecatedInputPredicate("auth.integrations.facebook.enabled")
|
||||
).props.disabled
|
||||
).toBe(true);
|
||||
await timeout();
|
||||
expect(
|
||||
testRenderer.root.find(
|
||||
deprecatedInputPredicate("auth.integrations.facebook.enabled")
|
||||
).props.disabled
|
||||
).toBe(false);
|
||||
expect(facebookEnabled.props.disabled).toBe(true);
|
||||
|
||||
await act(async () => {
|
||||
// When submitting finished, the fields become enabled again.
|
||||
await wait(() => expect(facebookEnabled.props.disabled).toBe(false));
|
||||
});
|
||||
|
||||
// Now let's enable oidc
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.oidc.enabled"))
|
||||
.props.onChange({});
|
||||
|
||||
expect(
|
||||
limitSnapshotTo("configure-auth-oidc-container", testRenderer.toJSON())
|
||||
).toMatchSnapshot("enable oidc configure box");
|
||||
act(() => oidcEnabled.props.onChange({}));
|
||||
expect(() =>
|
||||
within(oidcContainer).getAllByText("This field is required", {
|
||||
exact: false,
|
||||
})
|
||||
).toThrow();
|
||||
|
||||
// Try to submit form, this will give validation error messages.
|
||||
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
|
||||
expect(
|
||||
limitSnapshotTo("configure-auth-oidc-container", testRenderer.toJSON())
|
||||
).toMatchSnapshot("oidc validation errors");
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
within(oidcContainer).getAllByText("This field is required", {
|
||||
exact: false,
|
||||
});
|
||||
|
||||
// Fill form
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.oidc.name"))
|
||||
.props.onChange("name");
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.oidc.clientID"))
|
||||
.props.onChange("clientID");
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.oidc.clientSecret"))
|
||||
.props.onChange("clientSecret");
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("auth.integrations.oidc.issuer"))
|
||||
.props.onChange("http://issuer.com");
|
||||
act(() =>
|
||||
within(oidcContainer)
|
||||
.getByLabelText("Provider name", { exact: false })
|
||||
.props.onChange("name")
|
||||
);
|
||||
act(() =>
|
||||
within(oidcContainer)
|
||||
.getByLabelText("Client ID", { exact: false })
|
||||
.props.onChange("clientID")
|
||||
);
|
||||
act(() =>
|
||||
within(oidcContainer)
|
||||
.getByLabelText("Client secret", { exact: false })
|
||||
.props.onChange("clientSecret")
|
||||
);
|
||||
act(() =>
|
||||
within(oidcContainer)
|
||||
.getByLabelText("Issuer", { exact: false })
|
||||
.props.onChange("http://issuer.com")
|
||||
);
|
||||
|
||||
// Discover the rest.
|
||||
testRenderer.root
|
||||
.find(deprecatedInputPredicate("configure-auth-oidc-discover"))
|
||||
.props.onClick();
|
||||
await timeout();
|
||||
await act(
|
||||
async () =>
|
||||
await within(oidcContainer)
|
||||
.getByText("Discover", { selector: "button" })
|
||||
.props.onClick()
|
||||
);
|
||||
|
||||
// Try to submit again, this should work now.
|
||||
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
|
||||
expect(
|
||||
limitSnapshotTo("configure-auth-oidc-container", testRenderer.toJSON())
|
||||
).toMatchSnapshot("during submit: oidc without errors");
|
||||
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
// Submit button should be disabled.
|
||||
expect(saveChanges.props.disabled).toBe(true);
|
||||
// Disable other fields while submitting
|
||||
// We are only testing for one here right now..
|
||||
expect(
|
||||
testRenderer.root.find(
|
||||
deprecatedInputPredicate("auth.integrations.oidc.enabled")
|
||||
).props.disabled
|
||||
).toBe(true);
|
||||
await timeout();
|
||||
expect(
|
||||
testRenderer.root.find(
|
||||
deprecatedInputPredicate("auth.integrations.oidc.enabled")
|
||||
).props.disabled
|
||||
).toBe(false);
|
||||
expect(oidcEnabled.props.disabled).toBe(true);
|
||||
|
||||
await act(async () => {
|
||||
// When submitting finished, the fields become enabled again.
|
||||
await wait(() => expect(oidcEnabled.props.disabled).toBe(false));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import { pureMerge } from "coral-common/utils";
|
||||
import { InvalidRequestError } from "coral-framework/lib/errors";
|
||||
import { GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
act,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
replaceHistoryLocation,
|
||||
@@ -86,19 +87,23 @@ it("change language", async () => {
|
||||
const languageField = within(generalContainer).getByLabelText("Language");
|
||||
|
||||
// Let's change the language.
|
||||
languageField.props.onChange("es");
|
||||
act(() => languageField.props.onChange("es"));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
// Wait for client to change language.
|
||||
@@ -142,23 +147,27 @@ it("change site wide commenting", async () => {
|
||||
);
|
||||
|
||||
// Let's enable it.
|
||||
offField.props.onChange(offField.props.value.toString());
|
||||
act(() => offField.props.onChange(offField.props.value.toString()));
|
||||
|
||||
// Let's change the content.
|
||||
contentField.props.onChange("Closing message");
|
||||
act(() => contentField.props.onChange("Closing message"));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(offField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(offField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(offField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
@@ -201,23 +210,29 @@ it("change community guidlines", async () => {
|
||||
);
|
||||
|
||||
// Let's enable it.
|
||||
onField.props.onChange(onField.props.value.toString());
|
||||
act(() => onField.props.onChange(onField.props.value.toString()));
|
||||
|
||||
// Let's change the content.
|
||||
contentField.props.onChange("This is the community guidlines summary");
|
||||
act(() =>
|
||||
contentField.props.onChange("This is the community guidlines summary")
|
||||
);
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(onField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
@@ -248,19 +263,23 @@ it("change closed stream message", async () => {
|
||||
);
|
||||
|
||||
// Let's change the content.
|
||||
contentField.props.onChange("The stream has been closed");
|
||||
act(() => contentField.props.onChange("The stream has been closed"));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -292,22 +311,26 @@ it("change comment editing time", async () => {
|
||||
const hoursOption = within(unitField).getByText(/Hours?/);
|
||||
|
||||
// Let's turn on and set some invalid values.
|
||||
valueField.props.onChange({ target: { value: "" } });
|
||||
act(() => valueField.props.onChange({ target: { value: "" } }));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
expect(
|
||||
within(generalContainer).queryAllByText("This field is required.").length
|
||||
).toBe(1);
|
||||
|
||||
// Let's change to sth valid.
|
||||
valueField.props.onChange({ target: { value: "30" } });
|
||||
unitField.props.onChange({
|
||||
target: { value: hoursOption.props.value.toString() },
|
||||
});
|
||||
act(() => valueField.props.onChange({ target: { value: "30" } }));
|
||||
act(() =>
|
||||
unitField.props.onChange({
|
||||
target: { value: hoursOption.props.value.toString() },
|
||||
})
|
||||
);
|
||||
|
||||
expect(
|
||||
within(generalContainer).queryAllByText(
|
||||
@@ -316,16 +339,20 @@ it("change comment editing time", async () => {
|
||||
).toBe(0);
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -365,14 +392,16 @@ it("change comment length limitations", async () => {
|
||||
);
|
||||
|
||||
// Let's turn on and set some invalid values.
|
||||
onField.props.onChange(onField.props.value.toString());
|
||||
minField.props.onChange("invalid");
|
||||
maxField.props.onChange("-1");
|
||||
act(() => onField.props.onChange(onField.props.value.toString()));
|
||||
act(() => minField.props.onChange("invalid"));
|
||||
act(() => maxField.props.onChange("-1"));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
expect(
|
||||
within(generalContainer).queryAllByText(
|
||||
@@ -381,8 +410,8 @@ it("change comment length limitations", async () => {
|
||||
).toBe(2);
|
||||
|
||||
// Make max smaller than min.
|
||||
minField.props.onChange("1000");
|
||||
maxField.props.onChange("500");
|
||||
act(() => minField.props.onChange("1000"));
|
||||
act(() => maxField.props.onChange("500"));
|
||||
|
||||
expect(
|
||||
within(generalContainer).queryAllByText(
|
||||
@@ -391,8 +420,8 @@ it("change comment length limitations", async () => {
|
||||
).toBe(1);
|
||||
|
||||
// Let's change to sth valid.
|
||||
minField.props.onChange("");
|
||||
maxField.props.onChange("3000");
|
||||
act(() => minField.props.onChange(""));
|
||||
act(() => maxField.props.onChange("3000"));
|
||||
|
||||
expect(
|
||||
within(generalContainer).queryAllByText(
|
||||
@@ -401,9 +430,11 @@ it("change comment length limitations", async () => {
|
||||
).toBe(0);
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
@@ -411,9 +442,11 @@ it("change comment length limitations", async () => {
|
||||
expect(maxField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(minField.props.disabled).toBe(false);
|
||||
expect(maxField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(minField.props.disabled).toBe(false);
|
||||
expect(maxField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
});
|
||||
@@ -452,28 +485,34 @@ it("change closing comment streams", async () => {
|
||||
const daysOption = within(unitField).getByText(/Days?/);
|
||||
|
||||
// Let's turn on and set some invalid values.
|
||||
onField.props.onChange(onField.props.value.toString());
|
||||
valueField.props.onChange({ target: { value: "" } });
|
||||
act(() => onField.props.onChange(onField.props.value.toString()));
|
||||
act(() => valueField.props.onChange({ target: { value: "" } }));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
expect(
|
||||
within(generalContainer).queryAllByText("This field is required.").length
|
||||
).toBe(1);
|
||||
|
||||
// Let's change to sth valid.
|
||||
valueField.props.onChange({ target: { value: "30" } });
|
||||
unitField.props.onChange({
|
||||
target: { value: daysOption.props.value.toString() },
|
||||
});
|
||||
act(() => valueField.props.onChange({ target: { value: "30" } }));
|
||||
act(() =>
|
||||
unitField.props.onChange({
|
||||
target: { value: daysOption.props.value.toString() },
|
||||
})
|
||||
);
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
@@ -481,9 +520,11 @@ it("change closing comment streams", async () => {
|
||||
expect(unitField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(valueField.props.disabled).toBe(false);
|
||||
expect(unitField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(valueField.props.disabled).toBe(false);
|
||||
expect(unitField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
expect(resolvers.Mutation!.updateSettings!.called).toBe(true);
|
||||
});
|
||||
@@ -507,15 +548,19 @@ it("handle server error", async () => {
|
||||
);
|
||||
|
||||
// Let's change the content.
|
||||
contentField.props.onChange("The stream has been closed");
|
||||
act(() => contentField.props.onChange("The stream has been closed"));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Look for internal error being displayed.
|
||||
await waitForElement(() =>
|
||||
within(configureContainer).getByText("INTERNAL_ERROR")
|
||||
);
|
||||
await act(async () => {
|
||||
await waitForElement(() =>
|
||||
within(configureContainer).getByText("INTERNAL_ERROR")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { GQLMODERATION_MODE, GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
act,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
findParentWithType,
|
||||
replaceHistoryLocation,
|
||||
wait,
|
||||
waitForElement,
|
||||
@@ -73,11 +75,7 @@ it("change site wide pre-moderation", async () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
const {
|
||||
configureContainer,
|
||||
moderationContainer,
|
||||
saveChangesButton,
|
||||
} = await createTestRenderer({
|
||||
const { moderationContainer, saveChangesButton } = await createTestRenderer({
|
||||
resolvers,
|
||||
});
|
||||
|
||||
@@ -87,22 +85,24 @@ it("change site wide pre-moderation", async () => {
|
||||
)[0];
|
||||
|
||||
const onField = within(preModerationContainer).getByLabelText("On");
|
||||
const form = findParentWithType(preModerationContainer, "form")!;
|
||||
|
||||
// Let's enable it.
|
||||
onField.props.onChange(onField.props.value.toString());
|
||||
|
||||
act(() => onField.props.onChange(onField.props.value.toString()));
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(onField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
@@ -120,11 +120,7 @@ it("change site wide link pre-moderation", async () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
const {
|
||||
configureContainer,
|
||||
moderationContainer,
|
||||
saveChangesButton,
|
||||
} = await createTestRenderer({
|
||||
const { moderationContainer, saveChangesButton } = await createTestRenderer({
|
||||
resolvers,
|
||||
});
|
||||
|
||||
@@ -134,22 +130,25 @@ it("change site wide link pre-moderation", async () => {
|
||||
)[0];
|
||||
|
||||
const onField = within(preModerationContainer).getByLabelText("On");
|
||||
const form = findParentWithType(preModerationContainer, "form")!;
|
||||
|
||||
// Let's enable it.
|
||||
onField.props.onChange(onField.props.value.toString());
|
||||
act(() => onField.props.onChange(onField.props.value.toString()));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(onField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
@@ -171,11 +170,9 @@ it("change akismet settings", async () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
const {
|
||||
configureContainer,
|
||||
moderationContainer,
|
||||
saveChangesButton,
|
||||
} = await createTestRenderer({ resolvers });
|
||||
const { moderationContainer, saveChangesButton } = await createTestRenderer({
|
||||
resolvers,
|
||||
});
|
||||
|
||||
const akismetContainer = within(moderationContainer).getByTestID(
|
||||
"akismet-config"
|
||||
@@ -184,41 +181,44 @@ it("change akismet settings", async () => {
|
||||
const onField = within(akismetContainer).getByLabelText("On");
|
||||
const keyField = within(akismetContainer).getByLabelText("API key");
|
||||
const siteField = within(akismetContainer).getByLabelText("Site URL");
|
||||
const form = findParentWithType(akismetContainer, "form")!;
|
||||
|
||||
// Let's turn it on.
|
||||
onField.props.onChange(onField.props.value.toString());
|
||||
act(() => onField.props.onChange(onField.props.value.toString()));
|
||||
|
||||
expect(saveChangesButton.props.disabled).toBe(false);
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
expect(
|
||||
within(akismetContainer).queryAllByText("This field is required.").length
|
||||
).toBe(2);
|
||||
|
||||
// Input valid api key
|
||||
keyField.props.onChange("my api key");
|
||||
act(() => keyField.props.onChange("my api key"));
|
||||
|
||||
// Input correct site.
|
||||
siteField.props.onChange("https://coralproject.net");
|
||||
act(() => siteField.props.onChange("https://coralproject.net"));
|
||||
|
||||
expect(within(akismetContainer).queryAllByText("Invalid URL").length).toBe(0);
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(onField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
@@ -253,11 +253,9 @@ it("change perspective settings", async () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
const {
|
||||
configureContainer,
|
||||
moderationContainer,
|
||||
saveChangesButton,
|
||||
} = await createTestRenderer({ resolvers });
|
||||
const { moderationContainer, saveChangesButton } = await createTestRenderer({
|
||||
resolvers,
|
||||
});
|
||||
|
||||
const perspectiveContainer = within(moderationContainer).getByTestID(
|
||||
"perspective-container"
|
||||
@@ -272,17 +270,18 @@ it("change perspective settings", async () => {
|
||||
const endpointField = within(perspectiveContainer).getByLabelText(
|
||||
"Custom endpoint"
|
||||
);
|
||||
const form = findParentWithType(perspectiveContainer, "form")!;
|
||||
|
||||
// Let's turn it on.
|
||||
onField.props.onChange(onField.props.value.toString());
|
||||
allowField.props.onChange(allowField.props.value.toString());
|
||||
act(() => onField.props.onChange(onField.props.value.toString()));
|
||||
act(() => allowField.props.onChange(allowField.props.value.toString()));
|
||||
|
||||
expect(saveChangesButton.props.disabled).toBe(false);
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
expect(
|
||||
within(perspectiveContainer).queryAllByText("This field is required.")
|
||||
@@ -290,13 +289,13 @@ it("change perspective settings", async () => {
|
||||
).toBe(1);
|
||||
|
||||
// Input valid api key
|
||||
keyField.props.onChange("my api key");
|
||||
act(() => keyField.props.onChange("my api key"));
|
||||
|
||||
// Input malformed endpoint.
|
||||
endpointField.props.onChange("malformed url");
|
||||
act(() => endpointField.props.onChange("malformed url"));
|
||||
|
||||
// Input malformed threshold.
|
||||
thresholdField.props.onChange("abc");
|
||||
act(() => thresholdField.props.onChange("abc"));
|
||||
|
||||
expect(
|
||||
within(perspectiveContainer).queryAllByText("This field is required.")
|
||||
@@ -312,47 +311,51 @@ it("change perspective settings", async () => {
|
||||
).toBe(1);
|
||||
|
||||
// Input correct site.
|
||||
endpointField.props.onChange("https://custom-endpoint.net");
|
||||
act(() => endpointField.props.onChange("https://custom-endpoint.net"));
|
||||
|
||||
// Input valid threshold.
|
||||
thresholdField.props.onChange(10);
|
||||
act(() => thresholdField.props.onChange(10));
|
||||
|
||||
expect(
|
||||
within(perspectiveContainer).queryAllByText("Invalid URL").length
|
||||
).toBe(0);
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(onField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
expect(resolvers.Mutation!.updateSettings!.calledOnce).toBe(true);
|
||||
|
||||
// Use default threshold.
|
||||
thresholdField.props.onChange("");
|
||||
act(() => thresholdField.props.onChange(""));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(onField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(onField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
act,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
replaceHistoryLocation,
|
||||
@@ -84,18 +85,20 @@ it("change organization name", async () => {
|
||||
);
|
||||
|
||||
// Let's change some organization name.
|
||||
organizationNameField.props.onChange("");
|
||||
act(() => organizationNameField.props.onChange(""));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Should show validation error.
|
||||
within(organizationContainer).getByText("This field is required.");
|
||||
|
||||
// Let's change to some valid organization name.
|
||||
organizationNameField.props.onChange("Coral Test");
|
||||
act(() => organizationNameField.props.onChange("Coral Test"));
|
||||
|
||||
// Should not show validation error.
|
||||
expect(
|
||||
@@ -103,17 +106,21 @@ it("change organization name", async () => {
|
||||
).toBeNull();
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(organizationNameField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(organizationNameField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(organizationNameField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
@@ -144,18 +151,20 @@ it("change organization contact email", async () => {
|
||||
);
|
||||
|
||||
// Let's change some organization name.
|
||||
organizationEmailField.props.onChange("");
|
||||
act(() => organizationEmailField.props.onChange(""));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Should show validation error.
|
||||
within(organizationContainer).getByText("This field is required.");
|
||||
|
||||
// Let's change to some valid organization name.
|
||||
organizationEmailField.props.onChange("test@coralproject.net");
|
||||
act(() => organizationEmailField.props.onChange("test@coralproject.net"));
|
||||
|
||||
// Should not show validation error.
|
||||
expect(
|
||||
@@ -163,17 +172,21 @@ it("change organization contact email", async () => {
|
||||
).toBeNull();
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
expect(organizationEmailField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(organizationEmailField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(organizationEmailField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { pureMerge } from "coral-common/utils";
|
||||
import { GQLResolver } from "coral-framework/schema";
|
||||
import {
|
||||
act,
|
||||
createResolversStub,
|
||||
CreateTestRendererParams,
|
||||
replaceHistoryLocation,
|
||||
@@ -90,13 +91,15 @@ it("change banned and suspect words", async () => {
|
||||
);
|
||||
|
||||
// Let's change the wordlist contents.
|
||||
bannedField.props.onChange("Fuck\nAsshole");
|
||||
suspectField.props.onChange("idiot\nshame");
|
||||
act(() => bannedField.props.onChange("Fuck\nAsshole"));
|
||||
act(() => suspectField.props.onChange("idiot\nshame"));
|
||||
|
||||
// Send form
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
act(() => {
|
||||
within(configureContainer)
|
||||
.getByType("form")
|
||||
.props.onSubmit();
|
||||
});
|
||||
|
||||
// Submit button and text field should be disabled.
|
||||
expect(saveChangesButton.props.disabled).toBe(true);
|
||||
@@ -104,9 +107,11 @@ it("change banned and suspect words", async () => {
|
||||
expect(suspectField.props.disabled).toBe(true);
|
||||
|
||||
// Wait for submission to be finished
|
||||
await wait(() => {
|
||||
expect(bannedField.props.disabled).toBe(false);
|
||||
expect(suspectField.props.disabled).toBe(false);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(bannedField.props.disabled).toBe(false);
|
||||
expect(suspectField.props.disabled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have successfully sent with server.
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
CreateTestRendererParams,
|
||||
findParentWithType,
|
||||
replaceHistoryLocation,
|
||||
wait,
|
||||
waitForElement,
|
||||
waitUntilThrow,
|
||||
within,
|
||||
@@ -59,15 +60,22 @@ async function createTestRenderer(
|
||||
},
|
||||
});
|
||||
|
||||
const container = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("stories-container")
|
||||
);
|
||||
return { testRenderer, container, context };
|
||||
return await act(async () => {
|
||||
const container = await waitForElement(() =>
|
||||
within(testRenderer.root).getByTestID("stories-container")
|
||||
);
|
||||
|
||||
return { testRenderer, container, context };
|
||||
});
|
||||
}
|
||||
|
||||
it("renders stories", async () => {
|
||||
const { container } = await createTestRenderer();
|
||||
expect(within(container).toJSON()).toMatchSnapshot();
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(within(container).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("renders empty stories", async () => {
|
||||
@@ -78,7 +86,12 @@ it("renders empty stories", async () => {
|
||||
},
|
||||
}),
|
||||
});
|
||||
expect(within(container).toJSON()).toMatchSnapshot();
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(within(container).toJSON()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("goes to moderation when clicking on title", async () => {
|
||||
@@ -96,10 +109,15 @@ it("goes to moderation when clicking on title", async () => {
|
||||
.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}`
|
||||
);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(transitionControl.history[0].pathname).toBe(
|
||||
`/admin/moderate/${story.id}`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("filter by status", async () => {
|
||||
@@ -122,10 +140,13 @@ it("filter by status", async () => {
|
||||
const selectField = within(container).getByLabelText("Search by status");
|
||||
const closedOption = within(selectField).getByText("Closed Stories");
|
||||
|
||||
await act(async () => {
|
||||
act(() => {
|
||||
selectField.props.onChange({
|
||||
target: { value: closedOption.props.value.toString() },
|
||||
});
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await waitForElement(() =>
|
||||
within(container).getByText("could not find any", { exact: false })
|
||||
);
|
||||
@@ -185,7 +206,6 @@ it("change story status", async () => {
|
||||
act(() => {
|
||||
changeStatusButton.props.onClick();
|
||||
});
|
||||
|
||||
act(() => {
|
||||
within(popup)
|
||||
.getByText("Closed", { selector: "button" })
|
||||
@@ -241,14 +261,21 @@ it("load more", async () => {
|
||||
}),
|
||||
});
|
||||
const loadMore = within(container).getByText("Load More");
|
||||
await act(async () => {
|
||||
act(() => {
|
||||
loadMore.props.onClick();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
// 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!);
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
// Make sure third user was added.
|
||||
within(container).getByText(stories[2].metadata!.title!);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("filter by search", async () => {
|
||||
@@ -274,11 +301,16 @@ it("filter by search", async () => {
|
||||
);
|
||||
const form = findParentWithType(searchField, "form")!;
|
||||
|
||||
await act(async () => {
|
||||
act(() =>
|
||||
searchField.props.onChange({
|
||||
target: { value: "search" },
|
||||
});
|
||||
})
|
||||
);
|
||||
act(() => {
|
||||
form.props.onSubmit();
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
await waitForElement(() =>
|
||||
within(container).getByText("could not find any", { exact: false })
|
||||
);
|
||||
@@ -303,5 +335,10 @@ it("use searchFilter from url", async () => {
|
||||
"Search by story title",
|
||||
{ exact: false }
|
||||
);
|
||||
expect(searchField.props.value).toBe(searchFilter);
|
||||
|
||||
await act(async () => {
|
||||
await wait(() => {
|
||||
expect(searchField.props.value).toBe(searchFilter);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user