Skip to content

Commit

Permalink
test: Add React Query Wrapper around Components
Browse files Browse the repository at this point in the history
  • Loading branch information
anshg1214 committed Sep 21, 2024
1 parent 15dad1f commit 763a273
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 56 deletions.
101 changes: 62 additions & 39 deletions frontend/js/tests/pins/PinnedRecordingCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,21 @@ import GlobalAppContext, {
import { waitForComponentToPaint } from "../test-utils";
import RecordingFeedbackManager from "../../src/utils/RecordingFeedbackManager";
import ListenCard from "../../src/common/listens/ListenCard";
import { ReactQueryWrapper } from "../test-react-query";

// Font Awesome generates a random hash ID for each icon everytime.
// Mocking Math.random() fixes this
// https://github.com/FortAwesome/react-fontawesome/issues/194#issuecomment-627235075
jest.spyOn(global.Math, "random").mockImplementation(() => 0);

function PinnedRecordingCardWithWrapper(props: PinnedRecordingCardProps) {
return (
<ReactQueryWrapper>
<PinnedRecordingCard {...props} />
</ReactQueryWrapper>
);
}

const user = {
id: 1,
name: "name",
Expand Down Expand Up @@ -64,18 +73,17 @@ const props: PinnedRecordingCardProps = {

describe("PinnedRecordingCard", () => {
it("renders correctly", () => {
const wrapper = mount<PinnedRecordingCard>(
<PinnedRecordingCard {...props} />
);
const wrapper = mount(<PinnedRecordingCardWithWrapper {...props} />);
expect(wrapper.find(ListenCard)).toHaveLength(1);
});

describe("determineIfCurrentlyPinned", () => {
it("returns true when pinned_until > now", async () => {
const wrapper = mount<PinnedRecordingCard>(
<PinnedRecordingCard {...props} />
const componentWrapper = mount(
<PinnedRecordingCardWithWrapper {...props} />
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;

let isPlaying;
await act(() => {
Expand All @@ -85,12 +93,13 @@ describe("PinnedRecordingCard", () => {
});

it("returns false when pinned_until < now", async () => {
const wrapper = mount<PinnedRecordingCard>(
<PinnedRecordingCard
const componentWrapper = mount(
<PinnedRecordingCardWithWrapper
{...{ ...props, pinnedRecording: expiredPinnedRecording }}
/>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;
let isPlaying;
await act(() => {
isPlaying = instance.determineIfCurrentlyPinned();
Expand All @@ -101,12 +110,13 @@ describe("PinnedRecordingCard", () => {

describe("unpinRecording", () => {
it("calls API, updates currentlyPinned in state", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider value={globalProps}>
<PinnedRecordingCard {...props} />
<PinnedRecordingCardWithWrapper {...props} />
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;

const { APIService } = instance.context;
const spy = jest.spyOn(APIService, "unpinRecording");
Expand All @@ -126,12 +136,15 @@ describe("PinnedRecordingCard", () => {
});

it("does nothing if isCurrentUser is false", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider value={globalProps}>
<PinnedRecordingCard {...{ ...props, isCurrentUser: false }} />
<PinnedRecordingCardWithWrapper
{...{ ...props, isCurrentUser: false }}
/>
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;

const { APIService } = instance.context;
const spy = jest.spyOn(APIService, "unpinRecording");
Expand All @@ -148,17 +161,18 @@ describe("PinnedRecordingCard", () => {
});

it("does nothing if CurrentUser.authtoken is not set", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider
value={{
...globalProps,
currentUser: { auth_token: undefined, name: "test" },
}}
>
<PinnedRecordingCard {...props} />
<PinnedRecordingCardWithWrapper {...props} />
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;

const { APIService } = instance.context;
const spy = jest.spyOn(APIService, "unpinRecording");
Expand All @@ -175,12 +189,13 @@ describe("PinnedRecordingCard", () => {
});

it("doesn't update currentlyPinned in state if status code is not 200", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider value={globalProps}>
<PinnedRecordingCard {...{ ...props }} />
<PinnedRecordingCardWithWrapper {...{ ...props }} />
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;

const { APIService } = instance.context;
const spy = jest.spyOn(APIService, "unpinRecording");
Expand All @@ -197,12 +212,13 @@ describe("PinnedRecordingCard", () => {
});

it("calls handleError if error is returned", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider value={globalProps}>
<PinnedRecordingCard {...{ ...props }} />
<PinnedRecordingCardWithWrapper {...{ ...props }} />
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;
instance.handleError = jest.fn();

const error = new Error("error");
Expand All @@ -226,12 +242,13 @@ describe("PinnedRecordingCard", () => {

describe("deletePin", () => {
it("calls API and updates isDeleted and currentlyPinned in state", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider value={globalProps}>
<PinnedRecordingCard {...{ ...props }} />
<PinnedRecordingCardWithWrapper {...props} />
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;

const { APIService } = instance.context;
const spy = jest.spyOn(APIService, "deletePin");
Expand Down Expand Up @@ -260,12 +277,15 @@ describe("PinnedRecordingCard", () => {
});

it("does nothing if isCurrentUser is false", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider value={globalProps}>
<PinnedRecordingCard {...{ ...props, isCurrentUser: false }} />
<PinnedRecordingCardWithWrapper
{...{ ...props, isCurrentUser: false }}
/>
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;

const { APIService } = instance.context;
const spy = jest.spyOn(APIService, "deletePin");
Expand All @@ -282,17 +302,18 @@ describe("PinnedRecordingCard", () => {
});

it("does nothing if CurrentUser.authtoken is not set", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider
value={{
...globalProps,
currentUser: { auth_token: undefined, name: "test" },
}}
>
<PinnedRecordingCard {...props} />
<PinnedRecordingCardWithWrapper {...props} />
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;

const { APIService } = instance.context;
const spy = jest.spyOn(APIService, "deletePin");
Expand All @@ -309,12 +330,13 @@ describe("PinnedRecordingCard", () => {
});

it("doesn't update currentlyPinned in state if status code is not 200", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider value={globalProps}>
<PinnedRecordingCard {...{ ...props }} />
<PinnedRecordingCardWithWrapper {...{ ...props }} />
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;

const { APIService } = instance.context;
const spy = jest.spyOn(APIService, "deletePin");
Expand All @@ -331,12 +353,13 @@ describe("PinnedRecordingCard", () => {
});

it("calls handleError if error is returned", async () => {
const wrapper = mount<PinnedRecordingCard>(
const componentWrapper = mount(
<GlobalAppContext.Provider value={globalProps}>
<PinnedRecordingCard {...{ ...props }} />
<PinnedRecordingCardWithWrapper {...{ ...props }} />
</GlobalAppContext.Provider>
);
const instance = wrapper.instance();
const wrapper = componentWrapper.find(PinnedRecordingCard);
const instance = wrapper.instance() as PinnedRecordingCard;
instance.handleError = jest.fn();

const error = new Error("error");
Expand Down
47 changes: 30 additions & 17 deletions frontend/js/tests/pins/UserPins.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,21 @@ import UserPins, {
} from "../../src/user/taste/components/UserPins";
import PinnedRecordingCard from "../../src/user/components/PinnedRecordingCard";
import RecordingFeedbackManager from "../../src/utils/RecordingFeedbackManager";
import { ReactQueryWrapper } from "../test-react-query";

// Font Awesome generates a random hash ID for each icon everytime.
// Mocking Math.random() fixes this
// https://github.com/FortAwesome/react-fontawesome/issues/194#issuecomment-627235075
jest.spyOn(global.Math, "random").mockImplementation(() => 0);

function UserPinsWithWrapper(props: UserPinsProps) {
return (
<ReactQueryWrapper>
<UserPins {...props} />
</ReactQueryWrapper>
);
}

// typescript doesn't recognise string literal values
const props = {
...pinsPageProps,
Expand Down Expand Up @@ -66,14 +75,14 @@ const mountOptions: { context: GlobalAppContextT } = {

describe("UserPins", () => {
it("renders correctly", () => {
const wrapper = mount<UserPins>(<UserPins {...props} />, mountOptions);
const wrapper = mount(<UserPinsWithWrapper {...props} />, mountOptions);
expect(wrapper.find("#pinned-recordings")).toHaveLength(1);
expect(wrapper.getDOMNode()).toHaveTextContent("Lorde");
expect(wrapper.getDOMNode()).toHaveTextContent("400 Lux");
});

it("renders the correct number of pinned recordings", () => {
const wrapper = mount<UserPins>(<UserPins {...props} />, mountOptions);
const wrapper = mount(<UserPinsWithWrapper {...props} />, mountOptions);

const wrapperElement = wrapper.find("#pinned-recordings");
const pinnedRecordings = wrapperElement.find(PinnedRecordingCard);
Expand All @@ -83,26 +92,28 @@ describe("UserPins", () => {
describe("handleLoadMore", () => {
describe("handleClickOlder", () => {
it("does nothing if page >= maxPage", async () => {
const wrapper = mount<UserPins>(<UserPins {...props} />, mountOptions);
const instance = wrapper.instance();
const wrapper = mount(<UserPinsWithWrapper {...props} />, mountOptions);
const userPinWrapper = wrapper.find(UserPins);
const instance = userPinWrapper.instance() as UserPins;

const spy = jest.fn().mockImplementation(() => {});
instance.getPinsFromAPI = spy;
await act(() => {
wrapper.setState({ maxPage: 1 });
userPinWrapper.setState({ maxPage: 1 });
});

await act(async () => {
await instance.handleLoadMore();
});

expect(wrapper.state("loading")).toBeFalsy();
expect(userPinWrapper.state("loading")).toBeFalsy();
expect(spy).not.toHaveBeenCalled();
});

it("calls the API to get next page", async () => {
const wrapper = mount<UserPins>(<UserPins {...props} />, mountOptions);
const instance = wrapper.instance();
const wrapper = mount(<UserPinsWithWrapper {...props} />, mountOptions);
const userPinWrapper = wrapper.find(UserPins);
const instance = userPinWrapper.instance() as UserPins;

const apiSpy = jest
.fn()
Expand All @@ -119,10 +130,10 @@ describe("UserPins", () => {
expect(getPinsFromAPISpy).toHaveBeenCalledWith(2);
expect(apiSpy).toHaveBeenCalledWith(props.user.name, 25, 25);

expect(wrapper.state("loading")).toBeFalsy();
expect(wrapper.state("page")).toEqual(2);
expect(userPinWrapper.state("loading")).toBeFalsy();
expect(userPinWrapper.state("page")).toEqual(2);
// result should be combined previous pins and new pins
expect(wrapper.state("pins")).toEqual([
expect(userPinWrapper.state("pins")).toEqual([
...props.pins,
...APIPinsPageTwo.pinned_recordings,
]);
Expand All @@ -132,21 +143,23 @@ describe("UserPins", () => {

describe("removePinFromPinsList", () => {
it("updates the listens state after removing particular pin", async () => {
const wrapper = mount<UserPins>(<UserPins {...props} />, mountOptions);
const instance = wrapper.instance();
const wrapper = mount(<UserPinsWithWrapper {...props} />, mountOptions);
const userPinWrapper = wrapper.find(UserPins);
const instance = userPinWrapper.instance() as UserPins;

await act(() => {
wrapper.setState({ pins: props.pins });
userPinWrapper.setState({ pins: props.pins });
});

expect(wrapper.state("pins")).toHaveLength(25);
expect(userPinWrapper.state("pins")).toHaveLength(25);

const expectedNewFirstPin = props.pins[1];
await act(() => {
instance.removePinFromPinsList(props.pins[0]);
});

expect(wrapper.state("pins")).toHaveLength(24);
expect(wrapper.state("pins")[0].recording_msid).toEqual(
expect(userPinWrapper.state("pins")).toHaveLength(24);
expect(userPinWrapper.state("pins")[0].recording_msid).toEqual(
expectedNewFirstPin.recording_msid
);
});
Expand Down

0 comments on commit 763a273

Please sign in to comment.