import { useNetInfo, } from "@react-native-community/netinfo"; import { fireEvent, screen } from "@testing-library/react-native"; import Settings from "components/Settings/Settings"; import i18n from "i18next"; import inatjs from "inaturalistjs"; import React from "react"; import * as useCurrentUser from "sharedHooks/useCurrentUser"; import useStore from "stores/useStore"; import factory, { makeResponse } from "tests/factory"; import { renderComponent } from "tests/helpers/render"; const mockUser = factory( "LocalUser" ); const mockNavigate = jest.fn( ); jest.mock( "@react-navigation/native", ( ) => { const actualNav = jest.requireActual( "@react-navigation/native" ); return { ...actualNav, useNavigation: ( ) => ( { navigate: mockNavigate, } ), }; } ); const initialStoreState = useStore.getState( ); const toggleAdvancedSwitch = async ( ) => { const advancedSwitch = await screen.findByTestId( "advanced-interface-switch.switch" ); fireEvent.press( advancedSwitch ); }; beforeAll( async ( ) => { useStore.setState( initialStoreState, true ); // userEvent recommends fake timers jest.useFakeTimers( ); } ); beforeEach( ( ) => { // reset the picker for each test i18n.changeLanguage( "en" ); inatjs.users.me.mockResolvedValue( makeResponse( [mockUser] ) ); inatjs.translations.locales.mockResolvedValue( makeResponse( [{ language_in_locale: "Slovenský", locale: "sk", }, { language_in_locale: "Español (Colombia)", locale: "es-CO", }] ) ); } ); describe( "Settings", ( ) => { it( "should toggle the green observation button from all options -> AICamera", async ( ) => { renderComponent( ); await toggleAdvancedSwitch( ); const allObsOptions = await screen.findByLabelText( /All observation options/ ); expect( allObsOptions ).toHaveProp( "accessibilityState", expect.objectContaining( { checked: true, } ) ); const aiCameraRow = await screen.findByLabelText( "iNaturalist AI Camera" ); expect( aiCameraRow ).toHaveProp( "accessibilityState", expect.objectContaining( { checked: false, } ) ); fireEvent.press( aiCameraRow ); expect( aiCameraRow ).toHaveProp( "accessibilityState", expect.objectContaining( { checked: true, } ) ); } ); describe( "is logged in", ( ) => { beforeEach( ( ) => { jest.spyOn( useCurrentUser, "default" ).mockImplementation( () => mockUser ); } ); afterEach( ( ) => { jest.clearAllMocks( ); } ); it( "should navigate user to iNaturalist settings", async ( ) => { renderComponent( ); const iNatSettingsButton = await screen.findByText( "ACCOUNT SETTINGS" ); fireEvent.press( iNatSettingsButton ); expect( mockNavigate ).toHaveBeenCalledWith( "FullPageWebView", expect.objectContaining( { loggedIn: true, } ), ); } ); describe( "no internet", ( ) => { beforeEach( ( ) => { useNetInfo.mockImplementation( ( ) => ( { isConnected: false } ) ); } ); it( "should not navigate to iNaturalist settings if no internet", async ( ) => { renderComponent( ); const iNatSettingsButton = await screen.findByText( "ACCOUNT SETTINGS" ); fireEvent.press( iNatSettingsButton ); expect( mockNavigate ).not.toHaveBeenCalled( ); } ); } ); } ); test( "should change language immediately via language picker via online results", async ( ) => { renderComponent( ); const changeLanguageButton = await screen.findByText( /CHANGE APP LANGUAGE/ ); fireEvent.press( changeLanguageButton ); const picker = await screen.findByTestId( "ReactNativePicker" ); // English is number 11 in the list of offline locales expect( picker.props.selectedIndex ).toStrictEqual( 0 ); // trigger a change to the UI, selecting the second element fireEvent( picker, "onValueChange", "es-CO" ); expect( picker.props.selectedIndex ).toStrictEqual( 1 ); const confirmText = await screen.findByText( "CONFIRM" ); fireEvent.press( confirmText ); const columbianSpanishSciNameTexts = await screen.findAllByText( /Nombre científico/ ); expect( columbianSpanishSciNameTexts.length ).toBeGreaterThan( 0 ); expect( columbianSpanishSciNameTexts[0] ).toBeVisible( ); } ); } );