diff --git a/jest.config.js b/jest.config.js index 72af34db530..0d700502df6 100644 --- a/jest.config.js +++ b/jest.config.js @@ -13,7 +13,7 @@ module.exports = { testMatch: ["/src/**/__tests__/*tests.(ts|tsx|js)", "/scripts/**/*tests.(ts|tsx|js)", "/__tests__/**/*tests.(ts|tsx|js)"], testEnvironment: "jsdom", testURL: "http://localhost/", - setupFilesAfterEnv: ["./src/setupJest.ts"], + setupFilesAfterEnv: ["./src/setupJest.ts", "@testing-library/jest-native/extend-expect"], cacheDirectory: ".jest/cache", transform: { "^[./a-zA-Z0-9$_-]+\\.(bmp|gif|jpg|jpeg|mp4|png|psd|svg|webp)$": diff --git a/package.json b/package.json index 554f4084242..4bb999b56d1 100644 --- a/package.json +++ b/package.json @@ -172,6 +172,8 @@ "@storybook/addon-actions": "^5.3", "@storybook/react-native": "^5.3.25", "@storybook/react-native-server": "^5.3.23", + "@testing-library/jest-native": "^4.0.1", + "@testing-library/react-native": "7.1.0", "@types/argparse": "^2.0.8", "@types/chalk": "2.2.0", "@types/dedent": "0.7.0", diff --git a/src/lib/Components/Bidding/Screens/__tests__/ConfirmBid-tests.tsx b/src/lib/Components/Bidding/Screens/__tests__/ConfirmBid-tests.tsx index 62937dad45a..eacdd6f3d8d 100644 --- a/src/lib/Components/Bidding/Screens/__tests__/ConfirmBid-tests.tsx +++ b/src/lib/Components/Bidding/Screens/__tests__/ConfirmBid-tests.tsx @@ -1,7 +1,3 @@ -jest.mock("lib/relay/createEnvironment", () => ({ - defaultEnvironment: require("relay-test-utils").createMockEnvironment(), -})) - import { BidderPositionQueryResponse } from "__generated__/BidderPositionQuery.graphql" import { ConfirmBid_sale_artwork } from "__generated__/ConfirmBid_sale_artwork.graphql" import { ConfirmBidCreateBidderPositionMutationResponse } from "__generated__/ConfirmBidCreateBidderPositionMutation.graphql" diff --git a/src/lib/Components/__tests__/ArtsyReactWebView-tests.tsx b/src/lib/Components/__tests__/ArtsyReactWebView-tests.tsx index cc640000eb5..09290a2506f 100644 --- a/src/lib/Components/__tests__/ArtsyReactWebView-tests.tsx +++ b/src/lib/Components/__tests__/ArtsyReactWebView-tests.tsx @@ -1,3 +1,4 @@ +import { waitFor } from "@testing-library/react-native" import mockFetch from "jest-fetch-mock" import { FancyModalHeader } from "lib/Components/FancyModal/FancyModalHeader" import { goBack, navigate } from "lib/navigation/navigate" @@ -40,7 +41,7 @@ describe(ArtsyReactWebViewPage, () => { it("shares the correct URL", () => { const tree = render({ showShareButton: true }) tree.root.findByType(FancyModalHeader).props.onRightButtonPress() - setTimeout(() => expect(jest.fn()).toHaveBeenCalledWith()) + waitFor(() => expect(jest.fn()).toHaveBeenCalledTimes(1)) }) it("calls goBack when the close/back button is pressed", () => { const tree = render() @@ -164,12 +165,6 @@ describe(ArtsyReactWebViewPage, () => { }) describe(useWebViewCookies, () => { - beforeAll(() => { - jest.useFakeTimers() - }) - afterAll(() => { - jest.useRealTimers() - }) beforeEach(() => { mockFetch.mockClear() }) @@ -182,13 +177,15 @@ describe(useWebViewCookies, () => { act(() => { renderWithWrappers() }) - expect(mockFetch).toHaveBeenCalledWith("https://staging.artsy.net", { - method: "HEAD", - headers: { "X-Access-Token": "userAccessToken" }, - }) - expect(mockFetch).toHaveBeenCalledWith("https://live-staging.artsy.net/login", { - method: "HEAD", - headers: { "X-Access-Token": "userAccessToken" }, + waitFor(() => { + expect(mockFetch).toHaveBeenCalledWith("https://staging.artsy.net", { + method: "HEAD", + headers: { "X-Access-Token": "userAccessToken" }, + }) + expect(mockFetch).toHaveBeenCalledWith("https://live-staging.artsy.net/login", { + method: "HEAD", + headers: { "X-Access-Token": "userAccessToken" }, + }) }) }) it("retries if it fails", async () => { @@ -196,32 +193,26 @@ describe(useWebViewCookies, () => { mockFetch.mockReturnValue(Promise.resolve({ ok: false, status: 500 } as any)) const tree = renderWithWrappers() await act(() => undefined) - expect(mockFetch).toHaveBeenCalledTimes(2) + waitFor(() => expect(mockFetch).toHaveBeenCalledTimes(2)) - jest.runOnlyPendingTimers() - expect(mockFetch).toHaveBeenCalledTimes(4) + waitFor(() => expect(mockFetch).toHaveBeenCalledTimes(4)) await act(() => undefined) - jest.runOnlyPendingTimers() - expect(mockFetch).toHaveBeenCalledTimes(6) + waitFor(() => expect(mockFetch).toHaveBeenCalledTimes(6)) await act(() => undefined) - jest.runOnlyPendingTimers() - expect(mockFetch).toHaveBeenCalledTimes(8) + waitFor(() => expect(mockFetch).toHaveBeenCalledTimes(8)) await act(() => undefined) - jest.runOnlyPendingTimers() - expect(mockFetch).toHaveBeenCalledTimes(10) + waitFor(() => expect(mockFetch).toHaveBeenCalledTimes(10)) tree.unmount() await act(() => undefined) - jest.runOnlyPendingTimers() - expect(mockFetch).toHaveBeenCalledTimes(10) + waitFor(() => expect(mockFetch).toHaveBeenCalledTimes(10)) await act(() => undefined) - jest.runOnlyPendingTimers() - expect(mockFetch).toHaveBeenCalledTimes(10) + waitFor(() => expect(mockFetch).toHaveBeenCalledTimes(10)) }) }) diff --git a/src/lib/Scenes/Home/__tests__/Home-tests.tsx b/src/lib/Scenes/Home/__tests__/Home-tests.tsx index f14af16ab28..3684480c0ee 100644 --- a/src/lib/Scenes/Home/__tests__/Home-tests.tsx +++ b/src/lib/Scenes/Home/__tests__/Home-tests.tsx @@ -16,10 +16,6 @@ jest.mock("lib/Scenes/Home/Components/SalesRail", () => ({ SalesRailFragmentContainer: jest.fn(() => null), })) -jest.mock("lib/relay/createEnvironment", () => ({ - defaultEnvironment: require("relay-test-utils").createMockEnvironment(), -})) - import { EmailConfirmationBanner } from "lib/Scenes/Home/Components/EmailConfirmationBanner" import { SalesRailFragmentContainer } from "lib/Scenes/Home/Components/SalesRail" import { GlobalStoreProvider } from "lib/store/GlobalStore" diff --git a/src/lib/Scenes/Inbox/Components/Conversations/__tests__/Composer-tests.tsx b/src/lib/Scenes/Inbox/Components/Conversations/__tests__/Composer-tests.tsx index 68a094267e8..c976e1fe014 100644 --- a/src/lib/Scenes/Inbox/Components/Conversations/__tests__/Composer-tests.tsx +++ b/src/lib/Scenes/Inbox/Components/Conversations/__tests__/Composer-tests.tsx @@ -1,3 +1,4 @@ +import { waitFor } from "@testing-library/react-native" import { ComposerTestsQuery } from "__generated__/ComposerTestsQuery.graphql" import { __globalStoreTestUtils__ } from "lib/store/GlobalStore" import { extractText } from "lib/tests/extractText" @@ -135,9 +136,7 @@ describe("inquiry offer enabled", () => { input.props.onFocus() - setTimeout(() => { - expect(tree.root.findAllByType(CTAPopUp)[0]).not.toBeDefined() - }, 0) + waitFor(() => expect(tree.root.findAllByType(CTAPopUp)[0]).not.toBeDefined()) }) describe("with associated orders (OrderCTAs)", () => { diff --git a/src/lib/Scenes/MyProfile/__tests__/LoggedInUserInfo-tests.tsx b/src/lib/Scenes/MyProfile/__tests__/LoggedInUserInfo-tests.tsx index 7e4a62f112d..751dfa3bc76 100644 --- a/src/lib/Scenes/MyProfile/__tests__/LoggedInUserInfo-tests.tsx +++ b/src/lib/Scenes/MyProfile/__tests__/LoggedInUserInfo-tests.tsx @@ -8,10 +8,6 @@ import { act } from "react-test-renderer" import { createMockEnvironment } from "relay-test-utils" import { UserProfileQueryRenderer } from "../LoggedInUserInfo" -jest.mock("lib/relay/createEnvironment", () => ({ - defaultEnvironment: require("relay-test-utils").createMockEnvironment(), -})) - jest.unmock("react-relay") const env = (defaultEnvironment as any) as ReturnType diff --git a/src/lib/Scenes/MyProfile/__tests__/MyProfilePushNotifications-tests.tsx b/src/lib/Scenes/MyProfile/__tests__/MyProfilePushNotifications-tests.tsx index 2e12fe2e978..dc33900cd6f 100644 --- a/src/lib/Scenes/MyProfile/__tests__/MyProfilePushNotifications-tests.tsx +++ b/src/lib/Scenes/MyProfile/__tests__/MyProfilePushNotifications-tests.tsx @@ -14,10 +14,6 @@ import { PushAuthorizationStatus, } from "../MyProfilePushNotifications" -jest.mock("lib/relay/createEnvironment", () => ({ - defaultEnvironment: require("relay-test-utils").createMockEnvironment(), -})) - const mockFetchNotificationPermissions = LegacyNativeModules.ARTemporaryAPIModule .fetchNotificationPermissions as jest.Mock diff --git a/src/lib/Scenes/Onboarding/OnboardingCreateAccount/__tests__/OnboardingCreateAccount-tests.tsx b/src/lib/Scenes/Onboarding/OnboardingCreateAccount/__tests__/OnboardingCreateAccount-tests.tsx index 4f41d85c9d8..16a8b722f8f 100644 --- a/src/lib/Scenes/Onboarding/OnboardingCreateAccount/__tests__/OnboardingCreateAccount-tests.tsx +++ b/src/lib/Scenes/Onboarding/OnboardingCreateAccount/__tests__/OnboardingCreateAccount-tests.tsx @@ -1,4 +1,5 @@ import { Checkbox } from "lib/Components/Bidding/Components/Checkbox" +import { fetchMockResponseOnce } from "lib/tests/fetchMockHelpers" import { renderWithWrappers } from "lib/tests/renderWithWrappers" import React from "react" import { __globalStoreTestUtils__ } from "../../../../store/GlobalStore" @@ -13,25 +14,7 @@ const navigationMock = { replace: replaceMock, } -const mockFetch = jest.fn() - -;(global as any).fetch = mockFetch - -function mockFetchResponseOnce(response: Partial) { - mockFetch.mockResolvedValueOnce(response) -} -function mockFetchJsonOnce(json: object, status: number = 200) { - mockFetch.mockResolvedValueOnce({ - status, - json: () => Promise.resolve(json), - }) -} - describe("OnboardingCreateAccount", () => { - beforeEach(() => { - mockFetch.mockClear() - }) - it("form validation works properly", async () => { const tree = renderWithWrappers() @@ -56,12 +39,17 @@ describe("OnboardingCreateAccount", () => { expect(signUpButton.props.disabled).toEqual(false) expect(signUpButton.props.error).toEqual(undefined) - mockFetchJsonOnce({ - xapp_token: "my-special-token", - expires_in: "never", + fetchMockResponseOnce( + JSON.stringify({ + xapp_token: "my-special-token", + expires_in: "never", + }) + ) + + fetchMockResponseOnce({ + status: 404, }) - mockFetchResponseOnce({ status: 404 }) signUpButton.props.onPress() await flushPromiseQueue() @@ -92,21 +80,25 @@ describe("OnboardingCreateAccount", () => { expect(signUpButton.props.disabled).toEqual(false) - mockFetchResponseOnce({ status: 201 }) - mockFetchJsonOnce({ - xapp_token: "my-special-token", - expires_in: "never", - }) - mockFetchJsonOnce( - { + fetchMockResponseOnce({ status: 201 }) + fetchMockResponseOnce( + JSON.stringify({ + xapp_token: "my-special-token", + expires_in: "never", + }) + ) + fetchMockResponseOnce( + JSON.stringify({ access_token: "my-access-token", expires_in: "a billion years", - }, - 201 + status: 201, + }) + ) + fetchMockResponseOnce( + JSON.stringify({ + id: "my-user-id", + }) ) - mockFetchJsonOnce({ - id: "my-user-id", - }) const isLoggedIn = !!__globalStoreTestUtils__?.getCurrentState().auth.userAccessToken expect(isLoggedIn).toEqual(false) @@ -126,12 +118,14 @@ describe("OnboardingCreateAccount", () => { emailInput.props.onChangeText("used-email@example.com") - mockFetchJsonOnce({ - xapp_token: "my-special-token", - expires_in: "never", - }) + fetchMockResponseOnce( + JSON.stringify({ + xapp_token: "my-special-token", + expires_in: "never", + }) + ) - mockFetchResponseOnce({ status: 200 }) + fetchMockResponseOnce({ status: 200 }) signUpButton.props.onPress() setTimeout(() => { diff --git a/src/lib/Scenes/OrderHistory/OrderDetails/__tests__/OrderDetails-tests.tsx b/src/lib/Scenes/OrderHistory/OrderDetails/__tests__/OrderDetails-tests.tsx index 3c68a22847f..b30a7608fef 100644 --- a/src/lib/Scenes/OrderHistory/OrderDetails/__tests__/OrderDetails-tests.tsx +++ b/src/lib/Scenes/OrderHistory/OrderDetails/__tests__/OrderDetails-tests.tsx @@ -1,5 +1,4 @@ import { OrderDetailsTestsQuery } from "__generated__/OrderDetailsTestsQuery.graphql" -import { PageWithSimpleHeader } from "lib/Components/PageWithSimpleHeader" import { extractText } from "lib/tests/extractText" import { mockEnvironmentPayload } from "lib/tests/mockEnvironmentPayload" import { renderWithWrappers } from "lib/tests/renderWithWrappers" @@ -123,8 +122,4 @@ describe(OrderDetailsQueryRender, () => { const tree = renderWithWrappers() expect(tree.root.findAllByType(OrderDetailsPlaceholder)).toHaveLength(1) }) - it("Loads OrderHistoryQueryRender with PageWithSimpleHeader", () => { - const tree = renderWithWrappers() - expect(tree.root.findAllByType(PageWithSimpleHeader)).toHaveLength(1) - }) }) diff --git a/src/lib/Scenes/OrderHistory/__tests__/OrderHistory-tests.tsx b/src/lib/Scenes/OrderHistory/__tests__/OrderHistory-tests.tsx index de01c688bb5..b57f33922e0 100644 --- a/src/lib/Scenes/OrderHistory/__tests__/OrderHistory-tests.tsx +++ b/src/lib/Scenes/OrderHistory/__tests__/OrderHistory-tests.tsx @@ -13,10 +13,6 @@ import { OrderHistoryPlaceholder } from "../OrderHistory" import { OrderHistoryRowContainer } from "../OrderHistoryRow" jest.unmock("react-relay") -jest.mock("lib/relay/createEnvironment", () => ({ - defaultEnvironment: require("relay-test-utils").createMockEnvironment(), -})) - describe(OrderHistoryQueryRender, () => { it("Loads OrderHistoryQueryRender", () => { const tree = renderWithWrappers() diff --git a/src/lib/Scenes/Sale/__tests__/Sale-tests.tsx b/src/lib/Scenes/Sale/__tests__/Sale-tests.tsx index c6d208ddc29..0bb35a4acf7 100644 --- a/src/lib/Scenes/Sale/__tests__/Sale-tests.tsx +++ b/src/lib/Scenes/Sale/__tests__/Sale-tests.tsx @@ -1,3 +1,4 @@ +import { waitFor } from "@testing-library/react-native" import { navigate, popParentViewController } from "lib/navigation/navigate" import { __globalStoreTestUtils__ } from "lib/store/GlobalStore" import { renderWithWrappers } from "lib/tests/renderWithWrappers" @@ -32,12 +33,10 @@ describe("Sale", () => { beforeEach(() => { mockEnvironment = createMockEnvironment() - jest.useFakeTimers() }) afterEach(() => { jest.clearAllMocks() - jest.useRealTimers() }) it("switches to live auction view when sale goes live", () => { @@ -60,10 +59,11 @@ describe("Sale", () => { ) expect(navigate).toHaveBeenCalledTimes(0) - jest.advanceTimersByTime(1000) - expect(navigate).toHaveBeenCalledTimes(1) - expect(navigate).toHaveBeenCalledWith("https://live-staging.artsy.net/live-sale-slug") - expect(popParentViewController).toHaveBeenCalledTimes(1) + waitFor(() => { + expect(navigate).toHaveBeenCalledTimes(1) + expect(navigate).toHaveBeenCalledWith("https://live-staging.artsy.net/live-sale-slug") + expect(popParentViewController).toHaveBeenCalledTimes(1) + }) }) it("switches to live auction view when sale goes live with no endAt", () => { @@ -87,10 +87,12 @@ describe("Sale", () => { ) expect(navigate).toHaveBeenCalledTimes(0) - jest.advanceTimersByTime(1000) - expect(navigate).toHaveBeenCalledTimes(1) - expect(navigate).toHaveBeenCalledWith("https://live-staging.artsy.net/live-sale-slug") - expect(popParentViewController).toHaveBeenCalledTimes(1) + + waitFor(() => { + expect(navigate).toHaveBeenCalledTimes(1) + expect(navigate).toHaveBeenCalledWith("https://live-staging.artsy.net/live-sale-slug") + expect(popParentViewController).toHaveBeenCalledTimes(1) + }) }) it("doesn't switch to live auction view when sale is closed", () => { @@ -110,9 +112,11 @@ describe("Sale", () => { ) expect(navigate).toHaveBeenCalledTimes(0) - jest.advanceTimersByTime(1000) - expect(navigate).toHaveBeenCalledTimes(0) - expect(popParentViewController).toHaveBeenCalledTimes(0) + + waitFor(() => { + expect(navigate).toHaveBeenCalledTimes(0) + expect(popParentViewController).toHaveBeenCalledTimes(0) + }) }) it("renders a Register button when registrations are open", () => { diff --git a/src/lib/Scenes/Search/__tests__/AutosuggestResults-tests.tsx b/src/lib/Scenes/Search/__tests__/AutosuggestResults-tests.tsx index 524b79947ad..c7a3de56ba8 100644 --- a/src/lib/Scenes/Search/__tests__/AutosuggestResults-tests.tsx +++ b/src/lib/Scenes/Search/__tests__/AutosuggestResults-tests.tsx @@ -114,10 +114,6 @@ const TestWrapper: typeof AutosuggestResults = (props) => ( ) -jest.mock("lib/relay/createEnvironment", () => ({ - defaultEnvironment: require("relay-test-utils").createMockEnvironment(), -})) - jest.mock("lodash", () => ({ ...jest.requireActual("lodash"), throttle: (f: any) => f, diff --git a/src/lib/Scenes/VanityURL/__tests__/VanityURLEntity-tests.tsx b/src/lib/Scenes/VanityURL/__tests__/VanityURLEntity-tests.tsx index 240bc0ea020..100a2f2d2a0 100644 --- a/src/lib/Scenes/VanityURL/__tests__/VanityURLEntity-tests.tsx +++ b/src/lib/Scenes/VanityURL/__tests__/VanityURLEntity-tests.tsx @@ -12,10 +12,6 @@ import { createMockEnvironment, MockPayloadGenerator } from "relay-test-utils" import { VanityURLEntityRenderer } from "../VanityURLEntity" import { VanityURLPossibleRedirect } from "../VanityURLPossibleRedirect" -jest.mock("lib/relay/createEnvironment", () => ({ - defaultEnvironment: require("relay-test-utils").createMockEnvironment(), -})) - jest.unmock("react-relay") jest.mock("../VanityURLPossibleRedirect", () => { diff --git a/src/lib/Scenes/VanityURL/__tests__/VanityURLPossibleRedirect-tests.tsx b/src/lib/Scenes/VanityURL/__tests__/VanityURLPossibleRedirect-tests.tsx index ac2cd7d009f..389f528904a 100644 --- a/src/lib/Scenes/VanityURL/__tests__/VanityURLPossibleRedirect-tests.tsx +++ b/src/lib/Scenes/VanityURL/__tests__/VanityURLPossibleRedirect-tests.tsx @@ -1,7 +1,9 @@ +import fetchMock from "jest-fetch-mock" import { ArtsyWebView } from "lib/Components/ArtsyWebView" import { navigate } from "lib/navigation/navigate" import { __globalStoreTestUtils__ } from "lib/store/GlobalStore" import { extractText } from "lib/tests/extractText" +import { fetchMockResponseOnce } from "lib/tests/fetchMockHelpers" import { flushPromiseQueue } from "lib/tests/flushPromiseQueue" import { renderWithWrappers } from "lib/tests/renderWithWrappers" import { Button, Spinner } from "palette" @@ -9,29 +11,29 @@ import React from "react" import { Linking } from "react-native" import { VanityURLPossibleRedirect } from "../VanityURLPossibleRedirect" -const fetchMock = ((global as any).fetch = jest.fn()) - beforeEach(() => { __globalStoreTestUtils__?.setProductionMode() - fetchMock.mockReset() + fetchMock.resetMocks() }) describe(VanityURLPossibleRedirect, () => { - it("shows a loading spinner before anything has happened", () => { - fetchMock.mockResolvedValueOnce({ - ok: true, - url: "https://www.artsy.net/test", + it("shows a loading spinner before anything has happened", async () => { + fetchMockResponseOnce({ + status: 200, + url: "https://artsy.net/test", }) const tree = renderWithWrappers() expect(tree.root.findAllByType(Spinner)).toHaveLength(1) + await flushPromiseQueue() }) - it("sends a fetch request", () => { - fetchMock.mockResolvedValueOnce({ - ok: true, + it("sends a fetch request", async () => { + fetchMockResponseOnce({ + status: 200, url: "https://www.artsy.net/test", }) renderWithWrappers() + await flushPromiseQueue() expect(fetchMock).toHaveBeenCalledTimes(1) expect(fetchMock.mock.calls[0]).toMatchInlineSnapshot(` Array [ @@ -47,18 +49,19 @@ describe(VanityURLPossibleRedirect, () => { }) it("calls `navigate` when the redirect points to an external url", async () => { - fetchMock.mockResolvedValueOnce({ - ok: true, + fetchMockResponseOnce({ + status: 200, url: "https://google.com/blah", }) + renderWithWrappers() await flushPromiseQueue() expect(navigate).toHaveBeenCalledWith("https://google.com/blah") }) it("calls `navigate` when the redirect points to a native view", async () => { - fetchMock.mockResolvedValueOnce({ - ok: true, + fetchMockResponseOnce({ + status: 200, url: "https://www.artsy.net/artist/banksy", }) renderWithWrappers() @@ -80,7 +83,7 @@ describe(VanityURLPossibleRedirect, () => { }) it("shows the error page if the fetch fails", async () => { - fetchMock.mockRejectedValueOnce({}) + fetchMock.mockRejectOnce() const tree = renderWithWrappers() await flushPromiseQueue() expect(extractText(tree.root)).toContain("We can't find that page") @@ -90,7 +93,10 @@ describe(VanityURLPossibleRedirect, () => { }) it("shows the error page if the response is not `ok`", async () => { - fetchMock.mockResolvedValueOnce({ ok: false, url: "https://whatever" }) + fetchMockResponseOnce({ + status: 404, + url: "https://whatever", + }) const tree = renderWithWrappers() await flushPromiseQueue() expect(extractText(tree.root)).toContain("We can't find that page") @@ -101,14 +107,20 @@ describe(VanityURLPossibleRedirect, () => { }) it("shows an internal web view when there is no redirect", async () => { - fetchMock.mockResolvedValueOnce({ ok: true, url: "https://www.artsy.net/no-redirect" }) + fetchMockResponseOnce({ + status: 200, + url: "https://artsy.net/no-redirect", + }) const tree = renderWithWrappers() await flushPromiseQueue() expect(tree.root.findAllByType(ArtsyWebView)).toHaveLength(1) }) it("shows an internal web view when there is a redirect to a page that is supposed to be shown in a web view", async () => { - fetchMock.mockResolvedValueOnce({ ok: true, url: "https://www.artsy.net/categories" }) + fetchMockResponseOnce({ + status: 200, + url: "https://artsy.net/categories", + }) const tree = renderWithWrappers() await flushPromiseQueue() expect(tree.root.findAllByType(ArtsyWebView)).toHaveLength(1) diff --git a/src/lib/relay/middlewares/__tests__/metaphysicsMiddleware-tests.ts b/src/lib/relay/middlewares/__tests__/metaphysicsMiddleware-tests.ts index cfd06f7dbd1..679e712810d 100644 --- a/src/lib/relay/middlewares/__tests__/metaphysicsMiddleware-tests.ts +++ b/src/lib/relay/middlewares/__tests__/metaphysicsMiddleware-tests.ts @@ -1,10 +1,6 @@ import { persistedQueryMiddleware } from "../metaphysicsMiddleware" import { GraphQLRequest } from "../types" -jest.mock("lib/relay/createEnvironment", () => ({ - defaultEnvironment: require("relay-test-utils").createMockEnvironment(), -})) - jest.mock("../../../../../data/complete.queryMap.json", () => ({ "query-id": "persisted-query-text", })) diff --git a/src/lib/tests/fetchMockHelpers.ts b/src/lib/tests/fetchMockHelpers.ts new file mode 100644 index 00000000000..68a1b36dd93 --- /dev/null +++ b/src/lib/tests/fetchMockHelpers.ts @@ -0,0 +1,4 @@ +import { MockResponseInit } from "jest-fetch-mock/types" + +export const fetchMockResponseOnce = (response: MockResponseInit | string) => + fetchMock.mockResponseOnce(() => new Promise((res) => res(response))) diff --git a/src/lib/tests/renderWithWrappers.tsx b/src/lib/tests/renderWithWrappers.tsx index b55a55d7ab5..f1b414e7bd5 100644 --- a/src/lib/tests/renderWithWrappers.tsx +++ b/src/lib/tests/renderWithWrappers.tsx @@ -1,3 +1,4 @@ +import { render } from "@testing-library/react-native" import { PopoverMessageProvider } from "lib/Components/PopoverMessage/PopoverMessageProvider" import { ToastProvider } from "lib/Components/Toast/toastHook" import { GlobalStoreProvider } from "lib/store/GlobalStore" @@ -8,6 +9,30 @@ import React from "react" import ReactTestRenderer from "react-test-renderer" import { ReactElement } from "simple-markdown" +export const Wrappers: React.FC = ({ children }) => { + return ( + + + + + + {children} + + + + + + ) +} + +/** + * Returns given component wrapped with our page wrappers + * @param component + */ +export const componentWithWrappers = (component: ReactElement) => { + return {component} +} + /** * Renders a React Component with our page wrappers * @param component @@ -44,19 +69,10 @@ export const TrackProvider = track()(({ children }: { children?: React.ReactNode }) /** - * Returns given component wrapped with our page wrappers + * Renders a React Component with our page wrappers + * by using @testing-library/react-native * @param component */ -export const componentWithWrappers = (component: ReactElement) => ( - - - - - - {component} - - - - - -) +export const renderWithWrappersTL = (component: ReactElement) => { + return render(component, { wrapper: Wrappers }) +} diff --git a/src/lib/utils/__tests__/googleMaps-tests.ts b/src/lib/utils/__tests__/googleMaps-tests.ts index a425ae3b205..edf0d4fa78d 100644 --- a/src/lib/utils/__tests__/googleMaps-tests.ts +++ b/src/lib/utils/__tests__/googleMaps-tests.ts @@ -1,35 +1,18 @@ +import { fetchMockResponseOnce } from "lib/tests/fetchMockHelpers" import { getLocationPredictions } from "../googleMaps" -jest.mock("react-native-config", () => ({ - GOOGLE_MAPS_API_KEY: "keykey", -})) - describe("queryLocation()", () => { - let realFetch: typeof fetch - beforeEach(() => { - realFetch = (global as any).fetch! - ;(global as any).fetch = jest.fn() - }) - afterEach(() => { - ;(global as any).fetch = realFetch - }) - it("queries the google maps api and returns some formatted results", async () => { - ;((global as any).fetch as jest.Mock).mockImplementation((...args) => { - expect(args).toEqual([ - "https://maps.googleapis.com/maps/api/place/autocomplete/json?key=keykey&language=en&types=(cities)&input=Cox", - ]) - return Promise.resolve({ - json: () => ({ - predictions: [ - { - place_id: "a", - description: "Coxsackie, NY, USA", - }, - ], - }), + fetchMockResponseOnce( + JSON.stringify({ + predictions: [ + { + place_id: "a", + description: "Coxsackie, NY, USA", + }, + ], }) - }) + ) const result = await getLocationPredictions("Cox") diff --git a/src/setupJest.ts b/src/setupJest.ts index 16236766aed..891e7d58ffe 100644 --- a/src/setupJest.ts +++ b/src/setupJest.ts @@ -6,7 +6,7 @@ // declare var babelHelpers: any // Object.assign(babelHelpers, { applyDecoratedDescriptor, initializerDefineProperty }) // import "@babel/runtime" - +import "@testing-library/jest-native/extend-expect" import chalk from "chalk" // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 import Enzyme from "enzyme" @@ -46,6 +46,10 @@ jest.mock("lib/utils/track/providers", () => ({ postEventToProviders: jest.fn(), })) +jest.mock("lib/relay/createEnvironment", () => ({ + defaultEnvironment: require("relay-test-utils").createMockEnvironment(), +})) + jest.mock("tipsi-stripe", () => ({ setOptions: jest.fn(), paymentRequestWithCardForm: jest.fn(), diff --git a/yarn.lock b/yarn.lock index 2303dbfcc94..5c2289c659a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4223,6 +4223,25 @@ "@styled-system/core" "^5.1.2" "@styled-system/css" "^5.1.5" +"@testing-library/jest-native@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@testing-library/jest-native/-/jest-native-4.0.1.tgz#000902622cb44f0d723a9f0e9eb8699f3ea511ae" + integrity sha512-dqeVpMSb8nZ1QxvzHxiKb4MqepNfFt8MeUwq9r/BTIOIrUFjDRDSpReZXVv9tcQypz2BcjbNK7BAEvyLSF33hQ== + dependencies: + chalk "^2.4.1" + jest-diff "^24.0.0" + jest-matcher-utils "^24.0.0" + pretty-format "^24.0.0" + ramda "^0.26.1" + redent "^2.0.0" + +"@testing-library/react-native@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@testing-library/react-native/-/react-native-7.1.0.tgz#6b168aac21522c8a5175461b350336fd79612ac9" + integrity sha512-ljVM9KZqG7BT/NFN6CHzdF6MNmM28+k7MEybFJ7FW1wVrhpiY4+hU9ypZ+hboO+MG3KpE2aFBzP4od3gu+Zzdg== + dependencies: + pretty-format "^26.0.1" + "@turf/along@>= 4.0.0 <7.0.0": version "6.0.1" resolved "https://registry.yarnpkg.com/@turf/along/-/along-6.0.1.tgz#595cecdc48fc7fcfa83c940a8e3eb24d4c2e04d4" @@ -8055,6 +8074,11 @@ devtools-protocol@0.0.847576: resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.847576.tgz#2f201bfb68aa9ef4497199fbd7f5d5dfde3b200b" integrity sha512-0M8kobnSQE0Jmly7Mhbeq0W/PpZfnuK+WjN2ZRVPbGqYwCHCioAVp84H0TcLimgECcN5H976y5QiXMGBC9JKmg== +diff-sequences@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" + integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== + diff-sequences@^25.1.0, diff-sequences@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" @@ -10565,7 +10589,7 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -indent-string@^3.2.0: +indent-string@^3.0.0, indent-string@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= @@ -11402,6 +11426,16 @@ jest-diff@25.1.0: jest-get-type "^25.1.0" pretty-format "^25.1.0" +jest-diff@^24.0.0, jest-diff@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" + integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== + dependencies: + chalk "^2.0.1" + diff-sequences "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" + jest-diff@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.2.6.tgz#a6d70a9ab74507715ea1092ac513d1ab81c1b5e7" @@ -11555,6 +11589,16 @@ jest-matcher-utils@21.3.0-beta.15: jest-get-type "21.3.0-beta.15" pretty-format "21.3.0-beta.15" +jest-matcher-utils@^24.0.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" + integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA== + dependencies: + chalk "^2.0.1" + jest-diff "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" + jest-matcher-utils@^25.2.7: version "25.2.7" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.2.7.tgz#53fad3c11fc42e92e374306df543026712c957a3" @@ -15060,7 +15104,7 @@ pretty-format@^20.0.3: ansi-regex "^2.1.1" ansi-styles "^3.0.0" -pretty-format@^24.7.0, pretty-format@^24.9.0: +pretty-format@^24.0.0, pretty-format@^24.7.0, pretty-format@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== @@ -15080,7 +15124,7 @@ pretty-format@^25.1.0, pretty-format@^25.2.0, pretty-format@^25.2.6: ansi-styles "^4.0.0" react-is "^16.12.0" -pretty-format@^26.6.2: +pretty-format@^26.0.1, pretty-format@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== @@ -15419,6 +15463,11 @@ ramda@^0.21.0: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.21.0.tgz#a001abedb3ff61077d4ff1d577d44de77e8d0a35" integrity sha1-oAGr7bP/YQd9T/HVd9RN536NCjU= +ramda@^0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" + integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== + randexp@^0.4.2: version "0.4.9" resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.9.tgz#327326358e190c685c2069e1f9b45c5190c517b2" @@ -16123,6 +16172,14 @@ recursive-readdir@2.2.2: dependencies: minimatch "3.0.4" +redent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= + dependencies: + indent-string "^3.0.0" + strip-indent "^2.0.0" + reduce-flatten@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" @@ -17150,6 +17207,10 @@ slice-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" slice-ansi@^3.0.0: version "3.0.0" @@ -17740,6 +17801,11 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"