diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 8cb75d971..7997a9b79 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -1477,12 +1477,12 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost: d3f49c53809116a5d38da093a8aa78bf551aed09
BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3
- DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
+ DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953
FasterImage: 60d0750ddbcefff0070c4c17309c2d1d6cc650f0
FBLazyVector: 9f533d5a4c75ca77c8ed774aced1a91a0701781e
FBReactNativeSpec: 40b791f4a1df779e7e4aa12c000319f4f216d40a
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
- glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
+ glog: c5d68082e772fa1c511173d6b30a9de2c05a69a2
hermes-engine: 39589e9c297d024e90fe68f6830ff86c4e01498a
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
MMKV: 506311d0494023c2f7e0b62cc1f31b7370fa3cfb
diff --git a/src/components/Developer/UiLibrary/Misc.js b/src/components/Developer/UiLibrary/Misc.js
index 4d53f5c23..d57cb8a62 100644
--- a/src/components/Developer/UiLibrary/Misc.js
+++ b/src/components/Developer/UiLibrary/Misc.js
@@ -344,11 +344,7 @@ const Misc = (): Node => {
Iconic Taxon Chooser
}
onTaxonChosen={taxon => console.log( "taxon selected:", taxon )}
/>
diff --git a/src/components/Explore/Explore.js b/src/components/Explore/Explore.js
index 357c1d3db..b7f2bd919 100644
--- a/src/components/Explore/Explore.js
+++ b/src/components/Explore/Explore.js
@@ -45,6 +45,7 @@ const exploreViewIcon = {
type Props = {
closeFiltersModal: Function,
count: Object,
+ filterByIconicTaxonUnknown: Function,
hideBackButton: boolean,
isOnline: boolean,
loadingStatus: boolean,
@@ -61,6 +62,7 @@ type Props = {
const Explore = ( {
closeFiltersModal,
count,
+ filterByIconicTaxonUnknown,
hideBackButton,
isOnline,
loadingStatus,
@@ -256,6 +258,7 @@ const Explore = ( {
{
useParams( );
- const updateTaxon = ( taxon: Object ) => {
- if ( !taxon ) {
- dispatch( {
- type: EXPLORE_ACTION.CHANGE_TAXON_NONE,
- taxon: null
- } );
- } else {
- dispatch( {
- type: EXPLORE_ACTION.CHANGE_TAXON,
- taxon,
- taxonId: taxon?.id,
- taxonName: taxon?.preferred_common_name || taxon?.name
- } );
- }
- };
-
const updateLocation = ( place: Object ) => {
if ( place === "worldwide" ) {
dispatch( {
@@ -113,13 +97,16 @@ const ExploreContainerWithContext = ( ): Node => {
closeFiltersModal={closeFiltersModal}
count={count}
hideBackButton={false}
+ filterByIconicTaxonUnknown={
+ () => dispatch( { type: EXPLORE_ACTION.FILTER_BY_ICONIC_TAXON_UNKNOWN } )
+ }
isOnline={isOnline}
loadingStatus={loadingStatus}
openFiltersModal={openFiltersModal}
queryParams={queryParams}
showFiltersModal={showFiltersModal}
updateCount={updateCount}
- updateTaxon={updateTaxon}
+ updateTaxon={taxon => dispatch( { type: EXPLORE_ACTION.CHANGE_TAXON, taxon } )}
updateLocation={updateLocation}
updateUser={updateUser}
updateProject={updateProject}
diff --git a/src/components/Explore/Header/Header.js b/src/components/Explore/Header/Header.js
index 355280fa1..604d8e451 100644
--- a/src/components/Explore/Header/Header.js
+++ b/src/components/Explore/Header/Header.js
@@ -48,6 +48,7 @@ const Header = ( {
const theme = useTheme( );
const { state, numberOfFilters } = useExplore( );
const { taxon } = state;
+ const iconicTaxonNames = state.iconic_taxa || [];
const placeGuess = state.place_guess;
const [showTaxonSearch, setShowTaxonSearch] = useState( false );
const [showLocationSearch, setShowLocationSearch] = useState( false );
@@ -71,11 +72,11 @@ const Header = ( {
/>
) }
- {taxon
+ {( taxon || iconicTaxonNames.indexOf( "unknown" ) >= 0 )
? (
setShowTaxonSearch( true )}
diff --git a/src/components/Explore/MapView.js b/src/components/Explore/MapView.js
index 5601a3ce0..406adf71c 100644
--- a/src/components/Explore/MapView.js
+++ b/src/components/Explore/MapView.js
@@ -28,7 +28,7 @@ type Props = {
const MapView = ( {
observations,
- queryParams: tileMapParams
+ queryParams
}: Props ): Node => {
const { t } = useTranslation( );
const { isDebug } = useDebugMode( );
@@ -48,6 +48,14 @@ const MapView = ( {
updateMapBoundaries
} = useMapLocation( );
+ const tileMapParams = {
+ ...queryParams
+ };
+ // Tile queries never need these params
+ delete tileMapParams.return_bounds;
+ delete tileMapParams.order;
+ delete tileMapParams.orderBy;
+
return (
diff --git a/src/components/Explore/Modals/ExploreFiltersModal.js b/src/components/Explore/Modals/ExploreFiltersModal.js
index 632031c9e..03a45076d 100644
--- a/src/components/Explore/Modals/ExploreFiltersModal.js
+++ b/src/components/Explore/Modals/ExploreFiltersModal.js
@@ -9,6 +9,7 @@ import FilterModal from "./FilterModal";
type Props = {
showModal: boolean,
closeModal: Function,
+ filterByIconicTaxonUnknown: Function,
updateTaxon: Function,
updateLocation: Function,
updateUser: Function,
@@ -18,6 +19,7 @@ type Props = {
const ExploreFiltersModal = ( {
showModal,
closeModal,
+ filterByIconicTaxonUnknown,
updateTaxon,
updateLocation,
updateUser,
@@ -31,6 +33,7 @@ const ExploreFiltersModal = ( {
modal={(
{t( "TAXON" )}
- {taxon
+ {( taxon || ( iconicTaxonNames || [] ).indexOf( "unknown" ) >= 0 )
? (
-
+
)
@@ -704,16 +707,21 @@ const FilterModal = ( {
{
if ( taxonName === "unknown" ) {
- updateTaxon( );
+ if ( ( iconicTaxonNames || [] ).indexOf( taxonName ) >= 0 ) {
+ updateTaxon( null );
+ } else {
+ filterByIconicTaxonUnknown();
+ }
+ } else if ( taxon?.name?.toLowerCase() === taxonName ) {
+ updateTaxon( null );
} else {
const selectedTaxon = realm
?.objects( "Taxon" )
.filtered( "name CONTAINS[c] $0", taxonName );
- const iconicTaxon
- = selectedTaxon.length > 0
+ const iconicTaxon = selectedTaxon.length > 0
? selectedTaxon[0]
: null;
updateTaxon( iconicTaxon );
diff --git a/src/components/Explore/RootExploreContainer.js b/src/components/Explore/RootExploreContainer.js
index 3489416f4..5a06cb87d 100644
--- a/src/components/Explore/RootExploreContainer.js
+++ b/src/components/Explore/RootExploreContainer.js
@@ -36,22 +36,6 @@ const RootExploreContainerWithContext = ( ): Node => {
const [showFiltersModal, setShowFiltersModal] = useState( false );
- const updateTaxon = ( taxon: Object ) => {
- if ( !taxon ) {
- dispatch( {
- type: EXPLORE_ACTION.CHANGE_TAXON_NONE,
- taxon: null
- } );
- } else {
- dispatch( {
- type: EXPLORE_ACTION.CHANGE_TAXON,
- taxon,
- taxonId: taxon?.id,
- taxonName: taxon?.preferred_common_name || taxon?.name
- } );
- }
- };
-
const updateLocation = ( place: Object ) => {
if ( place === "worldwide" ) {
dispatch( {
@@ -144,13 +128,16 @@ const RootExploreContainerWithContext = ( ): Node => {
closeFiltersModal={closeFiltersModal}
count={count}
hideBackButton
+ filterByIconicTaxonUnknown={
+ () => dispatch( { type: EXPLORE_ACTION.FILTER_BY_ICONIC_TAXON_UNKNOWN } )
+ }
isOnline={isOnline}
loadingStatus={loadingStatus}
openFiltersModal={openFiltersModal}
queryParams={queryParams}
showFiltersModal={showFiltersModal}
updateCount={updateCount}
- updateTaxon={updateTaxon}
+ updateTaxon={taxon => dispatch( { type: EXPLORE_ACTION.CHANGE_TAXON, taxon } )}
updateLocation={updateLocation}
updateUser={updateUser}
updateProject={updateProject}
diff --git a/src/components/ObsEdit/IdentificationSection.js b/src/components/ObsEdit/IdentificationSection.js
index 7a3ab1a2b..00b14059a 100644
--- a/src/components/ObsEdit/IdentificationSection.js
+++ b/src/components/ObsEdit/IdentificationSection.js
@@ -10,6 +10,7 @@ import {
TaxonResult
} from "components/SharedComponents";
import { View } from "components/styledComponents";
+import { capitalize } from "lodash";
import { RealmContext } from "providers/contexts";
import type { Node } from "react";
import React, { useCallback, useEffect } from "react";
@@ -40,19 +41,15 @@ const IdentificationSection = ( {
const navigation = useNavigation( );
const realm = useRealm( );
- const identification = currentObservation?.taxon;
+ const identTaxon = currentObservation?.taxon;
const hasPhotos = currentObservation?.observationPhotos?.length > 0;
- const hasIdentification = identification && identification.rank_level !== 100;
+ const hasIdentification = identTaxon && identTaxon.rank_level !== 100;
- const showIconicTaxonChooser = !identification
- || identification.name === identification.iconic_taxon_name
- || identification.isIconic
- || identification.name === "Life";
-
- const onTaxonChosen = taxonName => updateObservationKeys( {
- taxon: realm?.objects( "Taxon" ).filtered( "name CONTAINS[c] $0", taxonName )[0]
- } );
+ const showIconicTaxonChooser = !identTaxon
+ || identTaxon.name === identTaxon.iconic_taxon_name
+ || identTaxon.isIconic
+ || identTaxon.name === "Life";
const navToSuggestions = useCallback( ( ) => {
if ( hasPhotos ) {
@@ -83,20 +80,20 @@ const IdentificationSection = ( {
@@ -104,8 +101,26 @@ const IdentificationSection = ( {
accessibilityLabel={t( "View-suggestions" )}
/>
)}
- taxon={identification}
- onTaxonChosen={onTaxonChosen}
+ chosen={
+ identTaxon
+ ? [identTaxon.name.toLowerCase()]
+ : []
+ }
+ onTaxonChosen={taxonName => {
+ const capitalizedTaxonName = capitalize( taxonName );
+ if (
+ // user chose unknown
+ taxonName === "unknown"
+ // user tapped the selected iconic taxon to unselect
+ || identTaxon?.name === capitalizedTaxonName
+ ) {
+ updateObservationKeys( { taxon: undefined } );
+ } else {
+ const newTaxon = realm?.objects( "Taxon" )
+ .filtered( "name = $0", capitalizedTaxonName )[0];
+ updateObservationKeys( { taxon: newTaxon } );
+ }
+ }}
/>
);
@@ -120,14 +135,14 @@ const IdentificationSection = ( {
)}
- {identification && (
+ {identTaxon && (
{
const { t } = useTranslation( );
- const [selectedIcon, setSelectedIcon] = useState( null );
- const iconicTaxa = useIconicTaxa( { reload: false } );
- const isIconic = taxon?.id && iconicTaxa.filtered( `id = ${taxon?.id}` );
-
- useEffect( ( ) => {
- if ( !isIconic ) { return; }
- setSelectedIcon( taxon.name.toLowerCase( ) );
- }, [isIconic, taxon] );
-
- useEffect( ( ) => {
- // reset selectedIcon state when navigating multiple observations
- // on ObsEdit screen
- if ( !taxon && selectedIcon ) {
- setSelectedIcon( null );
- }
- }, [taxon, selectedIcon] );
-
- const renderIcon = useCallback( ( { item } ) => {
- const isSelected = selectedIcon === item;
+ const renderIcon = useCallback( ( { item: iconicTaxonName } ) => {
+ const isSelected = chosen.indexOf( iconicTaxonName ) >= 0;
return (
{
- setSelectedIcon( item );
- onTaxonChosen( item );
+ onTaxonChosen( iconicTaxonName );
}}
color={isSelected && colors.white}
accessibilityLabel={
- t( "Iconic-taxon-name", { iconicTaxon: item } )
+ t( "Iconic-taxon-name", { iconicTaxon: iconicTaxonName } )
}
accessibilityHint={
- t( "Selects-iconic-taxon-X-for-identification", { iconicTaxon: item } )
+ t( "Selects-iconic-taxon-X-for-identification", { iconicTaxon: iconicTaxonName } )
}
/>
);
- }, [onTaxonChosen, t, selectedIcon] );
+ }, [
+ chosen,
+ onTaxonChosen,
+ t
+ // selectedIcon
+ ] );
const renderHeader = useCallback( ( ) => {
if ( before ) {
diff --git a/src/providers/ExploreContext.tsx b/src/providers/ExploreContext.tsx
index 1cd0b4e24..56ec2e563 100644
--- a/src/providers/ExploreContext.tsx
+++ b/src/providers/ExploreContext.tsx
@@ -1,6 +1,7 @@
/* eslint-disable no-unused-vars */
/* eslint-disable no-shadow */
import { t } from "i18next";
+import { isEqual } from "lodash";
import * as React from "react";
import { LatLng } from "react-native-maps";
@@ -12,6 +13,7 @@ export enum EXPLORE_ACTION {
CHANGE_SORT_BY = "CHANGE_SORT_BY",
CHANGE_TAXON = "CHANGE_TAXON",
DISCARD = "DISCARD",
+ FILTER_BY_ICONIC_TAXON_UNKNOWN = "FILTER_BY_ICONIC_TAXON_UNKNOWN",
RESET = "RESET",
SET_DATE_OBSERVED_ALL = "SET_DATE_OBSERVED_ALL",
SET_DATE_OBSERVED_EXACT = "SET_DATE_OBSERVED_EXACT",
@@ -160,65 +162,68 @@ interface PLACE {
type ExploreProviderProps = {children: React.ReactNode}
type State = {
- verifiable: boolean,
+ casual: boolean,
+ created_d1: string | null | undefined,
+ created_d2: string | null | undefined,
+ created_on: string | null | undefined,
+ d1: string | null | undefined,
+ d2: string | null | undefined,
+ dateObserved: DATE_OBSERVED,
+ dateUploaded: DATE_UPLOADED,
+ establishmentMean: ESTABLISHMENT_MEAN,
+ hrank: TAXONOMIC_RANK | undefined | null,
+ iconic_taxa: string[] | undefined,
+ lat?: number,
+ lng?: number,
+ lrank: TAXONOMIC_RANK | undefined | null,
+ mapBoundaries: MapBoundaries | undefined,
+ media: MEDIA,
+ months: number[] | null | undefined,
+ needsID: boolean,
+ nelat?: number,
+ nelng?: number,
+ observed_on: string | null | undefined,
+ photoLicense: PHOTO_LICENSE,
+ place: PLACE | null | undefined,
+ place_guess: string,
+ place_id: number | null | undefined,
+ // TODO: technically this is not any Object but a "Project"
+ // and should be typed as such (e.g., in realm model)
+ project: Object | undefined,
+ project_id: number | undefined,
+ radius?: number,
+ researchGrade: boolean,
return_bounds: boolean,
+ reviewedFilter: REVIEWED,
+ sortBy: SORT_BY,
+ swlat?: number,
+ swlng?: number,
// TODO: technically this is not any Object but a "Taxon"
// and should be typed as such (e.g., in realm model)
taxon: Object | undefined,
taxon_id: number | undefined,
- place: PLACE | null | undefined,
- place_id: number | null | undefined,
- place_guess: string,
- user_id: number | undefined,
// TODO: technically this is not any Object but a "User"
// and should be typed as such (e.g., in realm model)
user: Object | undefined,
- project_id: number | undefined,
- // TODO: technically this is not any Object but a "Project"
- // and should be typed as such (e.g., in realm model)
- project: Object | undefined,
- sortBy: SORT_BY,
- researchGrade: boolean,
- needsID: boolean,
- casual: boolean,
- hrank: TAXONOMIC_RANK | undefined | null,
- lrank: TAXONOMIC_RANK | undefined | null,
- dateObserved: DATE_OBSERVED,
- observed_on: string | null | undefined,
- d1: string | null | undefined,
- d2: string | null | undefined,
- months: number[] | null | undefined,
- dateUploaded: DATE_UPLOADED,
- created_on: string | null | undefined,
- created_d1: string | null | undefined,
- created_d2: string | null | undefined,
- media: MEDIA,
- establishmentMean: ESTABLISHMENT_MEAN,
- wildStatus: WILD_STATUS,
- reviewedFilter: REVIEWED,
- photoLicense: PHOTO_LICENSE,
- mapBoundaries: MapBoundaries
+ user_id: number | undefined,
+ verifiable: boolean,
+ wildStatus: WILD_STATUS
}
type Action = {type: EXPLORE_ACTION.RESET}
| {type: EXPLORE_ACTION.DISCARD, snapshot: State}
| {type: EXPLORE_ACTION.SET_USER, user: Object, userId: number, storedState: State}
| {
type: EXPLORE_ACTION.CHANGE_TAXON,
- taxon: Object,
- taxonId: number,
- taxonName: string,
+ taxon: { id: number },
storedState: State
}
- | {
- type: EXPLORE_ACTION.CHANGE_TAXON_NONE,
- iconic_taxa: Object
- }
+ | { type: EXPLORE_ACTION.FILTER_BY_ICONIC_TAXON_UNKNOWN }
| {type: EXPLORE_ACTION.SET_EXPLORE_LOCATION, exploreLocation: Object}
| {
type: EXPLORE_ACTION.SET_PLACE,
place: PLACE,
placeId: number,
- placeName: string,
+ placeGuess: string,
lat: number,
lng: number,
radius: number,
@@ -272,26 +277,29 @@ const calculatedFilters = {
// Sort by: is NOT a filter criteria, but should return to default state when reset is pressed
const defaultFilters = {
...calculatedFilters,
- user: undefined,
- project: undefined,
- sortBy: SORT_BY.DATE_UPLOADED_NEWEST,
- observed_on: undefined,
+ created_d1: undefined,
+ created_d2: undefined,
+ created_on: undefined,
d1: undefined,
d2: undefined,
+ iconic_taxa: undefined,
months: undefined,
- created_on: undefined,
- created_d1: undefined,
- created_d2: undefined
+ observed_on: undefined,
+ project: undefined,
+ sortBy: SORT_BY.DATE_UPLOADED_NEWEST,
+ user: undefined
};
-const initialState = {
+const initialState: State = {
...defaultFilters,
+ mapBoundaries: undefined,
+ place: undefined,
+ place_guess: "",
+ place_id: undefined,
+ return_bounds: true,
taxon: undefined,
taxon_id: undefined,
- place_id: undefined,
- place_guess: "",
- verifiable: true,
- return_bounds: true
+ verifiable: true
};
// Checks if the date is in the format XXXX-XX-XX
@@ -315,6 +323,9 @@ async function defaultExploreLocation( ) {
};
}
+// Note: if an action needs to remove a value from state, do not `delete` it.
+// Instead, set it to undefined. This helps us detect changes to the default
+// state
function exploreReducer( state: State, action: Action ) {
switch ( action.type ) {
case EXPLORE_ACTION.RESET:
@@ -324,43 +335,56 @@ function exploreReducer( state: State, action: Action ) {
};
case EXPLORE_ACTION.DISCARD:
return action.snapshot;
- case EXPLORE_ACTION.CHANGE_TAXON:
- return {
+ case EXPLORE_ACTION.CHANGE_TAXON: {
+ const newState = {
...state,
...action.storedState,
- taxon: action.taxon,
- taxon_id: action.taxonId,
- iconic_taxa: []
+ iconic_taxa: undefined
};
- case EXPLORE_ACTION.CHANGE_TAXON_NONE:
- return {
+ if ( action.taxon ) {
+ newState.taxon = action.taxon;
+ newState.taxon_id = action.taxon.id;
+ } else {
+ newState.taxon = undefined;
+ newState.taxon_id = undefined;
+ }
+ return newState;
+ }
+ // Every iconic taxon filter is essentially a taxon filter... except
+ // "unknown", which is a search for observations not associated with an
+ // iconic taxon (either they have no taxon or their taxon is not a
+ // descendant of an iconic taxon), so it needs its own special action.
+ // We could also redo this so all iconic taxon filters remove the taxon
+ // and add iconic_taxa.
+ case EXPLORE_ACTION.FILTER_BY_ICONIC_TAXON_UNKNOWN: {
+ const newState = {
...state,
- taxon: "Unknown",
- taxon_id: null,
- iconic_taxa: ["unknown"]
+ iconic_taxa: ["unknown"],
+ taxon: undefined,
+ taxon_id: undefined
};
+ return newState;
+ }
case EXPLORE_ACTION.SET_EXPLORE_LOCATION:
return {
...state,
...action.exploreLocation
};
case EXPLORE_ACTION.SET_PLACE:
- // eslint-disable-next-line no-case-declarations
- const placeState = {
+ return {
...state,
...action.storedState,
- place: action.place,
- place_id: action.placeId,
- place_guess: action.placeGuess,
lat: action.lat,
lng: action.lng,
- radius: action.radius
+ nelat: undefined,
+ nelng: undefined,
+ place: action.place,
+ place_guess: action.placeGuess,
+ place_id: action.placeId,
+ radius: action.radius,
+ swlat: undefined,
+ swlng: undefined
};
- delete placeState.swlat;
- delete placeState.swlng;
- delete placeState.nelat;
- delete placeState.nelng;
- return placeState;
case EXPLORE_ACTION.SET_USER:
return {
...state,
@@ -512,15 +536,14 @@ function exploreReducer( state: State, action: Action ) {
reviewedFilter: action.reviewedFilter
};
case EXPLORE_ACTION.SET_MAP_BOUNDARIES: {
- const newState = {
+ return {
...state,
- ...action.mapBoundaries
+ ...action.mapBoundaries,
+ lat: undefined,
+ lng: undefined,
+ place_id: undefined,
+ radius: undefined
};
- delete newState.place_id;
- delete newState.lat;
- delete newState.lng;
- delete newState.radius;
- return newState;
}
case EXPLORE_ACTION.USE_STORED_STATE:
return {
@@ -544,9 +567,12 @@ const ExploreProvider = ( { children }: ExploreProviderProps ) => {
if ( !snapshot ) {
return false;
}
- return Object.keys( snapshot ).some( key => snapshot[key] !== state[key] );
+ return Object.keys( snapshot ).some( key => !isEqual( snapshot[key], state[key] ) );
};
- const differsFromSnapshot: boolean = checkSnapshot();
+ const differsFromSnapshot: boolean = React.useMemo(
+ checkSnapshot,
+ [state, snapshot]
+ );
const discardChanges = () => {
if ( !snapshot ) {
diff --git a/tests/unit/components/SharedComponents/IconicTaxonChooser.test.js b/tests/unit/components/SharedComponents/IconicTaxonChooser.test.js
index 0db2d7414..336ed3f3b 100644
--- a/tests/unit/components/SharedComponents/IconicTaxonChooser.test.js
+++ b/tests/unit/components/SharedComponents/IconicTaxonChooser.test.js
@@ -18,7 +18,7 @@ describe( "IconicTaxonChooser", () => {
name: "Aves"
} );
expect(
-
+
).toBeAccessible( );
} );
@@ -28,7 +28,7 @@ describe( "IconicTaxonChooser", () => {
iconic_taxon_name: "Plantae"
} );
- render( );
+ render( );
const plantButton = await screen.findByTestId(
`IconicTaxonButton.${mockTaxon.name.toLowerCase( )}`
diff --git a/tests/unit/providers/ExploreContext.test.js b/tests/unit/providers/ExploreContext.test.js
index d70208fe8..005e10389 100644
--- a/tests/unit/providers/ExploreContext.test.js
+++ b/tests/unit/providers/ExploreContext.test.js
@@ -40,5 +40,36 @@ describe( "ExploreContext", ( ) => {
expect( reducedState.radius ).toBeUndefined( );
} );
} );
+ describe( EXPLORE_ACTION.CHANGE_TAXON, ( ) => {
+ it( "should remove iconic_taxa", ( ) => {
+ const taxon = factory( "RemoteTaxon" );
+ const initialState = { iconic_taxa: ["Animalia"] };
+ const reducedState = exploreReducer( initialState, {
+ type: EXPLORE_ACTION.CHANGE_TAXON,
+ taxon,
+ taxonId: taxon.id
+ } );
+ expect( reducedState.iconic_taxa ).toBeUndefined( );
+ } );
+ it( "should extract an id from a taxon", ( ) => {
+ const taxon = factory( "RemoteTaxon" );
+ const initialState = { };
+ const reducedState = exploreReducer( initialState, {
+ type: EXPLORE_ACTION.CHANGE_TAXON,
+ taxon
+ } );
+ expect( reducedState.taxon_id ).toEqual( taxon.id );
+ } );
+ it( "should remove an id from a blank taxon", ( ) => {
+ const taxon = factory( "RemoteTaxon" );
+ const initialState = { taxon, taxon_id: taxon.id };
+ const reducedState = exploreReducer( initialState, {
+ type: EXPLORE_ACTION.CHANGE_TAXON,
+ taxon: null
+ } );
+ // expect( reducedState ).not.toHaveProperty( "taxon_id" );
+ expect( reducedState.taxon_id ).toBeUndefined( );
+ } );
+ } );
} );
} );