import { useRoute } from "@react-navigation/native"; import { screen } from "@testing-library/react-native"; import ObsDetailsScreen from "components/ObsDetailsSharedComponents/ObsDetailsScreen"; import inatjs from "inaturalistjs"; import React from "react"; import * as useLocalObservation from "sharedHooks/useLocalObservation"; import factory from "tests/factory"; import faker from "tests/helpers/faker"; import { renderComponent } from "tests/helpers/render"; const mockUuid = "test-123"; const mockCurrentUser = factory( "LocalUser", { id: 123, login: faker.internet.userName( ), } ); const mockLocalObservation = factory( "LocalObservation", { user: factory( "LocalUser", { id: 123, } ), uuid: mockUuid, taxon: factory( "LocalTaxon", { name: faker.person.firstName( ), rank: "species", rank_level: 10, } ), } ); jest.mock( "@react-native-community/netinfo", () => ( { useNetInfo: () => ( { isConnected: true } ), configure: jest.fn( ), } ) ); jest.mock( "sharedHooks/useCurrentUser", () => ( { __esModule: true, default: () => mockCurrentUser, } ) ); jest.mock( "sharedHooks/useLocalObservation", () => ( { __esModule: true, default: jest.fn( () => ( { localObservation: null, } ) ), } ) ); jest.mock( "sharedHooks/useRemoteObservation", ( ) => ( { __esModule: true, default: ( _uuid, _fetchRemoteEnabled ) => ( { remoteObservation: null, refetchRemoteObservation: jest.fn( ), isRefetching: false, fetchRemoteObservationError: null, } ), } ) ); useRoute.mockImplementation( ( ) => ( { params: { uuid: mockUuid }, } ) ); jest.mock( "@react-navigation/native", () => { const actualNav = jest.requireActual( "@react-navigation/native" ); return { ...actualNav, useRoute: jest.fn( ), useNavigation: () => ( { navigate: jest.fn(), addListener: jest.fn(), setOptions: jest.fn(), canGoBack: jest.fn(), } ), }; } ); jest.mock( "sharedHooks/useAuthenticatedQuery", () => ( { __esModule: true, default: jest.fn( () => ( { data: null, } ) ), } ) ); jest.mock( "sharedHooks/useAuthenticatedMutation", () => ( { __esModule: true, default: ( ) => ( { mutate: jest.fn(), } ), } ) ); jest.mock( "sharedHooks/useObservationsUpdates", () => ( { __esModule: true, default: jest.fn( () => ( { refetch: jest.fn(), } ) ), } ) ); describe( "ObsDetailsScreen", ( ) => { beforeAll( () => { jest.useFakeTimers( ); } ); describe( "when showSavedMatch is true", ( ) => { it( "renders SavedMatchContainer when observation belongs to current user and is not synced", ( ) => { const unsyncedLocalObservation = { ...mockLocalObservation, wasSynced: jest.fn( () => false ), }; jest.spyOn( useLocalObservation, "default" ).mockImplementation( () => ( { localObservation: unsyncedLocalObservation, markDeletedLocally: jest.fn( ), markViewedLocally: jest.fn( ), } ) ); renderComponent( ); expect( screen.getByTestId( "SavedMatch.container" ) ).toBeTruthy( ); expect( screen.queryByTestId( "ObsDetails.container" ) ).toBeFalsy( ); }, ); it( "renders SavedMatchContainer when observation has no user and is not synced", ( ) => { const unsyncedLocalObservationNoUser = factory( "LocalObservation", { user: null, uuid: mockUuid, wasSynced: jest.fn( () => false ), } ); jest.spyOn( useLocalObservation, "default" ).mockImplementation( () => ( { localObservation: unsyncedLocalObservationNoUser, markDeletedLocally: jest.fn( ), markViewedLocally: jest.fn( ), } ) ); renderComponent( ); expect( screen.getByTestId( "SavedMatch.container" ) ).toBeTruthy( ); expect( screen.queryByTestId( "ObsDetails.container" ) ).toBeFalsy( ); } ); it( "does not mark observation updates as viewed", ( ) => { const unsyncedLocalObservation = { ...mockLocalObservation, wasSynced: jest.fn( () => false ), }; jest.spyOn( useLocalObservation, "default" ).mockImplementation( () => ( { localObservation: unsyncedLocalObservation, markDeletedLocally: jest.fn( ), markViewedLocally: jest.fn( ), } ) ); renderComponent( ); expect( screen.getByTestId( "SavedMatch.container" ) ).toBeTruthy( ); expect( inatjs.observations.viewedUpdates ).not.toHaveBeenCalled( ); } ); } ); describe( "when showSavedMatch is false", ( ) => { it( "renders ObsDetailsContainer when observation is synced", ( ) => { const syncedLocalObservation = { ...mockLocalObservation, wasSynced: jest.fn( () => true ), }; jest.spyOn( useLocalObservation, "default" ).mockImplementation( () => ( { localObservation: syncedLocalObservation, markDeletedLocally: jest.fn( ), markViewedLocally: jest.fn( ), } ) ); renderComponent( ); expect( screen.getByTestId( "ObsDetails.container" ) ).toBeTruthy( ); expect( screen.queryByTestId( "SavedMatch.container" ) ).toBeFalsy( ); } ); it( "renders ObsDetailsContainer when observation does not belong to current user", ( ) => { const otherUserObservation = factory( "LocalObservation", { user: factory( "LocalUser", { id: 456, } ), uuid: mockUuid, taxon: factory( "LocalTaxon", { name: faker.person.firstName( ), rank: "species", rank_level: 10, } ), wasSynced: jest.fn( () => false ), } ); jest.spyOn( useLocalObservation, "default" ).mockImplementation( () => ( { localObservation: otherUserObservation, markDeletedLocally: jest.fn( ), markViewedLocally: jest.fn( ), } ) ); renderComponent( ); expect( screen.getByTestId( "ObsDetails.container" ) ).toBeTruthy( ); expect( screen.queryByTestId( "SavedMatch.container" ) ).toBeFalsy( ); }, ); } ); } );