+ return () => refresh.destroy();
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
- );
- }
-}
+
+
+
+
+ );
+};
export default FeedPage;
diff --git a/src/modules/feed/components/CreatePost/CreatePost.spec.tsx b/src/modules/feed/components/CreatePost/CreatePost.spec.tsx
index 76026c0c..eadb647d 100644
--- a/src/modules/feed/components/CreatePost/CreatePost.spec.tsx
+++ b/src/modules/feed/components/CreatePost/CreatePost.spec.tsx
@@ -1,14 +1,19 @@
import { GraphQLError } from "graphql";
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
import { CREATE_POST, CreatePost } from "./CreatePost";
import { GET_POSTS } from "../../queries";
-import { fireEvent, render, screen } from "@testing-library/react";
+import { fireEvent, screen } from "@testing-library/react";
import { mocks as guidelineMocks } from "../../../manage-team/sections/guideline/GuidelinesSection.spec";
import { mocksWithData as teamMemberMocks } from "../UserDropdown/UserDropdown.spec";
import {
getSelectOptions,
openSelect,
} from "../../../../support/testing/reactSelectHelpers";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
const mocks = () => [
{
@@ -121,18 +126,19 @@ const mocksWithError = [
];
describe("
", () => {
- const setup = (
- { withErrors = false }: { withErrors: boolean } = { withErrors: false },
- ) => {
- render(
- withMockedProviders(
, [
- ...(withErrors ? mocksWithError : []),
- ...mocks(),
- ...guidelineMocks("1"),
- ...teamMemberMocks("1"),
- ]),
- );
- };
+ const { renderComponent, updateDecorator } = setTestSubject(
+ makeFC(CreatePost),
+ {
+ decorators: [
+ dataDecorator([
+ ...mocks(),
+ ...guidelineMocks("1"),
+ ...teamMemberMocks("1"),
+ ]),
+ ],
+ props: { back: false },
+ },
+ );
beforeEach(() => {
mockLocalstorage("1");
@@ -171,7 +177,8 @@ describe("
", () => {
};
it("shows a message if the amount is null", async () => {
- setup();
+ renderComponent();
+
await pressSubmit();
const errorMessage = await screen.findByText("Amount can't be empty or 0.");
@@ -179,7 +186,8 @@ describe("
", () => {
});
it("shows a message if there are no receivers", async () => {
- setup();
+ renderComponent();
+
await setKudoAmount();
await pressSubmit();
@@ -190,7 +198,8 @@ describe("
", () => {
});
it("shows a warning if there is no message", async () => {
- setup();
+ renderComponent();
+
await setKudoAmount();
await setReceiver("Egon");
await pressSubmit();
@@ -200,7 +209,8 @@ describe("
", () => {
});
it("shows a warning if the message is too short", async () => {
- setup();
+ renderComponent();
+
await setKudoAmount();
await setReceiver("Egon");
await setMessage("Oi");
@@ -214,7 +224,8 @@ describe("
", () => {
});
it("shows a warning if the message is too long", async () => {
- setup();
+ renderComponent();
+
await setKudoAmount();
await setReceiver("Egon");
await setMessage(
@@ -231,7 +242,8 @@ describe("
", () => {
});
it("shows when the mutation is loading", async () => {
- setup();
+ renderComponent();
+
await setKudoAmount();
await setReceiver("Egon");
await setMessage("Some message");
@@ -244,7 +256,10 @@ describe("
", () => {
});
it("shows when there is an error", async () => {
- setup({ withErrors: true });
+ updateDecorator("application", (settings) => ({
+ mocks: [...mocksWithError, ...settings.mocks],
+ }));
+ renderComponent();
await setKudoAmount();
await setReceiver("Egon");
diff --git a/src/modules/feed/components/CreatePost/CreatePost.tsx b/src/modules/feed/components/CreatePost/CreatePost.tsx
index 5772ae98..4bf4d24d 100644
--- a/src/modules/feed/components/CreatePost/CreatePost.tsx
+++ b/src/modules/feed/components/CreatePost/CreatePost.tsx
@@ -345,7 +345,6 @@ export class CreatePost extends Component
{
ref={this.userDropdown}
onChange={this.handleDropdownChange}
error={receiversError}
- value={this.state.receivers}
/>
(v) = virtual user
diff --git a/src/modules/feed/components/GuidelineInput/GuidelineInput.spec.tsx b/src/modules/feed/components/GuidelineInput/GuidelineInput.spec.tsx
index 4e3f540b..946ccb42 100644
--- a/src/modules/feed/components/GuidelineInput/GuidelineInput.spec.tsx
+++ b/src/modules/feed/components/GuidelineInput/GuidelineInput.spec.tsx
@@ -1,12 +1,17 @@
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
import {
getSelectOptions,
getSelectedItemsText,
openSelect,
} from "../../../../support/testing/reactSelectHelpers";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
import { GET_GUIDELINES } from "../../../manage-team/sections/guideline/GuidelinesSection";
import GuidelineInput from "./GuidelineInput";
-import { render, waitFor, screen } from "@testing-library/react";
+import { waitFor, screen } from "@testing-library/react";
let queryCalled = false;
const mocks = [
@@ -64,18 +69,24 @@ const mocksWithoutData = [
describe("", () => {
const handleChangeMock = jest.fn();
+ const { renderComponent, updateDecorator } = setTestSubject(
+ makeFC(GuidelineInput),
+ {
+ decorators: [dataDecorator(mocks)],
+ props: {
+ handleChange: handleChangeMock,
+ amountError: false,
+ },
+ },
+ );
+
beforeEach(() => {
mockLocalstorage("1");
queryCalled = false;
});
it("handles state change correctly", async () => {
- render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
+ renderComponent();
const selectElement = await screen.findByRole("combobox", {
description: "Kudos amount",
@@ -88,45 +99,43 @@ describe("", () => {
});
it("display only guidelines that have a kudos value within a range of 5 from the selected guideline.", async () => {
- const modifiedMock = [...mocks];
- modifiedMock[0] = {
- ...mocks[0],
- result: () => {
- queryCalled = true;
- return {
- data: {
- teamById: {
- id: "1",
- __typename: "Team",
- guidelines: [
- {
- id: "1",
- kudos: 4,
- name: "Great help for someone",
- },
- {
- id: "2",
- kudos: 11,
- name: "Op tijd bij meeting",
- },
- {
- id: "3",
- kudos: 14, // Within range of 10
- name: "Bureau opgeruimd",
- },
- ],
+ updateDecorator("application", (settings) => {
+ const modifiedMock = [...settings.mocks];
+ modifiedMock[0] = {
+ ...mocks[0],
+ result: () => {
+ queryCalled = true;
+ return {
+ data: {
+ teamById: {
+ id: "1",
+ __typename: "Team",
+ guidelines: [
+ {
+ id: "1",
+ kudos: 4,
+ name: "Great help for someone",
+ },
+ {
+ id: "2",
+ kudos: 11,
+ name: "Op tijd bij meeting",
+ },
+ {
+ id: "3",
+ kudos: 14, // Within range of 10
+ name: "Bureau opgeruimd",
+ },
+ ],
+ },
},
- },
- };
- },
- };
+ };
+ },
+ };
+ return { mocks: modifiedMock };
+ });
- render(
- withMockedProviders(
- ,
- modifiedMock,
- ),
- );
+ renderComponent();
// Sets showGuidelines to true which is needed to trigger the query.
const selectElement = await screen.findByRole("combobox", {
@@ -149,12 +158,7 @@ describe("", () => {
});
it("shows the guidelines on down arrow", async () => {
- render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
+ renderComponent();
// Sets showGuidelines to true which is needed to trigger the query.
const selectElement = await screen.findByRole("combobox", {
@@ -170,12 +174,7 @@ describe("", () => {
});
it("calls the mutation if the input is focused and amount is not empty", async () => {
- render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
+ renderComponent();
expect(queryCalled).toBe(false);
@@ -191,12 +190,8 @@ describe("", () => {
});
it("shows a message when there are no guidelines", async () => {
- render(
- withMockedProviders(
- ,
- mocksWithoutData,
- ),
- );
+ updateDecorator("application", { mocks: mocksWithoutData });
+ renderComponent();
// Sets showGuidelines to true which is needed to trigger the query.
const selectElement = await screen.findByRole("combobox", {
@@ -208,12 +203,8 @@ describe("", () => {
});
it("is disabled when the query is loading", async () => {
- render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
+ renderComponent();
+
const selectElement = screen.getByRole("combobox", {
description: "Kudos amount",
hidden: true,
@@ -227,12 +218,7 @@ describe("", () => {
});
it("reports the correct amount when a guideline is clicked", async () => {
- render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
+ renderComponent();
// Sets showGuidelines to true which is needed to trigger the query.
const selectElement = await screen.findByRole("combobox", {
@@ -242,7 +228,7 @@ describe("", () => {
const options = getSelectOptions(selectElement);
options[1].click();
- expect(handleChangeMock).toBeCalledWith(15);
+ expect(handleChangeMock).toHaveBeenCalledWith(15);
expect(getSelectedItemsText(selectElement)).toEqual("15");
});
});
diff --git a/src/modules/feed/components/RightRail.spec.tsx b/src/modules/feed/components/RightRail.spec.tsx
index 34b6b6f5..a4280e6e 100644
--- a/src/modules/feed/components/RightRail.spec.tsx
+++ b/src/modules/feed/components/RightRail.spec.tsx
@@ -1,15 +1,23 @@
-import { render, screen } from "@testing-library/react";
-import { mockLocalstorage, withMockedProviders } from "../../../spec_helper";
+import { screen } from "@testing-library/react";
+import { mockLocalstorage } from "../../../spec_helper";
import RightRail from "./RightRail";
import { mocks as goalMocks } from "../../statistics/Statistics.spec";
+import { setTestSubject } from "../../../support/testing/testSubject";
+import { dataDecorator } from "../../../support/testing/testDecorators";
describe("", () => {
+ const { renderComponent } = setTestSubject(RightRail, {
+ decorators: [dataDecorator(goalMocks("1"))],
+ props: {},
+ });
+
beforeEach(() => {
mockLocalstorage("1");
- render(withMockedProviders(, goalMocks("1")));
});
it("renders the statistics section", async () => {
+ renderComponent();
+
const element = await screen.findByText("₭udometer");
expect(element).toBeInTheDocument();
});
diff --git a/src/modules/feed/components/Transaction/Header.spec.tsx b/src/modules/feed/components/Transaction/Header.spec.tsx
index 3640e140..3f4c40da 100644
--- a/src/modules/feed/components/Transaction/Header.spec.tsx
+++ b/src/modules/feed/components/Transaction/Header.spec.tsx
@@ -1,11 +1,12 @@
-import {
- MockedFunction,
- mockLocalstorage,
- withMockedProviders,
-} from "../../../../spec_helper";
+import { MockedFunction, mockLocalstorage } from "../../../../spec_helper";
import { Header, MUTATION_REMOVE_POST } from "./Header";
import { FragmentPostResult, GET_POSTS } from "../../queries";
-import { screen, render, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
const transaction: FragmentPostResult = {
amount: 5,
@@ -85,6 +86,11 @@ const mocks = [
];
describe("", () => {
+ const { renderComponent, updateProps } = setTestSubject(makeFC(Header), {
+ decorators: [dataDecorator(mocks)],
+ props: { transaction },
+ });
+
beforeEach(() => {
mockLocalstorage("1");
mutationCalled = false;
@@ -92,41 +98,45 @@ describe("", () => {
});
it("shows the correct kudo amount", async () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
+
const amount = await screen.findByTestId("post-amount");
expect(amount.textContent).toBe("5");
});
// This functionality is disabled in the code
it.skip("shows the correct timestamp", async () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
+
const timestamp = await screen.findByTestId("post-timestamp");
expect(timestamp.textContent).toContain("a few seconds ago");
});
it("shows the senders avatar", async () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
+
const senderAvatar = await screen.findByTestId("sender-avatar");
expect(senderAvatar.getAttribute("src")).toBe("fakeAvatarUrl");
});
it("shows the receivers avatar", async () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
+
const receiverAvatar = await screen.findByTestId("receiver-avatar");
expect(receiverAvatar.getAttribute("src")).toBe("receiverAvatarUrl");
});
it("allows the user to remove his own post within 15 minutes", () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
+
const deleteButton = screen.queryByTestId("delete-button");
expect(deleteButton).not.toBeNull();
});
// deletion is always allowed now...
it.skip("prevents the user to remove his own post after 15 minutes", () => {
- render(
- withMockedProviders(, mocks),
- );
+ updateProps({ transaction: olderTransaction });
+ renderComponent();
const deleteButton = screen.queryByTestId("delete-button");
expect(deleteButton).toBeNull();
@@ -134,7 +144,7 @@ describe("", () => {
it("always allows an admin to remove a post", () => {
mockLocalstorage("admin");
- render(withMockedProviders(, mocks));
+ renderComponent();
const deleteButton = screen.queryAllByTestId("delete-button");
expect(deleteButton).not.toBeNull();
@@ -142,7 +152,7 @@ describe("", () => {
it("does not allow an other user to delete the post", () => {
mockLocalstorage("3");
- render(withMockedProviders(, mocks));
+ renderComponent();
const deleteButton = screen.queryByTestId("delete-button");
expect(deleteButton).toBeNull();
@@ -151,7 +161,7 @@ describe("", () => {
describe("when deleting a post", () => {
beforeEach(() => {
global.confirm = jest.fn(() => true);
- render(withMockedProviders(, mocks));
+ renderComponent();
});
it("shows a confirmation dialog ", () => {
diff --git a/src/modules/feed/components/Transaction/LikeButton.spec.tsx b/src/modules/feed/components/Transaction/LikeButton.spec.tsx
index 66357757..210414e8 100644
--- a/src/modules/feed/components/Transaction/LikeButton.spec.tsx
+++ b/src/modules/feed/components/Transaction/LikeButton.spec.tsx
@@ -1,12 +1,17 @@
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
import LikeButton, { MUTATION_TOGGLE_LIKE } from "./LikeButton";
import {
FragmentPostResult,
GET_GOAL_PERCENTAGE,
GET_POSTS,
} from "../../queries";
-import { render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
import { InMemoryCache } from "@apollo/client";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
const likedPost: FragmentPostResult = {
id: "1",
@@ -85,24 +90,33 @@ const mocks = [
];
describe("", () => {
+ const { renderComponent, updateProps, updateDecorator } = setTestSubject(
+ makeFC(LikeButton),
+ {
+ decorators: [dataDecorator(mocks)],
+ props: {
+ liked: false,
+ post: likedPost,
+ },
+ },
+ );
+
beforeEach(() => {
mutationCalled = false;
mockLocalstorage("1");
});
it("renders the correct message", async () => {
- render(
- withMockedProviders(, mocks),
- );
+ renderComponent();
+
const message = await screen.findByTestId("message");
expect(message.textContent).toBe("+1₭ by Max");
});
it("renders the correct like icon if the post is not liked", async () => {
- render(
- withMockedProviders(, mocks),
- );
+ renderComponent();
+
const likeButton = await screen.findByRole("button");
const icon = likeButton.querySelector(
@@ -115,9 +129,8 @@ describe("", () => {
});
it("renders the correct like icon if the post is liked", async () => {
- render(
- withMockedProviders(, mocks),
- );
+ updateProps({ liked: true });
+ renderComponent();
const likeButton = await screen.findByRole("button");
const icon = likeButton.querySelector(
@@ -173,13 +186,8 @@ describe("", () => {
},
});
- render(
- withMockedProviders(
- ,
- mocks,
- cache,
- ),
- );
+ updateDecorator("application", { cache: cache });
+ renderComponent();
const likeButton = await screen.findByRole("button");
likeButton.click();
diff --git a/src/modules/feed/components/Transaction/Transaction.spec.tsx b/src/modules/feed/components/Transaction/Transaction.spec.tsx
index ca093fd4..0321de65 100644
--- a/src/modules/feed/components/Transaction/Transaction.spec.tsx
+++ b/src/modules/feed/components/Transaction/Transaction.spec.tsx
@@ -1,7 +1,8 @@
-import { withMockedProviders } from "../../../../spec_helper";
import { Transaction } from "./index";
import { FragmentPostResult } from "../../queries";
-import { render, screen } from "@testing-library/react";
+import { screen } from "@testing-library/react";
+import { setTestSubject } from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
const transaction: FragmentPostResult = {
id: "1",
@@ -37,10 +38,13 @@ const transactionWithVote = {
};
describe("Transaction", () => {
+ const { renderComponent } = setTestSubject(Transaction, {
+ decorators: [dataDecorator()],
+ props: { transaction: transactionWithVote },
+ });
+
beforeEach(() => {
- render(
- withMockedProviders(),
- );
+ renderComponent();
});
it("renders the kudos amount without votes", () => {
diff --git a/src/modules/feed/components/UserDropdown/UserDropdown.spec.tsx b/src/modules/feed/components/UserDropdown/UserDropdown.spec.tsx
index 9434e497..0fd2b5c7 100644
--- a/src/modules/feed/components/UserDropdown/UserDropdown.spec.tsx
+++ b/src/modules/feed/components/UserDropdown/UserDropdown.spec.tsx
@@ -1,12 +1,17 @@
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
import DropdownRemote from "./UserDropdown";
import { GET_USERS } from "../../queries";
-import { render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
import {
getSelectOptions,
openSelect,
} from "../../../../support/testing/reactSelectHelpers";
import userEvent from "@testing-library/user-event";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
export const mocksWithData = (teamId: string) => [
{
@@ -72,22 +77,25 @@ const mocksWithoutData = (teamId: string) => [
const handleChangeMock = jest.fn();
-const setup = (mocks: any) => {
- render(
- withMockedProviders(
- ,
- mocks,
- ),
+describe("", () => {
+ const { renderComponent, updateDecorator } = setTestSubject(
+ makeFC(DropdownRemote),
+ {
+ decorators: [dataDecorator(mocksWithData("1"))],
+ props: {
+ onChange: handleChangeMock,
+ error: false,
+ },
+ },
);
-};
-describe("", () => {
beforeEach(() => {
mockLocalstorage("1");
});
it("shows when the users are loading", async () => {
- setup(mocksWithData("1"));
+ renderComponent();
+
const input = screen.getByRole("combobox", {
description: "Receivers",
hidden: true,
@@ -102,7 +110,9 @@ describe("", () => {
});
it.skip("shows when there is an error", () => {
- setup(mocksWithError);
+ updateDecorator("application", { mocks: mocksWithError });
+ renderComponent();
+
const input = screen.getByRole("combobox", {
description: "Receivers",
hidden: true,
@@ -111,7 +121,9 @@ describe("", () => {
});
it("shows when there are no users", async () => {
- setup(mocksWithoutData("1"));
+ updateDecorator("application", { mocks: mocksWithoutData("1") });
+ renderComponent();
+
const input = await screen.findByRole("combobox", {
description: "Receivers",
});
@@ -121,7 +133,8 @@ describe("", () => {
});
it("creates an option for each user", async () => {
- setup(mocksWithData("1"));
+ renderComponent();
+
const input = await screen.findByRole("combobox", {
description: "Receivers",
});
@@ -131,7 +144,8 @@ describe("", () => {
});
it("handles change correctly", async () => {
- setup(mocksWithData("1"));
+ renderComponent();
+
const input = await screen.findByRole("combobox", {
description: "Receivers",
});
diff --git a/src/modules/feed/components/UserDropdown/UserDropdown.tsx b/src/modules/feed/components/UserDropdown/UserDropdown.tsx
index a104dc80..e78651fa 100644
--- a/src/modules/feed/components/UserDropdown/UserDropdown.tsx
+++ b/src/modules/feed/components/UserDropdown/UserDropdown.tsx
@@ -1,4 +1,4 @@
-import { Component, PropsWithRef } from "react";
+import { Component } from "react";
import { Query } from "@apollo/client/react/components";
import client from "../../../../client";
@@ -8,10 +8,10 @@ import { Storage } from "../../../../support/storage";
import { OnChangeValue } from "react-select";
import CreatableSelect from "react-select/creatable";
-export interface DropDownProps extends PropsWithRef {
+export type DropDownProps = {
onChange: (values: readonly NameOption[]) => void;
error: boolean;
-}
+};
export interface DropDownState {
values: readonly NameOption[];
diff --git a/src/modules/login/FinishForgotPasswordPage.spec.tsx b/src/modules/login/FinishForgotPasswordPage.spec.tsx
index dc44e84c..db9f3304 100644
--- a/src/modules/login/FinishForgotPasswordPage.spec.tsx
+++ b/src/modules/login/FinishForgotPasswordPage.spec.tsx
@@ -1,15 +1,10 @@
import { GraphQLError } from "graphql";
-import { withMockedProviders } from "../../spec_helper";
import { MUTATION_NEW_PASSWORD } from "./FinishForgotPasswordPage";
import { RouterBypassFinishForgotPasswordPage as FinishForgotPasswordPage } from "./index";
-import {
- RenderResult,
- fireEvent,
- render,
- screen,
- waitFor,
-} from "@testing-library/react";
-import { createBrowserHistory } from "history";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
+import { makeFC, setTestSubject } from "../../support/testing/testSubject";
+import { dataDecorator } from "../../support/testing/testDecorators";
+import { createRouterProps } from "../../spec_helper";
let mutationCalled = false;
const mocks = [
@@ -50,32 +45,28 @@ const mocks = [
},
];
+const createLocationWithToken = (token: string) => ({
+ search: `reset_password_token=${token}`,
+ pathname: "",
+ state: "",
+ hash: "",
+});
+
describe("", () => {
- const createPropsWithToken = (token: string) => ({
- location: {
- search: `reset_password_token=${token}`,
- pathname: "",
- state: "",
- hash: "",
- },
- history: createBrowserHistory(),
- match: {
- params: "",
- isExact: false,
- path: "",
- url: "",
+ const { renderComponent, updateProps } = setTestSubject(
+ makeFC(FinishForgotPasswordPage),
+ {
+ decorators: [dataDecorator(mocks)],
+ props: {
+ ...createRouterProps(),
+ location: createLocationWithToken("19810531"),
+ },
},
- });
-
- let renderResult: RenderResult;
+ );
beforeEach(() => {
- const props = createPropsWithToken("19810531");
-
mutationCalled = false;
- renderResult = render(
- withMockedProviders(, mocks),
- );
+ renderComponent();
});
it("Displays a reset password header", () => {
@@ -148,10 +139,8 @@ describe("", () => {
});
it("shows when there is an error", () => {
- renderResult.unmount();
-
- const props = createPropsWithToken("90210");
- render(withMockedProviders(, mocks));
+ updateProps({ location: createLocationWithToken("90210") });
+ renderComponent();
const passwordField = screen.getByLabelText("Password");
fireEvent.change(passwordField, { target: { value: "password" } });
diff --git a/src/modules/login/ForgotPasswordPage.spec.tsx b/src/modules/login/ForgotPasswordPage.spec.tsx
index 208aa910..cee80f09 100644
--- a/src/modules/login/ForgotPasswordPage.spec.tsx
+++ b/src/modules/login/ForgotPasswordPage.spec.tsx
@@ -1,8 +1,9 @@
import { GraphQLError } from "graphql";
-import { withMockedProviders } from "../../spec_helper";
import { ForgotPasswordPage } from "./index";
import { MUTATION_FORGOT_PASSWORD } from "./ForgotPasswordPage";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
+import { makeFC, setTestSubject } from "../../support/testing/testSubject";
+import { dataDecorator } from "../../support/testing/testDecorators";
let mutationCalled = false;
const mocks = [
@@ -38,9 +39,14 @@ const mocks = [
];
describe("", () => {
+ const { renderComponent } = setTestSubject(makeFC(ForgotPasswordPage), {
+ decorators: [dataDecorator(mocks)],
+ props: {},
+ });
+
beforeEach(() => {
mutationCalled = false;
- render(withMockedProviders(, mocks));
+ renderComponent();
});
it("displays a header for the page", () => {
diff --git a/src/modules/login/LoginPage.spec.tsx b/src/modules/login/LoginPage.spec.tsx
index 46518cdc..08e9cf38 100644
--- a/src/modules/login/LoginPage.spec.tsx
+++ b/src/modules/login/LoginPage.spec.tsx
@@ -1,8 +1,12 @@
import { GraphQLError } from "graphql";
import { LoginPage } from "./index";
-import { withMockedProviders } from "../../spec_helper";
import { MUTATION_LOGIN } from "./LoginPage";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
+import { makeFC, setTestSubject } from "../../support/testing/testSubject";
+import {
+ dataDecorator,
+ routingDecorator,
+} from "../../support/testing/testDecorators";
let mutationCalled = false;
const mocks = [
@@ -45,9 +49,14 @@ const mocks = [
];
describe("", () => {
+ const { renderComponent } = setTestSubject(makeFC(LoginPage), {
+ decorators: [dataDecorator(mocks), routingDecorator()],
+ props: {},
+ });
+
beforeEach(() => {
mutationCalled = false;
- render(withMockedProviders(, mocks));
+ renderComponent();
});
it("has a forgot password button", () => {
diff --git a/src/modules/login/RegisterPage.spec.tsx b/src/modules/login/RegisterPage.spec.tsx
index a8faffed..f16df789 100644
--- a/src/modules/login/RegisterPage.spec.tsx
+++ b/src/modules/login/RegisterPage.spec.tsx
@@ -1,8 +1,12 @@
import { GraphQLError } from "graphql";
-import { withMockedProviders } from "../../spec_helper";
import { RegisterPage } from "./index";
import { MUTATION_REGISTER } from "./RegisterPage";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
+import { makeFC, setTestSubject } from "../../support/testing/testSubject";
+import {
+ dataDecorator,
+ routingDecorator,
+} from "../../support/testing/testDecorators";
let mutationCalled = false;
const mocks = [
@@ -47,9 +51,15 @@ const mocks = [
];
describe("", () => {
+ const { renderComponent } = setTestSubject(makeFC(RegisterPage), {
+ decorators: [dataDecorator(mocks), routingDecorator()],
+ props: {},
+ });
+
beforeEach(() => {
mutationCalled = false;
- render(withMockedProviders(, mocks));
+
+ renderComponent();
});
it("handles input correctly", async () => {
diff --git a/src/modules/manage-team/ManageTeamPage.spec.tsx b/src/modules/manage-team/ManageTeamPage.spec.tsx
index 1089feaf..6c1bef00 100644
--- a/src/modules/manage-team/ManageTeamPage.spec.tsx
+++ b/src/modules/manage-team/ManageTeamPage.spec.tsx
@@ -1,15 +1,25 @@
import { createMemoryHistory, MemoryHistory } from "history";
-import { withMockedProviders } from "../../spec_helper";
import { ManageTeamPage } from "./ManageTeamPage";
-import { render, screen } from "@testing-library/react";
+import { screen } from "@testing-library/react";
+import { makeFC, setTestSubject } from "../../support/testing/testSubject";
+import { routingDecorator } from "../../support/testing/testDecorators";
+import { createRouterProps } from "../../spec_helper";
describe("", () => {
let history: MemoryHistory;
+ const { setProps, renderComponent } = setTestSubject(makeFC(ManageTeamPage), {
+ decorators: [routingDecorator()],
+ });
+
beforeEach(() => {
history = createMemoryHistory();
+ setProps({
+ ...createRouterProps(),
+ history,
+ });
- render(withMockedProviders());
+ renderComponent();
});
it("navigates to the general section", () => {
diff --git a/src/modules/manage-team/ManageTeamPage.tsx b/src/modules/manage-team/ManageTeamPage.tsx
index 37bb850e..6686b669 100644
--- a/src/modules/manage-team/ManageTeamPage.tsx
+++ b/src/modules/manage-team/ManageTeamPage.tsx
@@ -1,7 +1,6 @@
import { Component, MouseEvent } from "react";
-import { History } from "history";
-import { Route, Switch, withRouter } from "react-router-dom";
+import { Route, RouteComponentProps, Switch } from "react-router-dom";
import s from "./ManageTeamPage.module.scss";
import {
@@ -19,15 +18,11 @@ import { PATH_MANAGE_TEAM } from "../../routes";
import { Card } from "../../ui/Card";
import IntegrationSections from "./sections/integrations/Integrations";
-export interface Props {
- history: History;
-}
-
export interface State {
activeItem: string;
}
-export class ManageTeamPage extends Component {
+export class ManageTeamPage extends Component {
sections: { icon: string; name: string }[] = [
{ icon: "settings", name: "general" },
{ icon: "steps", name: "guidelines" },
@@ -37,7 +32,7 @@ export class ManageTeamPage extends Component {
{ icon: "move_up", name: "integrations" },
];
- constructor(props: Props) {
+ constructor(props: RouteComponentProps) {
super(props);
const location = props.history.location.pathname;
@@ -118,5 +113,4 @@ export class ManageTeamPage extends Component {
}
}
-// @ts-ignore
-export default withRouter(ManageTeamPage);
+export default ManageTeamPage;
diff --git a/src/modules/manage-team/sections/General.spec.tsx b/src/modules/manage-team/sections/General.spec.tsx
index f9df6698..87c67614 100644
--- a/src/modules/manage-team/sections/General.spec.tsx
+++ b/src/modules/manage-team/sections/General.spec.tsx
@@ -1,6 +1,8 @@
-import { mockLocalstorage, withMockedProviders } from "../../../spec_helper";
+import { mockLocalstorage } from "../../../spec_helper";
+import { makeFC, setTestSubject } from "../../../support/testing/testSubject";
+import { dataDecorator } from "../../../support/testing/testDecorators";
import GeneralSection, { GET_TEAM_NAME, UPDATE_TEAM } from "./General";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
let mutationCalled = false;
const mocks = [
@@ -61,13 +63,18 @@ const mocksWithError = [
];
describe("", () => {
+ const { renderComponent, updateDecorator } = setTestSubject(
+ makeFC(GeneralSection),
+ { decorators: [dataDecorator(mocks)], props: {} },
+ );
+
beforeEach(() => {
mockLocalstorage("1");
mutationCalled = false;
});
it("shows when the query is loading", async () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
expect(screen.getByText("Loading...")).toBeInTheDocument();
expect(
@@ -76,7 +83,8 @@ describe("", () => {
});
it("shows when there is an error", async () => {
- render(withMockedProviders(, mocksWithError));
+ updateDecorator("application", { mocks: mocksWithError });
+ renderComponent();
expect(
await screen.findByText("Error! something went wrong"),
@@ -84,7 +92,7 @@ describe("", () => {
});
it("renders the team name", async () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
expect(
await screen.findByRole("heading", { name: "Kabisa", level: 1 }),
@@ -92,7 +100,7 @@ describe("", () => {
});
it("handles input correctly", async () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
await screen.findByRole("heading", { name: "Kabisa", level: 1 });
diff --git a/src/modules/manage-team/sections/guideline/EditGuideline.spec.tsx b/src/modules/manage-team/sections/guideline/EditGuideline.spec.tsx
index 2ca07181..408d7fd7 100644
--- a/src/modules/manage-team/sections/guideline/EditGuideline.spec.tsx
+++ b/src/modules/manage-team/sections/guideline/EditGuideline.spec.tsx
@@ -1,11 +1,16 @@
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
import { EditGuideline } from "./EditGuideline";
import {
CREATE_GUIDELINE,
GET_GUIDELINES,
UPDATE_GUIDELINE,
} from "./GuidelinesSection";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
import { createRef } from "react";
let createMutationCalled = false;
@@ -86,6 +91,14 @@ const mocks = [
];
describe("", () => {
+ const { renderComponent, updateProps } = setTestSubject(
+ makeFC(EditGuideline),
+ {
+ decorators: [dataDecorator(mocks)],
+ props: {},
+ },
+ );
+
beforeEach(() => {
mockLocalstorage("1");
updateMutationCalled = false;
@@ -94,7 +107,7 @@ describe("", () => {
});
it("calls the create mutation if editing is set to false", async () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
const amountKudoInput = screen.getByLabelText("Amount of kudos");
fireEvent.change(amountKudoInput, { target: { value: "10" } });
@@ -112,7 +125,8 @@ describe("", () => {
it("calls the update mutation if editing is set to true", async () => {
const componentRef = createRef();
- render(withMockedProviders(, mocks));
+ updateProps({ ref: componentRef });
+ renderComponent();
componentRef.current?.setEditState(2, "10", "test guideline");
@@ -135,7 +149,8 @@ describe("", () => {
it("shows a cancel button when editing", () => {
const componentRef = createRef();
- render(withMockedProviders(, mocks));
+ updateProps({ ref: componentRef });
+ renderComponent();
componentRef.current?.setEditState(2, "10", "test guideline");
@@ -146,7 +161,7 @@ describe("", () => {
});
it("does not show a cancel button when not editing", () => {
- render(withMockedProviders(, mocks));
+ renderComponent();
const cancelButton = screen.queryByRole("button", {
name: "Cancel",
@@ -156,7 +171,8 @@ describe("", () => {
it("clears the edit state when pressing the cancel buttons", () => {
const componentRef = createRef();
- render(withMockedProviders(, mocks));
+ updateProps({ ref: componentRef });
+ renderComponent();
componentRef.current?.setEditState(2, "10", "test guideline");
diff --git a/src/modules/manage-team/sections/guideline/Guideline.spec.tsx b/src/modules/manage-team/sections/guideline/Guideline.spec.tsx
index b92816f3..3832570f 100644
--- a/src/modules/manage-team/sections/guideline/Guideline.spec.tsx
+++ b/src/modules/manage-team/sections/guideline/Guideline.spec.tsx
@@ -1,11 +1,12 @@
+import { MockedFunction, mockLocalstorage } from "../../../../spec_helper";
+import { setTestSubject } from "../../../../support/testing/testSubject";
import {
- MockedFunction,
- mockLocalstorage,
- withMockedProviders,
-} from "../../../../spec_helper";
+ dataDecorator,
+ tableDecorator,
+} from "../../../../support/testing/testDecorators";
import { DELETE_GUIDELINE, Guideline } from "./Guideline";
import { GET_GUIDELINES } from "./GuidelinesSection";
-import { render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
let mutationCalled = false;
let getGuidelinesCalled = false;
@@ -65,25 +66,21 @@ const guideline = {
describe("", () => {
const editGuidelineMock = jest.fn();
+ const { renderComponent } = setTestSubject(Guideline, {
+ decorators: [tableDecorator, dataDecorator(mocks)],
+ props: {
+ key: guideline.key,
+ name: guideline.name,
+ id: guideline.id,
+ kudos: guideline.kudos,
+ editGuideline: editGuidelineMock,
+ },
+ });
+
beforeEach(() => {
mockLocalstorage("1");
global.confirm = jest.fn(() => true);
- render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
+ renderComponent();
});
it("renders the guideline name", () => {
diff --git a/src/modules/manage-team/sections/guideline/GuidelinesSection.spec.tsx b/src/modules/manage-team/sections/guideline/GuidelinesSection.spec.tsx
index 0e044e57..17a0938a 100644
--- a/src/modules/manage-team/sections/guideline/GuidelinesSection.spec.tsx
+++ b/src/modules/manage-team/sections/guideline/GuidelinesSection.spec.tsx
@@ -1,6 +1,11 @@
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
import GuidelineSection, { GET_GUIDELINES } from "./GuidelinesSection";
-import { render, screen } from "@testing-library/react";
+import { screen } from "@testing-library/react";
export const mocks = (teamId: string) => [
{
@@ -44,12 +49,18 @@ const errorMocks = [
];
describe("", () => {
+ const { renderComponent, updateDecorator } = setTestSubject(
+ makeFC(GuidelineSection),
+ { decorators: [dataDecorator(mocks("1"))], props: {} },
+ );
+
beforeEach(() => {
mockLocalstorage("1");
});
it("shows a loading state", async () => {
- render(withMockedProviders(, mocks("1")));
+ renderComponent();
+
expect(screen.getByText("Loading...")).toBeInTheDocument();
// Wait for fetch to complete before unmount
@@ -57,12 +68,14 @@ describe("", () => {
});
it("shows when there is an error", async () => {
- render(withMockedProviders(, errorMocks));
+ updateDecorator("application", { mocks: errorMocks });
+ renderComponent();
+
expect(await screen.findByText("Error! it went wrong")).toBeInTheDocument();
});
it("shows a row for each guideline ", async () => {
- render(withMockedProviders(, mocks("1")));
+ renderComponent();
const rows = await screen.findAllByRole("row");
// 1 header row, 2 data rows
diff --git a/src/modules/manage-team/sections/integrations/Integrations.spec.tsx b/src/modules/manage-team/sections/integrations/Integrations.spec.tsx
index 98530b4d..b9224c71 100644
--- a/src/modules/manage-team/sections/integrations/Integrations.spec.tsx
+++ b/src/modules/manage-team/sections/integrations/Integrations.spec.tsx
@@ -1,10 +1,15 @@
-import { createMemoryHistory, History } from "history";
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { createMemoryHistory } from "history";
+import { mockLocalstorage } from "../../../../spec_helper";
import IntegrationsSection, {
GET_TEAM_INTEGRATIONS,
REMOVE_SLACK,
} from "./Integrations";
-import { render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
let mutationCalled = false;
const mocksWithoutSlack = [
@@ -80,20 +85,25 @@ const mocksWithError = [
},
];
-let history: History;
-const setup = (mocks: any) => {
- history = createMemoryHistory();
- mutationCalled = false;
- render(withMockedProviders(, mocks));
-};
-
describe("", () => {
+ const { renderComponent, updateDecorator } = setTestSubject(
+ makeFC(IntegrationsSection),
+ {
+ decorators: [dataDecorator(mocksWithoutSlack)],
+ props: {
+ history: createMemoryHistory(),
+ },
+ },
+ );
+
beforeEach(() => {
mockLocalstorage("1");
+ mutationCalled = false;
});
it("shows when the query is loading", async () => {
- setup(mocksWithoutSlack);
+ renderComponent();
+
expect(screen.getByText("Loading...")).toBeInTheDocument();
await waitFor(() => {
@@ -102,14 +112,17 @@ describe("", () => {
});
it("shows when there is an error", async () => {
- setup(mocksWithError);
+ updateDecorator("application", { mocks: mocksWithError });
+ renderComponent();
+
const errorMessage = await screen.findByText("something went wrong");
expect(errorMessage).toBeInTheDocument();
});
describe("not connected to Slack", () => {
beforeEach(() => {
- setup(mocksWithoutSlack);
+ updateDecorator("application", { mocks: mocksWithoutSlack });
+ renderComponent();
});
it("shows the slack disconnected container", async () => {
@@ -147,7 +160,8 @@ describe("", () => {
describe("connected to slack", () => {
beforeEach(() => {
- setup(mocksWitSlack);
+ updateDecorator("application", { mocks: mocksWitSlack });
+ renderComponent();
});
it("shows the connected to slack container", async () => {
diff --git a/src/modules/manage-team/sections/invite/CreateInvite.spec.tsx b/src/modules/manage-team/sections/invite/CreateInvite.spec.tsx
index ee65534d..55f62b9f 100644
--- a/src/modules/manage-team/sections/invite/CreateInvite.spec.tsx
+++ b/src/modules/manage-team/sections/invite/CreateInvite.spec.tsx
@@ -1,7 +1,12 @@
import { CreateInvite, MUTATION_CREATE_INVITE } from "./CreateInvite";
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
import { QUERY_GET_INVITES } from "./InvitesSection";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
let mutationCalled = false;
const mocks = [
@@ -56,10 +61,17 @@ const mocks = [
describe("", () => {
const mockRefetch = jest.fn();
+ const { renderComponent } = setTestSubject(makeFC(CreateInvite), {
+ decorators: [dataDecorator(mocks)],
+ props: {
+ refetch: mockRefetch,
+ },
+ });
+
beforeEach(() => {
mockLocalstorage("1");
mutationCalled = false;
- render(withMockedProviders(, mocks));
+ renderComponent();
});
it("renders the e-mail input field", () => {
diff --git a/src/modules/manage-team/sections/invite/Invite.spec.tsx b/src/modules/manage-team/sections/invite/Invite.spec.tsx
index 216e79d8..e1b70b64 100644
--- a/src/modules/manage-team/sections/invite/Invite.spec.tsx
+++ b/src/modules/manage-team/sections/invite/Invite.spec.tsx
@@ -1,11 +1,12 @@
+import { MockedFunction, mockLocalstorage } from "../../../../spec_helper";
+import { setTestSubject } from "../../../../support/testing/testSubject";
import {
- MockedFunction,
- mockLocalstorage,
- withMockedProviders,
-} from "../../../../spec_helper";
+ dataDecorator,
+ tableDecorator,
+} from "../../../../support/testing/testDecorators";
import { Invite, MUTATION_DELETE_INVITE } from "./Invite";
import { InviteModel, QUERY_GET_INVITES } from "./InvitesSection";
-import { render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
const pendingInvite: InviteModel = {
acceptedAt: "",
@@ -77,27 +78,24 @@ const mocks = [
];
describe("", () => {
- function setup(invite: InviteModel) {
- const mockRefetch = jest.fn();
-
- render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
- }
+ const mockRefetch = jest.fn();
+
+ const { renderComponent, updateProps } = setTestSubject(Invite, {
+ decorators: [tableDecorator, dataDecorator(mocks)],
+ props: {
+ invite: pendingInvite,
+ key: 1,
+ refetch: mockRefetch,
+ },
+ });
beforeEach(() => {
global.confirm = jest.fn(() => true);
mockLocalstorage("1");
mutationCalled = false;
queryCalled = false;
- setup(pendingInvite);
+
+ renderComponent();
});
it("shows the invite send date and email", () => {
@@ -114,14 +112,16 @@ describe("", () => {
});
it("shows that the invite is accepted", () => {
- setup(acceptedInvite);
+ updateProps({ invite: acceptedInvite });
+ renderComponent();
const status = screen.getByRole("cell", { name: "Accepted" });
expect(status).toBeInTheDocument();
});
it("shows that the invite is declined", () => {
- setup(declinedInvite);
+ updateProps({ invite: declinedInvite });
+ renderComponent();
const status = screen.getByRole("cell", { name: "Declined" });
expect(status).toBeInTheDocument();
diff --git a/src/modules/manage-team/sections/invite/InviteSection.spec.tsx b/src/modules/manage-team/sections/invite/InviteSection.spec.tsx
index 7ecc6597..f682eb33 100644
--- a/src/modules/manage-team/sections/invite/InviteSection.spec.tsx
+++ b/src/modules/manage-team/sections/invite/InviteSection.spec.tsx
@@ -1,6 +1,8 @@
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
+import { setTestSubject } from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
import InviteSection, { QUERY_GET_INVITES } from "./InvitesSection";
-import { render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
const mocks = [
{
@@ -44,12 +46,18 @@ const mocksWithError = [
];
describe("", () => {
+ const { renderComponent, updateDecorator } = setTestSubject(InviteSection, {
+ decorators: [dataDecorator(mocks)],
+ props: {},
+ });
+
beforeEach(() => {
mockLocalstorage("1");
- render(withMockedProviders(, mocks));
});
it("shows a loading message", async () => {
+ renderComponent();
+
expect(screen.getByText("Loading...")).toBeInTheDocument();
await waitFor(() => {
@@ -58,16 +66,22 @@ describe("", () => {
});
it("shows when there is an error", async () => {
- render(withMockedProviders(, mocksWithError));
+ updateDecorator("application", { mocks: mocksWithError });
+ renderComponent();
+
expect(await screen.findByText("Error! it broke")).toBeInTheDocument();
});
it("renders a row for each invite", async () => {
+ renderComponent();
+
// header row + 2 data rows
expect(await screen.findAllByRole("row")).toHaveLength(1 + 2);
});
it("renders the add invites section", async () => {
+ renderComponent();
+
expect(
await screen.findByRole("button", { name: "Invite" }),
).toBeInTheDocument();
diff --git a/src/modules/manage-team/sections/kudometer/KudometerRow.spec.tsx b/src/modules/manage-team/sections/kudometer/KudometerRow.spec.tsx
index 1317568f..5cdb78fe 100644
--- a/src/modules/manage-team/sections/kudometer/KudometerRow.spec.tsx
+++ b/src/modules/manage-team/sections/kudometer/KudometerRow.spec.tsx
@@ -1,8 +1,4 @@
-import {
- MockedFunction,
- mockLocalstorage,
- withMockedProviders,
-} from "../../../../spec_helper";
+import { MockedFunction, mockLocalstorage } from "../../../../spec_helper";
import { KudometerRow } from "./KudometerRow";
import {
DELETE_KUDOMETER,
@@ -11,7 +7,12 @@ import {
SET_ACTIVE_KUDOS_METER,
} from "./KudometerQueries";
import { GET_GOAL_PERCENTAGE } from "../../../feed/queries";
-import { render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
+import { setTestSubject } from "../../../../support/testing/testSubject";
+import {
+ dataDecorator,
+ tableDecorator,
+} from "../../../../support/testing/testDecorators";
const getKudometer = (isActive: boolean): Kudometer => ({
id: "1",
@@ -112,43 +113,37 @@ const viewButtonHandler = jest.fn();
const deleteHandler = jest.fn();
const editHandler = jest.fn();
-const setup = (kudometer: Kudometer) => {
- mutationCalled = false;
- makeActiveMutationCalled = false;
- queryCalled = false;
- render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
-};
-
describe("", () => {
+ const { renderComponent, updateProps } = setTestSubject(KudometerRow, {
+ decorators: [tableDecorator, dataDecorator(mocks)],
+ props: {
+ key: "1",
+ kudometer: getKudometer(false),
+ viewButtonClickHandler: viewButtonHandler,
+ deleteKudometerHandler: deleteHandler,
+ edit: editHandler,
+ },
+ });
+
beforeEach(() => {
global.confirm = jest.fn(() => true);
+ mutationCalled = false;
+ makeActiveMutationCalled = false;
+ queryCalled = false;
mockLocalstorage("1");
});
it("shows the kudometer name", async () => {
- setup(getKudometer(false));
+ renderComponent();
+
expect(
await screen.findByRole("cell", { name: "First kudometer" }),
).toBeInTheDocument();
});
it("opens the goals", async () => {
- setup(getKudometer(false));
+ renderComponent();
+
const goalButton = screen.getByRole("button", { name: "View goals" });
goalButton.click();
@@ -158,7 +153,8 @@ describe("", () => {
});
it("has a confirm delete button", async () => {
- setup(getKudometer(false));
+ renderComponent();
+
const deleteButton = screen.getByRole("button", { name: "delete" });
deleteButton.click();
@@ -170,7 +166,8 @@ describe("", () => {
});
it("calls the delete mutation", async () => {
- setup(getKudometer(false));
+ renderComponent();
+
const deleteButton = screen.getByRole("button", { name: "delete" });
deleteButton.click();
@@ -181,7 +178,8 @@ describe("", () => {
});
it("does not the delete mutation if confirm is cancelled", async () => {
- setup(getKudometer(false));
+ renderComponent();
+
(global.confirm as MockedFunction).mockReturnValueOnce(
true,
);
@@ -192,13 +190,15 @@ describe("", () => {
});
it("has a edit button", () => {
- setup(getKudometer(false));
+ renderComponent();
+
const editButton = screen.getByRole("button", { name: "edit" });
expect(editButton).toBeInTheDocument();
});
it("calls the edit function", () => {
- setup(getKudometer(false));
+ renderComponent();
+
const editButton = screen.getByRole("button", { name: "edit" });
editButton.click();
@@ -207,7 +207,8 @@ describe("", () => {
describe("make active button", () => {
it("is not disabled if the kudometer is not active", () => {
- setup(getKudometer(false));
+ renderComponent();
+
const activateButton = screen.getByRole("button", {
name: "Set as active",
});
@@ -215,7 +216,9 @@ describe("", () => {
});
it("is disabled if the kudometer is active", () => {
- setup(getKudometer(true));
+ updateProps({ kudometer: getKudometer(true) });
+ renderComponent();
+
const activateButton = screen.getByRole("button", {
name: "Already active",
});
@@ -223,7 +226,7 @@ describe("", () => {
});
it("calls the mutation", async () => {
- setup(getKudometer(false));
+ renderComponent();
const activateButton = screen.getByRole("button", {
name: "Set as active",
diff --git a/src/modules/manage-team/sections/kudometer/KudometerSection.spec.tsx b/src/modules/manage-team/sections/kudometer/KudometerSection.spec.tsx
index d1a93bcc..5d4b0200 100644
--- a/src/modules/manage-team/sections/kudometer/KudometerSection.spec.tsx
+++ b/src/modules/manage-team/sections/kudometer/KudometerSection.spec.tsx
@@ -1,17 +1,16 @@
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
import KudometerSection from "./KudometerSection";
import {
CREATE_KUDOMETER,
GET_KUDOMETERS,
UPDATE_KUDOMETER,
} from "./KudometerQueries";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
import {
- fireEvent,
- render,
- RenderResult,
- screen,
- waitFor,
-} from "@testing-library/react";
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
let createMutationCalled = false;
let editMutationCalled = false;
@@ -145,20 +144,20 @@ const mocksWithoutData = [
];
describe("", () => {
- let wrapper: RenderResult;
+ const { renderComponent, updateDecorator } = setTestSubject(
+ makeFC(KudometerSection),
+ { decorators: [dataDecorator(mocks)], props: {} },
+ );
beforeEach(() => {
mockLocalstorage("1");
createMutationCalled = false;
editMutationCalled = false;
- wrapper = render(withMockedProviders(, mocks));
- });
-
- afterEach(() => {
- wrapper.unmount();
});
it("shows a loading state", async () => {
+ renderComponent();
+
expect(screen.getByText("Loading...")).toBeInTheDocument();
await waitFor(() => {
expect(screen.queryByText("Loading...")).toBeNull();
@@ -166,16 +165,17 @@ describe("", () => {
});
it("shows when there are no kudometers", async () => {
- wrapper = render(
- withMockedProviders(, mocksWithoutData),
- );
+ updateDecorator("application", { mocks: mocksWithoutData });
+ renderComponent();
+
expect(
await screen.findByRole("cell", { name: "No kudometers available" }),
).toBeInTheDocument();
});
it("shows when there is an error", async () => {
- wrapper = render(withMockedProviders(, mocksWithError));
+ updateDecorator("application", { mocks: mocksWithError });
+ renderComponent();
expect(
await screen.findByText("Error! Something went wrong"),
@@ -183,12 +183,16 @@ describe("", () => {
});
it("shows a row for each kudometer", async () => {
+ renderComponent();
+
// 1 header row, 2 data rows
expect(await screen.findAllByRole("row")).toHaveLength(1 + 2);
});
describe("create kudometer", () => {
it("calls the create mutation", async () => {
+ renderComponent();
+
const inputField = screen.getByRole("textbox", { name: "Name" });
fireEvent.change(inputField, { target: { value: "Test kudometer" } });
@@ -203,6 +207,8 @@ describe("", () => {
});
it("does not call the mutation if the name is empty", async () => {
+ renderComponent();
+
const createButton = screen.getByRole("button", {
name: "Create kudometer",
});
@@ -216,6 +222,8 @@ describe("", () => {
describe("edit", () => {
it("calls the edit mutation", async () => {
+ renderComponent();
+
await waitFor(() => {
expect(screen.queryByText("Loading...")).toBeNull();
});
@@ -243,6 +251,8 @@ describe("", () => {
});
it("sets the selected kudometer", async () => {
+ renderComponent();
+
await waitFor(() => {
expect(screen.queryByText("Loading...")).toBeNull();
});
@@ -258,6 +268,8 @@ describe("", () => {
});
it("deselects the selected kudometer", async () => {
+ renderComponent();
+
await waitFor(() => {
expect(screen.queryByText("Loading...")).toBeNull();
});
diff --git a/src/modules/manage-team/sections/kudometer/goals/EditGoal.spec.tsx b/src/modules/manage-team/sections/kudometer/goals/EditGoal.spec.tsx
index cce9fe8b..bc2a6c86 100644
--- a/src/modules/manage-team/sections/kudometer/goals/EditGoal.spec.tsx
+++ b/src/modules/manage-team/sections/kudometer/goals/EditGoal.spec.tsx
@@ -1,17 +1,13 @@
-import {
- mockLocalstorage,
- withMockedProviders,
-} from "../../../../../spec_helper";
+import { mockLocalstorage } from "../../../../../spec_helper";
import { EditGoal } from "./EditGoal";
import { CREATE_GOAL, GET_KUDOMETERS, UPDATE_GOAL } from "../KudometerQueries";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
+import { createRef } from "react";
import {
- fireEvent,
- render,
- RenderResult,
- screen,
- waitFor,
-} from "@testing-library/react";
-import { RefObject, createRef } from "react";
+ makeFC,
+ setTestSubject,
+} from "../../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../../support/testing/testDecorators";
let createMutationCalled = false;
let updateMutationCalled = false;
@@ -107,25 +103,20 @@ const mocksWithErrors = [
];
describe("", () => {
- let component: RenderResult;
- let ref: RefObject;
+ const { renderComponent, updateProps, updateDecorator } = setTestSubject(
+ makeFC(EditGoal),
+ { decorators: [dataDecorator(mocks)], props: { kudometerId: "1" } },
+ );
beforeEach(() => {
mockLocalstorage("1");
createMutationCalled = false;
updateMutationCalled = false;
- ref = createRef();
-
- component = render(
- withMockedProviders(, mocks),
- );
- });
-
- afterEach(() => {
- component.unmount();
});
it("has a empty initial state", () => {
+ renderComponent();
+
const nameField = screen.getByRole("textbox", { name: "Name" });
expect(nameField).toHaveValue("");
@@ -135,6 +126,10 @@ describe("", () => {
describe("editing goal", () => {
beforeEach(() => {
+ const ref = createRef();
+ updateProps({ ref });
+ renderComponent();
+
ref.current?.setState({ editing: true, editGoalId: "2" });
});
@@ -176,6 +171,8 @@ describe("", () => {
describe("adding goal", () => {
it("Calls the create mutation if editing is false", async () => {
+ renderComponent();
+
const nameField = screen.getByRole("textbox", { name: "Name" });
fireEvent.change(nameField, { target: { value: "first goal" } });
@@ -192,10 +189,9 @@ describe("", () => {
});
it("shows when there is an error", async () => {
- component.unmount();
- component = render(
- withMockedProviders(, mocksWithErrors),
- );
+ updateDecorator("application", { mocks: mocksWithErrors });
+ renderComponent();
+
const nameField = screen.getByRole("textbox", { name: "Name" });
fireEvent.change(nameField, { target: { value: "first goal" } });
diff --git a/src/modules/manage-team/sections/kudometer/goals/GoalRow.spec.tsx b/src/modules/manage-team/sections/kudometer/goals/GoalRow.spec.tsx
index 4cd9e496..63d39249 100644
--- a/src/modules/manage-team/sections/kudometer/goals/GoalRow.spec.tsx
+++ b/src/modules/manage-team/sections/kudometer/goals/GoalRow.spec.tsx
@@ -1,11 +1,12 @@
-import {
- MockedFunction,
- mockLocalstorage,
- withMockedProviders,
-} from "../../../../../spec_helper";
+import { MockedFunction, mockLocalstorage } from "../../../../../spec_helper";
import { GoalRow } from "./GoalRow";
import { DELETE_GOAL, GET_KUDOMETERS, Goal } from "../KudometerQueries";
-import { render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
+import { setTestSubject } from "../../../../../support/testing/testSubject";
+import {
+ dataDecorator,
+ tableDecorator,
+} from "../../../../../support/testing/testDecorators";
let mutationCalled = false;
let queryCalled = false;
@@ -68,21 +69,22 @@ const goal: Goal = {
describe("", () => {
const editGoalMock = jest.fn(() => 1);
+ const { renderComponent } = setTestSubject(GoalRow, {
+ decorators: [tableDecorator, dataDecorator(mocks)],
+ props: {
+ key: goal.id,
+ goal,
+ editGoal: editGoalMock,
+ },
+ });
+
beforeEach(() => {
mockLocalstorage("1");
global.confirm = jest.fn(() => true);
mutationCalled = false;
queryCalled = false;
- render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
+
+ renderComponent();
});
it("renders all the information", () => {
diff --git a/src/modules/manage-team/sections/kudometer/goals/Goals.spec.tsx b/src/modules/manage-team/sections/kudometer/goals/Goals.spec.tsx
index 4a570742..e39d8337 100644
--- a/src/modules/manage-team/sections/kudometer/goals/Goals.spec.tsx
+++ b/src/modules/manage-team/sections/kudometer/goals/Goals.spec.tsx
@@ -1,7 +1,11 @@
-import { withMockedProviders } from "../../../../../spec_helper";
import { Goals } from "./Goals";
import { Goal, Kudometer } from "../KudometerQueries";
-import { render, screen } from "@testing-library/react";
+import { screen } from "@testing-library/react";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../../support/testing/testDecorators";
const goals: Goal[] = [
{
@@ -28,8 +32,13 @@ const kudometer: Kudometer = {
};
describe("", () => {
+ const { renderComponent } = setTestSubject(makeFC(Goals), {
+ decorators: [dataDecorator()],
+ props: { kudometer },
+ });
+
beforeEach(() => {
- render(withMockedProviders());
+ renderComponent();
});
it("renders the add goal section", () => {
diff --git a/src/modules/manage-team/sections/member/AlterRoleButton.spec.tsx b/src/modules/manage-team/sections/member/AlterRoleButton.spec.tsx
index db69a409..7e4b6922 100644
--- a/src/modules/manage-team/sections/member/AlterRoleButton.spec.tsx
+++ b/src/modules/manage-team/sections/member/AlterRoleButton.spec.tsx
@@ -1,7 +1,9 @@
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
+import { setTestSubject } from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
import { AlterRoleButton, AlterRoleButtonMode } from "./AlterRoleButton";
import { ALTER_ROLE } from "./Members";
-import { render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
const adminMembership = {
id: "1",
@@ -52,50 +54,62 @@ const mocks = [
const refetch = jest.fn();
-function setup(membership: any, mode: AlterRoleButtonMode) {
- return render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
-}
-
describe("", () => {
+ const { renderComponent, updateProps } = setTestSubject(AlterRoleButton, {
+ decorators: [dataDecorator(mocks)],
+ props: {
+ refetch,
+ membership: adminMembership,
+ mode: AlterRoleButtonMode.PROMOTE,
+ },
+ });
+
beforeEach(() => {
mockLocalstorage("1");
mutationCalled = false;
});
it("renders the promote button correctly", () => {
- setup(adminMembership, AlterRoleButtonMode.PROMOTE);
+ renderComponent();
const promoteButton = screen.getByRole("button", { name: "arrow_upward" });
expect(promoteButton).toBeInTheDocument();
});
it("renders the demote button correctly", () => {
- setup(adminMembership, AlterRoleButtonMode.DEMOTE);
+ updateProps({ mode: AlterRoleButtonMode.DEMOTE });
+ renderComponent();
+
const demoteButton = screen.getByRole("button", { name: "arrow_downward" });
expect(demoteButton).toBeInTheDocument();
});
it("disables the promote button when the user is an admin", () => {
- setup(adminMembership, AlterRoleButtonMode.PROMOTE);
+ renderComponent();
const promoteButton = screen.getByRole("button", { name: "arrow_upward" });
expect(promoteButton).toBeDisabled();
});
it("disables the demote button when the user is a member", () => {
- setup(normalMembership, AlterRoleButtonMode.DEMOTE);
+ updateProps({
+ membership: normalMembership,
+ mode: AlterRoleButtonMode.DEMOTE,
+ });
+ renderComponent();
+
const demoteButton = screen.getByRole("button", { name: "arrow_downward" });
expect(demoteButton).toBeDisabled();
});
it("calls the mutation", async () => {
- setup(normalMembership, AlterRoleButtonMode.PROMOTE);
+ updateProps({
+ membership: normalMembership,
+ mode: AlterRoleButtonMode.PROMOTE,
+ });
+ renderComponent();
+
const promoteButton = screen.getByRole("button", { name: "arrow_upward" });
promoteButton.click();
diff --git a/src/modules/manage-team/sections/member/MemberRow.spec.tsx b/src/modules/manage-team/sections/member/MemberRow.spec.tsx
index 27d9ec0b..516f9b71 100644
--- a/src/modules/manage-team/sections/member/MemberRow.spec.tsx
+++ b/src/modules/manage-team/sections/member/MemberRow.spec.tsx
@@ -1,11 +1,12 @@
+import { MockedFunction, mockLocalstorage } from "../../../../spec_helper";
+import { setTestSubject } from "../../../../support/testing/testSubject";
import {
- MockedFunction,
- mockLocalstorage,
- withMockedProviders,
-} from "../../../../spec_helper";
+ dataDecorator,
+ tableDecorator,
+} from "../../../../support/testing/testDecorators";
import { MemberRow } from "./MemberRow";
import { DEACTIVATE_USER } from "./Members";
-import { RenderResult, render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
const membership = {
id: "1",
@@ -38,31 +39,24 @@ const mocks = [
];
const refetch = jest.fn();
-let result: RenderResult | null = null;
-const setup = () => {
- if (result !== null) {
- result.unmount();
- }
-
- result = render(
- withMockedProviders(
- ,
- mocks,
- ),
- );
-};
describe("", () => {
+ const { renderComponent } = setTestSubject(MemberRow, {
+ decorators: [tableDecorator, dataDecorator(mocks)],
+ props: {
+ key: "1",
+ membership,
+ refetch,
+ },
+ });
+
mockLocalstorage("5");
beforeEach(() => {
mutationCalled = false;
global.confirm = jest.fn(() => true);
- setup();
+
+ renderComponent();
});
it("renders the membership information", () => {
@@ -98,7 +92,7 @@ describe("", () => {
it("renders the buttons if the membership is not the current user", () => {
mockLocalstorage("5");
- setup();
+ renderComponent();
const buttons = screen.queryAllByRole("button");
expect(buttons).toHaveLength(3);
@@ -106,7 +100,7 @@ describe("", () => {
it("does not render the buttons if the membership is the current user", () => {
mockLocalstorage("1");
- setup();
+ renderComponent();
const buttons = screen.queryAllByRole("button");
expect(buttons).toHaveLength(0);
diff --git a/src/modules/manage-team/sections/member/Members.spec.tsx b/src/modules/manage-team/sections/member/Members.spec.tsx
index 46d16a27..b230f8ea 100644
--- a/src/modules/manage-team/sections/member/Members.spec.tsx
+++ b/src/modules/manage-team/sections/member/Members.spec.tsx
@@ -1,6 +1,11 @@
-import { mockLocalstorage, withMockedProviders } from "../../../../spec_helper";
+import { mockLocalstorage } from "../../../../spec_helper";
+import {
+ makeFC,
+ setTestSubject,
+} from "../../../../support/testing/testSubject";
+import { dataDecorator } from "../../../../support/testing/testDecorators";
import MemberSection, { GET_USERS } from "./Members";
-import { RenderResult, render, screen, waitFor } from "@testing-library/react";
+import { screen, waitFor } from "@testing-library/react";
export const mocks = () => [
{
@@ -47,35 +52,19 @@ const mocksWithError = [
},
];
-type GraphQLData = {
- request: {
- query: unknown;
- variables?: unknown;
- };
- error?: unknown;
- result?: {
- data: unknown;
- };
-};
-
-let renderResult: RenderResult | null = null;
-const setup = async (mockData: GraphQLData[] = mocks()) => {
- if (renderResult) {
- await waitFor(() => {
- expect(screen.queryByText("Loading...")).toBeNull();
- });
- renderResult.unmount();
- }
- renderResult = render(withMockedProviders(, mockData));
-};
-
describe("", () => {
- beforeEach(async () => {
+ const { renderComponent, updateDecorator } = setTestSubject(
+ makeFC(MemberSection),
+ { decorators: [dataDecorator(mocks())], props: {} },
+ );
+
+ beforeEach(() => {
mockLocalstorage("1");
- await setup();
});
it("shows a loading state", async () => {
+ renderComponent();
+
expect(screen.getByText("Loading...")).toBeInTheDocument();
await waitFor(() => {
@@ -84,7 +73,9 @@ describe("", () => {
});
it("shows when there is an error", async () => {
- await setup(mocksWithError);
+ updateDecorator("application", { mocks: mocksWithError });
+ renderComponent();
+
await waitFor(() => {
expect(screen.queryByText("Loading...")).toBeNull();
});
@@ -95,6 +86,8 @@ describe("", () => {
});
it("renders a row for each membership", async () => {
+ renderComponent();
+
// 1 header row, 2 data rows
expect(await screen.findAllByRole("row")).toHaveLength(3);
});
diff --git a/src/modules/settings/InvitePage.spec.tsx b/src/modules/settings/InvitePage.spec.tsx
index b15f40ac..b622efd7 100644
--- a/src/modules/settings/InvitePage.spec.tsx
+++ b/src/modules/settings/InvitePage.spec.tsx
@@ -1,13 +1,17 @@
-import { withMockedProviders } from "../../spec_helper";
+import { setTestSubject } from "../../support/testing/testSubject";
+import { dataDecorator } from "../../support/testing/testDecorators";
import { InvitePage } from "./InvitePage";
-import { render, screen } from "@testing-library/react";
+import { screen } from "@testing-library/react";
describe("", () => {
- beforeEach(() => {
- render(withMockedProviders());
+ const { renderComponent } = setTestSubject(InvitePage, {
+ decorators: [dataDecorator()],
+ props: {},
});
it("renders without crashing", async () => {
+ renderComponent();
+
expect(
await screen.findByRole("button", { name: "Invite" }),
).toBeInTheDocument();
diff --git a/src/modules/settings/SettingsPage.spec.tsx b/src/modules/settings/SettingsPage.spec.tsx
index 743dd223..ed6fec93 100644
--- a/src/modules/settings/SettingsPage.spec.tsx
+++ b/src/modules/settings/SettingsPage.spec.tsx
@@ -1,15 +1,21 @@
-import { mockLocalstorage, withMockedProviders } from "../../spec_helper";
+import { mockLocalstorage } from "../../spec_helper";
+import { setTestSubject } from "../../support/testing/testSubject";
+import {
+ dataDecorator,
+ routingDecorator,
+} from "../../support/testing/testDecorators";
import { SettingsPage } from "./index";
-import { render, screen } from "@testing-library/react";
-
-const setup = () => {
- render(withMockedProviders());
-};
+import { screen } from "@testing-library/react";
describe("", () => {
+ const { renderComponent } = setTestSubject(SettingsPage, {
+ decorators: [dataDecorator(), routingDecorator()],
+ props: {},
+ });
+
it("shows the invite button if the user is an admin", () => {
mockLocalstorage("admin");
- setup();
+ renderComponent();
const inviteButton = screen.queryByRole("button", {
name: "Invite",
@@ -19,7 +25,7 @@ describe("", () => {
it("hides the invite button if the user is a member", () => {
mockLocalstorage("member");
- setup();
+ renderComponent();
const inviteButton = screen.queryByRole("button", {
name: "Invite",
diff --git a/src/modules/statistics/Statistics.spec.tsx b/src/modules/statistics/Statistics.spec.tsx
index af2af581..2694270a 100644
--- a/src/modules/statistics/Statistics.spec.tsx
+++ b/src/modules/statistics/Statistics.spec.tsx
@@ -1,6 +1,8 @@
-import { mockLocalstorage, withMockedProviders } from "../../spec_helper";
+import { mockLocalstorage } from "../../spec_helper";
+import { setTestSubject } from "../../support/testing/testSubject";
+import { dataDecorator } from "../../support/testing/testDecorators";
import Statistics, { GET_GOAL_PERCENTAGE } from "./Statistics";
-import { render, screen, waitFor, within } from "@testing-library/react";
+import { screen, waitFor, within } from "@testing-library/react";
export const mocks = (teamId: string) => [
{
@@ -37,9 +39,15 @@ export const mocks = (teamId: string) => [
];
describe("", () => {
+ const { renderComponent } = setTestSubject(Statistics, {
+ decorators: [dataDecorator(mocks("1"))],
+ props: {},
+ });
+
beforeEach(() => {
mockLocalstorage("1");
- render(withMockedProviders(, mocks("1")));
+
+ renderComponent();
});
it("shows a loading state", async () => {
diff --git a/src/modules/user/ResetPasswordPage.spec.tsx b/src/modules/user/ResetPasswordPage.spec.tsx
index b5efc5e8..8b373dc9 100644
--- a/src/modules/user/ResetPasswordPage.spec.tsx
+++ b/src/modules/user/ResetPasswordPage.spec.tsx
@@ -1,7 +1,11 @@
-import { withMockedProviders } from "../../spec_helper";
+import { makeFC, setTestSubject } from "../../support/testing/testSubject";
+import {
+ dataDecorator,
+ routingDecorator,
+} from "../../support/testing/testDecorators";
import { ResetPasswordPage } from "./index";
import { MUTATION_RESET_PASSWORD } from "./ResetPasswordPage";
-import { fireEvent, render, screen, waitFor } from "@testing-library/react";
+import { fireEvent, screen, waitFor } from "@testing-library/react";
let mutationCalled = false;
const mocks = [
@@ -22,9 +26,15 @@ const mocks = [
];
describe("", () => {
+ const { renderComponent } = setTestSubject(makeFC(ResetPasswordPage), {
+ decorators: [dataDecorator(mocks), routingDecorator()],
+ props: {},
+ });
+
beforeEach(() => {
mutationCalled = false;
- render(withMockedProviders(, mocks));
+
+ renderComponent();
});
it("has three input elements", () => {
diff --git a/src/modules/user/UserPage.spec.tsx b/src/modules/user/UserPage.spec.tsx
index 6ac8815a..85e6207e 100644
--- a/src/modules/user/UserPage.spec.tsx
+++ b/src/modules/user/UserPage.spec.tsx
@@ -1,14 +1,10 @@
import { createMemoryHistory, MemoryHistory } from "history";
import { DISCONNECT_SLACK, GET_USER, UserPage } from "./UserPage";
-import { mockLocalstorage, withMockedProviders } from "../../spec_helper";
+import { createRouterProps, mockLocalstorage } from "../../spec_helper";
import { PATH_RESET_PASSWORD } from "../../routes";
-import {
- render,
- RenderResult,
- screen,
- waitFor,
- within,
-} from "@testing-library/react";
+import { screen, waitFor, within } from "@testing-library/react";
+import { makeFC, setTestSubject } from "../../support/testing/testSubject";
+import { dataDecorator } from "../../support/testing/testDecorators";
let mutationCalled = false;
export const mocks = ({ slackId = "" } = { slackId: "" }) => [
@@ -65,29 +61,21 @@ const mocksWithSlackId = [
},
];
-let history: MemoryHistory;
-let renderResult: RenderResult | null = null;
-const setup = async (mock: any) => {
- if (renderResult) {
- await waitFor(() => {
- expect(screen.queryByText("Loading...")).toBeNull();
- });
-
- renderResult.unmount();
- }
-
- history = createMemoryHistory();
- mutationCalled = false;
- mockLocalstorage("1");
-
- renderResult = render(
- withMockedProviders(, mock),
+describe("", () => {
+ const { renderComponent, setProps, updateDecorator } = setTestSubject(
+ makeFC(UserPage),
+ { decorators: [dataDecorator(mocks())] },
);
-};
+ let history: MemoryHistory;
-describe("", () => {
const original = window;
- beforeEach(async () => {
+ beforeEach(() => {
+ history = createMemoryHistory();
+ setProps({
+ ...createRouterProps(),
+ history,
+ });
+
window = Object.create(window);
const url = "http://dummy.com";
Object.defineProperty(window, "location", {
@@ -97,7 +85,8 @@ describe("", () => {
writable: true, // possibility to override
});
- await setup(mocks());
+ mutationCalled = false;
+ mockLocalstorage("1");
});
afterEach(() => {
@@ -105,6 +94,8 @@ describe("", () => {
});
it("shows the component is loading", async () => {
+ renderComponent();
+
const loading = screen.getByText("Loading...");
expect(loading).toBeInTheDocument();
@@ -114,22 +105,29 @@ describe("", () => {
});
it("shows the users name", async () => {
+ renderComponent();
+
const name = await screen.findByRole("heading", { level: 2, name: "Max" });
expect(name).toBeInTheDocument();
});
it("shows the users avatar", async () => {
- const image = (await screen.findAllByRole("img"))[0];
+ renderComponent();
+ const image = (await screen.findAllByRole("img"))[0];
expect(image.getAttribute("src")).toEqual("fakeAvatarUrl");
});
it("shows a link to gravatar", async () => {
+ renderComponent();
+
const link = await screen.findByRole("link", { name: "gravatar.com" });
expect(link.getAttribute("href")).toEqual("https://nl.gravatar.com/");
});
it("shows a link to the reset password page", async () => {
+ renderComponent();
+
const resetPasswordButton = await screen.findByRole("button", {
name: "Change password",
});
@@ -137,6 +135,8 @@ describe("", () => {
});
it("shows a logout button", async () => {
+ renderComponent();
+
const resetPasswordButton = await screen.findByRole("button", {
name: "Log out",
});
@@ -144,6 +144,8 @@ describe("", () => {
});
it("navigates to the reset password page", async () => {
+ renderComponent();
+
const resetPasswordButton = await screen.findByRole("button", {
name: "Change password",
});
@@ -155,8 +157,8 @@ describe("", () => {
});
describe("not connected to slack", () => {
- beforeEach(async () => {
- await setup(mocks());
+ beforeEach(() => {
+ renderComponent();
});
it("shows the connect to slack part if the slack id is null", async () => {
@@ -182,8 +184,9 @@ describe("", () => {
});
describe("connected to slack", () => {
- beforeEach(async () => {
- await setup(mocksWithSlackId);
+ beforeEach(() => {
+ updateDecorator("application", { mocks: mocksWithSlackId });
+ renderComponent();
});
it("shows the user is connected to slack if the slack id is not null", async () => {
diff --git a/src/modules/user/UserPage.tsx b/src/modules/user/UserPage.tsx
index bccd53f7..cdae6547 100644
--- a/src/modules/user/UserPage.tsx
+++ b/src/modules/user/UserPage.tsx
@@ -1,8 +1,7 @@
import { Component } from "react";
import { Query } from "@apollo/client/react/components";
import { gql } from "@apollo/client";
-import { withRouter } from "react-router-dom";
-import { History } from "history";
+import { RouteComponentProps } from "react-router-dom";
import { toast } from "react-toastify";
import { Auth } from "../../support";
@@ -59,22 +58,18 @@ export interface GetUserResult {
};
}
-export interface Props {
- history: History;
-}
-
export interface State {
// Future state vars go here
}
-export class UserPage extends Component {
+export class UserPage extends Component {
slackConnectUrl = `${settings.API_BASE_URL}/auth/slack/user/${Storage.getItem(
settings.USER_ID_TOKEN,
)}`;
slackIconPath = `${process.env.PUBLIC_URL}/assets/slack_logo.png`;
- constructor(props: Props) {
+ constructor(props: RouteComponentProps) {
super(props);
const parsed = queryString.parse(this.props.history.location.search);
@@ -146,5 +141,4 @@ export class UserPage extends Component {
}
}
-// @ts-ignore
-export default withRouter(UserPage);
+export default UserPage;
diff --git a/src/spec_helper.tsx b/src/spec_helper.tsx
index 9ea0016e..ac162b99 100644
--- a/src/spec_helper.tsx
+++ b/src/spec_helper.tsx
@@ -1,22 +1,6 @@
-import { MockedProvider } from "@apollo/client/testing";
-import { MemoryRouter, Route } from "react-router-dom";
-import { ApolloCache, InMemoryCache } from "@apollo/client/cache";
-import { PATH_CHOOSE_TEAM, PATH_LOGIN } from "./routes";
-
-export const withMockedProviders = (
- component: any,
- mocks?: any,
- cache?: ApolloCache,
- useTypeName: boolean = true,
-) => (
-
-
- {component}
-
- Login Page
- Choose team Page
-
-);
+import { InMemoryCache } from "@apollo/client/cache";
+import { createMemoryHistory } from "history";
+import { RouteComponentProps } from "react-router-dom";
export const wait = (amount = 0) =>
new Promise((resolve) => setTimeout(resolve, amount));
@@ -31,6 +15,22 @@ export type MockedFunction any> = jest.Mock<
Parameters
>;
+export const createRouterProps = (): RouteComponentProps => ({
+ location: {
+ search: "",
+ pathname: "",
+ state: "",
+ hash: "",
+ },
+ history: createMemoryHistory(),
+ match: {
+ params: "",
+ isExact: false,
+ path: "",
+ url: "",
+ },
+});
+
export const getMockCache = () =>
new InMemoryCache({
typePolicies: {
diff --git a/src/support/testing/testDecorators.tsx b/src/support/testing/testDecorators.tsx
new file mode 100644
index 00000000..9f0555b7
--- /dev/null
+++ b/src/support/testing/testDecorators.tsx
@@ -0,0 +1,67 @@
+import { Decorator } from "./testSubject";
+import { MockedProvider } from "@apollo/client/testing";
+import { MemoryRouter, Route } from "react-router-dom";
+import { ApolloCache } from "@apollo/client/cache";
+import { Context as ResponsiveContext } from "react-responsive";
+
+export const responsiveDecorator: Decorator<"responsive", { width: number }> = {
+ name: "responsive",
+ settings: { width: 1200 },
+ Decorator: ({ Component, settings }) => (
+
+
+
+ ),
+};
+
+export const dataDecorator = (
+ mocks?: any,
+ cache?: ApolloCache,
+): Decorator<
+ "application",
+ { useTypeName: boolean; mocks?: any; cache?: ApolloCache }
+> => ({
+ name: "application",
+ settings: { useTypeName: true, mocks, cache },
+ Decorator: ({ Component, settings }) => (
+
+
+
+ ),
+});
+
+export const routingDecorator = (): Decorator<
+ "routing",
+ { paths: Record }
+> => ({
+ name: "routing",
+ settings: {
+ paths: {},
+ },
+ Decorator: ({ Component, settings }) => (
+
+
+ {Object.entries(settings.paths).map(([path, content]) => (
+
+ {content}
+
+ ))}
+
+ ),
+});
+
+export const tableDecorator: Decorator<"table"> = {
+ name: "table",
+ settings: {},
+ Decorator: ({ Component }) => (
+
+ ),
+};
diff --git a/src/support/testing/testSubject.tsx b/src/support/testing/testSubject.tsx
new file mode 100644
index 00000000..c7c247ff
--- /dev/null
+++ b/src/support/testing/testSubject.tsx
@@ -0,0 +1,205 @@
+import { RenderResult, render } from "@testing-library/react";
+import { forwardRef } from "react";
+
+type DecoratorSettings<
+ TDecorators extends Decorator,
+ TKey extends string,
+> = TDecorators extends Decorator ? TSettings : never;
+
+type UpdatedSettings = Partial | ((initialSettings: T) => Partial);
+
+type TestHelpers<
+ TComponent extends React.FC,
+ TDecorators extends Decorator[],
+> = {
+ /**
+ * Set the initial properties of the component
+ *
+ * You can also set the props through the settings in `setComponent`
+ */
+ setProps(props: React.ComponentProps): void;
+ /**
+ * Update the properties of the component.
+ * After a `renderComponent` call these settings get reset.
+ */
+ updateProps(
+ newProps: UpdatedSettings>,
+ ): void;
+ /**
+ * Update the settings of a decorator.
+ * After a `renderComponent` call these settings get reset.
+ */
+ updateDecorator(
+ key: TKey,
+ settings: UpdatedSettings>,
+ ): void;
+ /**
+ * Render the component wrapped with all decorators, applying
+ * all property and decorator setting updates.
+ */
+ renderComponent(): RenderResult;
+};
+
+export type Decorator<
+ TName extends string,
+ TSettings extends Record = Record,
+> = {
+ /**
+ * Name of the decorator, can be used in `updateDecorator` to update the settings
+ */
+ name: TName;
+ /**
+ * Initial settings of this decorator, van be updated through `updateDecorator`
+ */
+ settings: TSettings;
+ /**
+ * Function to decorate incoming `Component`. This can be part of a larger chain.
+ *
+ * @param Component The component to decorate
+ * @param settings settings to apply on the decoration
+ * @returns an updated JSX structure
+ */
+ Decorator: React.FC<{ Component: React.FC; settings: TSettings }>;
+};
+
+const hasAlreadyRendered = (
+ lastRender: RenderResult | null,
+): lastRender is RenderResult =>
+ lastRender !== null && // Rendered before
+ document.body.firstChild !== null &&
+ // And still in the document?
+ document.body.firstChild === lastRender.baseElement.firstChild;
+
+/**
+ * Set the component subject of this test.
+ *
+ * This component should be a FunctionalComponent. If you want
+ * to test a ClassComponent, you can wrap your component with `makeFC`
+ *
+ * @example ```
+ * const { renderComponent } = setComponent(YourComponent)
+ * ```
+ *
+ * You can decorate your component with contexts by setting decorators:
+ *
+ * @example ```
+ * const { renderComponent } = setComponent(YourComponent, {
+ * decorators: [dataDecorator, themeDecorator]
+ * })
+ * ```
+ *
+ * @param Component The react component under test
+ * @param settings
+ * @returns
+ */
+export const setTestSubject = <
+ TComponent extends React.FC,
+ TDecorators extends Decorator[],
+>(
+ Component: TComponent,
+ settings: {
+ decorators?: TDecorators;
+ props?: React.ComponentProps;
+ } = {},
+): TestHelpers => {
+ let props: React.ComponentProps | null = null;
+ let initialProps: React.ComponentProps | null =
+ settings.props ?? null;
+
+ const initializeDecoratorSettings = (): Record<
+ string,
+ Record
+ > =>
+ (settings.decorators ?? []).reduce(
+ (result, decorator) => ({
+ ...result,
+ [decorator.name]: decorator.settings,
+ }),
+ {},
+ );
+
+ let decoratorSettings: Record<
+ string,
+ Record
+ > = initializeDecoratorSettings();
+ let lastRender: RenderResult | null = null;
+
+ return {
+ renderComponent: () => {
+ if (initialProps === null) {
+ throw new Error("No props specified with setProps");
+ }
+
+ const jsxStructure = (settings.decorators ?? []).reduce(
+ (result, dec) => (
+ result}
+ settings={decoratorSettings[dec.name]}
+ />
+ ),
+ ,
+ );
+
+ if (hasAlreadyRendered(lastRender)) {
+ lastRender.rerender(jsxStructure);
+ } else {
+ const result = render(jsxStructure);
+ lastRender = result;
+ }
+
+ props = null;
+ decoratorSettings = initializeDecoratorSettings();
+
+ return lastRender;
+ },
+ setProps: (props) => {
+ initialProps = props;
+ },
+ updateProps: (updatedProps) => {
+ if (initialProps === null) {
+ throw new Error("No props specified with setProps");
+ }
+ const update: Partial> =
+ typeof updatedProps === "function"
+ ? updatedProps(props ? props : initialProps)
+ : updatedProps;
+
+ props = { ...initialProps, ...props, ...update };
+ },
+ updateDecorator: (name, updatedSettings) => {
+ const update: Record =
+ typeof updatedSettings === "function"
+ ? updatedSettings(
+ decoratorSettings[name] as DecoratorSettings<
+ TDecorators[number],
+ typeof name
+ >,
+ )
+ : updatedSettings;
+
+ decoratorSettings[name] = {
+ ...decoratorSettings[name],
+ ...update,
+ };
+ },
+ };
+};
+
+/**
+ * Convert a ClassComponent into a FunctionalComponent.
+ * The ref that can be supplied will be a ref to the instance of the
+ * ClassComponent.
+ */
+export const makeFC = (
+ Component: React.ComponentClass,
+): React.ForwardRefExoticComponent<
+ React.PropsWithoutRef &
+ React.RefAttributes>>
+> => {
+ const fc = forwardRef<
+ InstanceType>,
+ TComponentProps
+ >((props, ref) => );
+ fc.displayName = `Wrapped${Component.displayName ?? Component.name}`;
+ return fc;
+};
diff --git a/src/ui/Card/Card.spec.tsx b/src/ui/Card/Card.spec.tsx
index a8744f45..60c73277 100644
--- a/src/ui/Card/Card.spec.tsx
+++ b/src/ui/Card/Card.spec.tsx
@@ -1,33 +1,27 @@
-import { render } from "@testing-library/react";
+import { screen } from "@testing-library/react";
import { Card } from ".";
+import { setTestSubject } from "../../support/testing/testSubject";
-test("given an icon name, renders an icon", () => {
- const { getByText } = render(
- ,
- );
+describe("Card", () => {
+ const { renderComponent, updateProps } = setTestSubject(Card, {
+ props: {
+ title: { text: "Kudometer" },
+ content: "content",
+ },
+ });
- getByText("Kudometer");
- getByText("flag");
-});
+ test("given an icon name, renders an icon", () => {
+ updateProps({ title: { text: "Kudometer", iconName: "flag" } });
+ renderComponent();
+
+ screen.getByText("Kudometer");
+ screen.getByText("flag");
+ });
-test("render a default card with mandatory settings", () => {
- const { getByText } = render(
- ,
- );
+ test("render a default card with mandatory settings", () => {
+ renderComponent();
- getByText("Kudometer");
- getByText("content");
+ screen.getByText("Kudometer");
+ screen.getByText("content");
+ });
});
diff --git a/src/ui/Dropdown/Dropdown.spec.tsx b/src/ui/Dropdown/Dropdown.spec.tsx
index fb595725..d59aa132 100644
--- a/src/ui/Dropdown/Dropdown.spec.tsx
+++ b/src/ui/Dropdown/Dropdown.spec.tsx
@@ -1,34 +1,47 @@
-import { render, fireEvent } from "@testing-library/react";
+import { screen, fireEvent } from "@testing-library/react";
import { Dropdown, DropdownMenuItem } from ".";
+import { Decorator, setTestSubject } from "../../support/testing/testSubject";
+
+const dropdownDecorator: Decorator<"dropdown"> = {
+ name: "dropdown",
+ settings: {},
+ Decorator: ({ Component }) => (
+
+
+
+ ),
+};
describe("Dropdown Component", () => {
- it("should display the dropdown menu when clicked", () => {
- const { queryByText, getByRole } = render(
-
-
- ,
- );
+ const { renderComponent, updateProps } = setTestSubject(DropdownMenuItem, {
+ decorators: [dropdownDecorator],
+ props: {
+ label: "Item 1",
+ },
+ });
- expect(queryByText("Item 1")).toBeNull();
+ it("should display the dropdown menu when clicked", () => {
+ renderComponent();
- const dropdownButton = getByRole("button", { name: "Dropdown Label" });
+ expect(screen.queryByText("Item 1")).toBeNull();
+ const dropdownButton = screen.getByRole("button", {
+ name: "Dropdown Label",
+ });
fireEvent.click(dropdownButton);
- expect(getByRole("menuitem", { name: "Item 1" })).toBeInTheDocument();
+ expect(
+ screen.getByRole("menuitem", { name: "Item 1" }),
+ ).toBeInTheDocument();
});
it("should render an icon when passed", () => {
- const iconName = "man";
+ updateProps({ iconName: "man" });
+ renderComponent();
- const { getByText, getByRole } = render(
-
-
- ,
- );
-
- const dropdownButton = getByRole("button", { name: "Dropdown Label" });
+ const dropdownButton = screen.getByRole("button", {
+ name: "Dropdown Label",
+ });
fireEvent.click(dropdownButton);
-
- expect(getByText(iconName)).toBeInTheDocument();
+ expect(screen.getByText("man")).toBeInTheDocument();
});
});
diff --git a/src/ui/Dropzone/index.spec.tsx b/src/ui/Dropzone/index.spec.tsx
index da84c9d3..25fbf5f0 100644
--- a/src/ui/Dropzone/index.spec.tsx
+++ b/src/ui/Dropzone/index.spec.tsx
@@ -1,19 +1,16 @@
-import { render } from "@testing-library/react";
-
+import { screen } from "@testing-library/react";
+import { setTestSubject } from "../../support/testing/testSubject";
import Dropzone from ".";
describe("", () => {
- const props = {
- label: 'Drop it!'
- }
-
- test('renders an img with provided alt text', () => {
- const { queryByText } = render(
-
- );
+ const { renderComponent } = setTestSubject(Dropzone, {
+ props: { label: "Drop it!" },
+ });
- const label = queryByText(props.label);
+ test("renders an img with provided alt text", () => {
+ renderComponent();
- expect(label).toBeInTheDocument();
- });
+ const label = screen.queryByText("Drop it!");
+ expect(label).toBeInTheDocument();
+ });
});
diff --git a/src/ui/InputField/InputField.spec.tsx b/src/ui/InputField/InputField.spec.tsx
index ecc21394..ed6e12a1 100644
--- a/src/ui/InputField/InputField.spec.tsx
+++ b/src/ui/InputField/InputField.spec.tsx
@@ -1,35 +1,34 @@
-import { render, screen } from "@testing-library/react";
+import { screen } from "@testing-library/react";
import InputField from ".";
+import { setTestSubject } from "../../support/testing/testSubject";
-test("given an element type input (by default), it renders a input field", () => {
- render(
- ,
- );
+describe("InputField", () => {
+ const { renderComponent, updateProps } = setTestSubject(InputField, {
+ props: {
+ id: "input",
+ label: "Enter some text",
+ type: "text",
+ placeholder: "Placeholder",
+ },
+ });
- const inputElement = screen.getByLabelText("Enter some text");
- expect(inputElement).toHaveAttribute("id", "input");
- expect(inputElement).toHaveAttribute("type", "text");
- expect(inputElement).toHaveAttribute("placeholder", "Placeholder");
- expect(inputElement.tagName).toBe("INPUT");
-});
+ test("given an element type input (by default), it renders a input field", () => {
+ renderComponent();
+
+ const inputElement = screen.getByLabelText("Enter some text");
+ expect(inputElement).toHaveAttribute("id", "input");
+ expect(inputElement).toHaveAttribute("type", "text");
+ expect(inputElement).toHaveAttribute("placeholder", "Placeholder");
+ expect(inputElement.tagName).toBe("INPUT");
+ });
-test("given an element type textarea, it renders a textarea field", () => {
- render(
- ,
- );
+ test("given an element type textarea, it renders a textarea field", () => {
+ updateProps({ id: "textfield-1", elementType: "textarea" });
+ renderComponent();
- const inputElement = screen.getByLabelText("Enter some text");
- expect(inputElement).toHaveAttribute("id", "textfield-1");
- expect(inputElement).toHaveAttribute("placeholder", "Placeholder");
- expect(inputElement.tagName).toBe("TEXTAREA");
+ const inputElement = screen.getByLabelText("Enter some text");
+ expect(inputElement).toHaveAttribute("id", "textfield-1");
+ expect(inputElement).toHaveAttribute("placeholder", "Placeholder");
+ expect(inputElement.tagName).toBe("TEXTAREA");
+ });
});
diff --git a/src/ui/Progress/GoalProgressIndicator.spec.tsx b/src/ui/Progress/GoalProgressIndicator.spec.tsx
index 15d75dc6..1cfc4e27 100644
--- a/src/ui/Progress/GoalProgressIndicator.spec.tsx
+++ b/src/ui/Progress/GoalProgressIndicator.spec.tsx
@@ -1,64 +1,58 @@
-import { render } from "@testing-library/react";
+import { screen } from "@testing-library/react";
import GoalProgressIndicator from "./GoalProgressIndicator";
import { createGoal } from "./factory";
+import { setTestSubject } from "../../support/testing/testSubject";
-test("renders the goal progress indicator", () => {
- const goals = {
- activeGoals: [
- createGoal("Third goal", 1500, null),
- createGoal("Second goal", 1000, null),
- createGoal("First goal", 500, null),
- ],
- };
- const { getAllByRole } = render(
- ,
+describe("GoalProgressIndicator", () => {
+ const { renderComponent, updateProps } = setTestSubject(
+ GoalProgressIndicator,
+ {
+ props: {
+ goals: [
+ createGoal("Third goal", 1500, null),
+ createGoal("Second goal", 1000, null),
+ createGoal("First goal", 500, null),
+ ],
+ activeKudosMeter: { amount: 200 },
+ },
+ },
);
- const progressBars = getAllByRole("progressbar");
- expect(progressBars).toHaveLength(3);
-});
+ it("renders the goal progress indicator", () => {
+ renderComponent();
-test("renders the goal progress indicator with no goals achieved, but with progress", () => {
- const goals = {
- activeGoals: [
- createGoal("Third goal", 1500, null),
- createGoal("Second goal", 1000, null),
- createGoal("First goal", 500, null),
- ],
- };
+ const progressBars = screen.getAllByRole("progressbar");
+ expect(progressBars).toHaveLength(3);
+ });
- const { getAllByRole } = render(
- ,
- );
+ it("renders the goal progress indicator with no goals achieved, but with progress", () => {
+ renderComponent();
- const progressBars = getAllByRole("progressbar");
- expect(progressBars).toHaveLength(3);
- expect(progressBars[progressBars.length - 1]).toHaveAttribute("value", "40");
-});
+ const progressBars = screen.getAllByRole("progressbar");
+ expect(progressBars).toHaveLength(3);
+ expect(progressBars[progressBars.length - 1]).toHaveAttribute(
+ "value",
+ "40",
+ );
+ });
-test("renders the goal progress indicator with the first goal achieved", () => {
- const goals = {
- activeGoals: [
- createGoal("Third goal", 1500, null),
- createGoal("Second goal", 1000, null),
- createGoal("First goal", 500, "2023-05-13"),
- ],
- };
- const { getAllByRole } = render(
- ,
- );
+ it("renders the goal progress indicator with the first goal achieved", () => {
+ updateProps({
+ goals: [
+ createGoal("Third goal", 1500, null),
+ createGoal("Second goal", 1000, null),
+ createGoal("First goal", 500, "2023-05-13"),
+ ],
+ activeKudosMeter: { amount: 600 },
+ });
+ renderComponent();
- const progressBars = getAllByRole("progressbar");
- expect(progressBars).toHaveLength(3);
- expect(progressBars[progressBars.length - 1]).toHaveAttribute("value", "100");
- expect(progressBars[1]).toHaveAttribute("value", "20");
+ const progressBars = screen.getAllByRole("progressbar");
+ expect(progressBars).toHaveLength(3);
+ expect(progressBars[progressBars.length - 1]).toHaveAttribute(
+ "value",
+ "100",
+ );
+ expect(progressBars[1]).toHaveAttribute("value", "20");
+ });
});