Files
iNaturalistReactNative/tests/unit/providers/ExploreV2Context.test.js
2026-05-27 23:52:00 -07:00

249 lines
8.5 KiB
JavaScript

import {
defaultExploreV2Location,
EXPLORE_V2_ACTION,
EXPLORE_V2_PLACE_MODE,
exploreV2Reducer,
initialExploreV2State,
} from "providers/ExploreV2Context";
import fetchCoarseUserLocation from "sharedHelpers/fetchCoarseUserLocation";
import { OBSERVATIONS_SORT } from "sharedHelpers/observationsSort";
jest.mock( "sharedHelpers/fetchCoarseUserLocation", ( ) => ( {
__esModule: true,
default: jest.fn( ),
} ) );
describe( "initialExploreV2State", ( ) => {
it( "starts with no subject, UNINITIALIZED placeMode, newest-upload sort, empty filters", ( ) => {
expect( initialExploreV2State.subject ).toBeNull( );
expect( initialExploreV2State.location.placeMode ).toBe( EXPLORE_V2_PLACE_MODE.UNINITIALIZED );
expect( initialExploreV2State.sortBy ).toBe( OBSERVATIONS_SORT.DATE_UPLOADED_NEWEST );
expect( initialExploreV2State.filters ).toEqual( {} );
} );
} );
describe( "exploreV2Reducer", ( ) => {
describe( EXPLORE_V2_ACTION.SET_SUBJECT, ( ) => {
it( "sets a taxon subject, replacing any prior subject", ( ) => {
const taxon = { id: 42, name: "Foo" };
const state = {
...initialExploreV2State,
subject: { type: "user", user: { id: 1 } },
};
const next = exploreV2Reducer( state, {
type: EXPLORE_V2_ACTION.SET_SUBJECT,
subject: { type: "taxon", taxon },
} );
expect( next.subject ).toEqual( { type: "taxon", taxon } );
} );
it( "preserves location, sortBy, and filters when changing subject", ( ) => {
const state = {
subject: null,
location: {
placeMode: EXPLORE_V2_PLACE_MODE.NEARBY,
lat: 1,
lng: 2,
radius: 3,
},
sortBy: OBSERVATIONS_SORT.MOST_FAVED,
filters: { quality_grade: "research" },
};
const next = exploreV2Reducer( state, {
type: EXPLORE_V2_ACTION.SET_SUBJECT,
subject: { type: "taxon", taxon: { id: 1 } },
} );
expect( next.location ).toEqual( state.location );
expect( next.sortBy ).toBe( state.sortBy );
expect( next.filters ).toEqual( state.filters );
} );
} );
describe( EXPLORE_V2_ACTION.CLEAR_SUBJECT, ( ) => {
it( "clears the selected subject", ( ) => {
const state = {
...initialExploreV2State,
subject: { type: "taxon", taxon: { id: 99 } },
};
const next = exploreV2Reducer( state, { type: EXPLORE_V2_ACTION.CLEAR_SUBJECT } );
expect( next.subject ).toBeNull( );
} );
} );
describe( "location actions", ( ) => {
it( "SET_LOCATION_NEARBY transitions from PLACE and drops place", ( ) => {
const state = {
...initialExploreV2State,
location: {
placeMode: EXPLORE_V2_PLACE_MODE.PLACE,
place: { id: 1 },
},
};
const next = exploreV2Reducer( state, {
type: EXPLORE_V2_ACTION.SET_LOCATION_NEARBY,
lat: 37.5,
lng: -122.1,
radius: 1,
} );
expect( next.location.placeMode ).toBe( EXPLORE_V2_PLACE_MODE.NEARBY );
expect( next.location.lat ).toBe( 37.5 );
expect( next.location.lng ).toBe( -122.1 );
expect( next.location.radius ).toBe( 1 );
expect( next.location.place ).toBeUndefined( );
} );
it( "SET_LOCATION_WORLDWIDE transitions from NEARBY and drops coords", ( ) => {
const state = {
...initialExploreV2State,
location: {
placeMode: EXPLORE_V2_PLACE_MODE.NEARBY,
lat: 1,
lng: 1,
radius: 1,
},
};
const next = exploreV2Reducer( state, {
type: EXPLORE_V2_ACTION.SET_LOCATION_WORLDWIDE,
} );
expect( next.location.placeMode ).toBe( EXPLORE_V2_PLACE_MODE.WORLDWIDE );
expect( next.location.lat ).toBeUndefined( );
expect( next.location.lng ).toBeUndefined( );
expect( next.location.radius ).toBeUndefined( );
} );
it( "SET_LOCATION_PLACE transitions from NEARBY and drops coords", ( ) => {
const state = {
...initialExploreV2State,
location: {
placeMode: EXPLORE_V2_PLACE_MODE.NEARBY,
lat: 1,
lng: 1,
radius: 1,
},
};
const place = { id: 5, display_name: "Oakland" };
const next = exploreV2Reducer( state, {
type: EXPLORE_V2_ACTION.SET_LOCATION_PLACE,
place,
} );
expect( next.location.placeMode ).toBe( EXPLORE_V2_PLACE_MODE.PLACE );
expect( next.location.place ).toEqual( place );
expect( next.location.lat ).toBeUndefined( );
} );
it( "SET_LOCATION_PLACE replaces an existing place", ( ) => {
const state = {
...initialExploreV2State,
location: {
placeMode: EXPLORE_V2_PLACE_MODE.PLACE,
place: { id: 1, display_name: "Oakland" },
},
};
const place = { id: 2, display_name: "Berkeley" };
const next = exploreV2Reducer( state, {
type: EXPLORE_V2_ACTION.SET_LOCATION_PLACE,
place,
} );
expect( next.location.placeMode ).toBe( EXPLORE_V2_PLACE_MODE.PLACE );
expect( next.location.place ).toEqual( place );
} );
it( "SET_LOCATION_NEEDS_PERMISSION transitions from UNINITIALIZED", ( ) => {
const next = exploreV2Reducer( initialExploreV2State, {
type: EXPLORE_V2_ACTION.SET_LOCATION_NEEDS_PERMISSION,
} );
expect( next.location.placeMode ).toBe( EXPLORE_V2_PLACE_MODE.NEEDS_PERMISSION );
} );
it( "SET_LOCATION_NEEDS_PERMISSION preserves subject, sortBy, and filters", ( ) => {
const state = {
subject: { type: "taxon", taxon: { id: 42 } },
location: { placeMode: EXPLORE_V2_PLACE_MODE.UNINITIALIZED },
sortBy: OBSERVATIONS_SORT.MOST_FAVED,
filters: { quality_grade: "research" },
};
const next = exploreV2Reducer( state, {
type: EXPLORE_V2_ACTION.SET_LOCATION_NEEDS_PERMISSION,
} );
expect( next.subject ).toEqual( state.subject );
expect( next.sortBy ).toBe( state.sortBy );
expect( next.filters ).toEqual( state.filters );
} );
it( "preserves subject, sortBy, and filters when changing location", ( ) => {
const state = {
subject: { type: "taxon", taxon: { id: 42 } },
location: { placeMode: EXPLORE_V2_PLACE_MODE.UNINITIALIZED },
sortBy: OBSERVATIONS_SORT.MOST_FAVED,
filters: { quality_grade: "research" },
};
const next = exploreV2Reducer( state, {
type: EXPLORE_V2_ACTION.SET_LOCATION_WORLDWIDE,
} );
expect( next.subject ).toEqual( state.subject );
expect( next.sortBy ).toBe( state.sortBy );
expect( next.filters ).toEqual( state.filters );
} );
} );
describe( EXPLORE_V2_ACTION.SET_SORT, ( ) => {
it( "updates sortBy", ( ) => {
const next = exploreV2Reducer( initialExploreV2State, {
type: EXPLORE_V2_ACTION.SET_SORT,
sortBy: OBSERVATIONS_SORT.DATE_OBSERVED_NEWEST,
} );
expect( next.sortBy ).toBe( OBSERVATIONS_SORT.DATE_OBSERVED_NEWEST );
} );
} );
describe( EXPLORE_V2_ACTION.SET_FILTERS, ( ) => {
it( "replaces filters with the provided object", ( ) => {
const state = {
...initialExploreV2State,
filters: { quality_grade: "research" },
};
const filters = { quality_grade: "needs_id", iconic_taxa: ["Aves"] };
const next = exploreV2Reducer( state, {
type: EXPLORE_V2_ACTION.SET_FILTERS,
filters,
} );
expect( next.filters ).toEqual( filters );
} );
} );
describe( EXPLORE_V2_ACTION.RESET, ( ) => {
it( "returns initial state", ( ) => {
const state = {
...initialExploreV2State,
subject: { type: "taxon", taxon: { id: 1 } },
sortBy: OBSERVATIONS_SORT.MOST_FAVED,
};
const next = exploreV2Reducer( state, { type: EXPLORE_V2_ACTION.RESET } );
expect( next ).toEqual( initialExploreV2State );
} );
} );
} );
describe( "defaultExploreV2Location", ( ) => {
beforeEach( ( ) => {
fetchCoarseUserLocation.mockReset( );
} );
it( "returns NEARBY with radius 1 when a location is available", async ( ) => {
fetchCoarseUserLocation.mockResolvedValueOnce( { latitude: 37.5, longitude: -122.1 } );
const result = await defaultExploreV2Location( );
expect( result ).toEqual( {
placeMode: EXPLORE_V2_PLACE_MODE.NEARBY,
lat: 37.5,
lng: -122.1,
radius: 1,
} );
} );
it( "returns WORLDWIDE when fetchCoarseUserLocation returns null", async ( ) => {
fetchCoarseUserLocation.mockResolvedValueOnce( null );
const result = await defaultExploreV2Location( );
expect( result ).toEqual( { placeMode: EXPLORE_V2_PLACE_MODE.WORLDWIDE } );
} );
} );