Eslint: disallow console logs (#312)

* Remove console.logs; remote useLoggedIn hook and instead use useCurrentUser; closes #310

* Comment out locale test
This commit is contained in:
Amanda Bullington
2022-12-29 10:56:50 -08:00
committed by GitHub
parent 0c4b9a5158
commit ec0a686df6
33 changed files with 80 additions and 161 deletions

View File

@@ -62,7 +62,7 @@ module.exports = {
"space-in-parens": [2, "always"],
"module-resolver/use-alias": 2,
// At least before we start making production builds
"no-console": 0,
"no-console": ["error", { allow: ["warn", "error"] }],
"no-restricted-globals": 0,
"no-param-reassign": 0,
"no-var": 1,

View File

@@ -43,7 +43,7 @@ const fetchUserMe = async ( params: Object = {}, opts: Object = {} ): Promise<an
const { results } = await inatjs.users.me( { ...PARAMS, ...params, ...opts } );
return results[0];
} catch ( e ) {
return handleError( e );
return handleError( e, { throw: true } );
}
};

View File

@@ -85,13 +85,9 @@ const CameraView = ( { camera, device }: Props ): Node => {
}, [neutralZoom, zoom] );
const tapToFocus = async ( { nativeEvent } ) => {
try {
await camera.current.focus( { x: nativeEvent.x, y: nativeEvent.y } );
tapToFocusAnimation.setValue( 1 );
setTappedCoordinates( nativeEvent );
} catch ( e ) {
console.log( e, "couldn't tap to focus" );
}
await camera.current.focus( { x: nativeEvent.x, y: nativeEvent.y } );
tapToFocusAnimation.setValue( 1 );
setTappedCoordinates( nativeEvent );
};
return (

View File

@@ -6,6 +6,7 @@ import {
} from "@react-navigation/drawer";
import type { Node } from "react";
import React from "react";
import useCurrentUser from "sharedHooks/useCurrentUser";
type Props = {
state: any,
@@ -16,6 +17,7 @@ type Props = {
const CustomDrawerContent = ( { ...props }: Props ): Node => {
// $FlowFixMe
const { state, navigation, descriptors } = props;
const currentUser = useCurrentUser( );
return (
<DrawerContentScrollView state={state} navigation={navigation} descriptors={descriptors}>
@@ -31,10 +33,6 @@ const CustomDrawerContent = ( { ...props }: Props ): Node => {
label="projects"
onPress={( ) => navigation.navigate( "projects" )}
/>
<DrawerItem
label="help"
onPress={( ) => console.log( "nav to help/tutorials" )}
/>
<DrawerItem
label="about"
onPress={( ) => navigation.navigate( "about" )}
@@ -48,7 +46,7 @@ const CustomDrawerContent = ( { ...props }: Props ): Node => {
onPress={( ) => navigation.navigate( "network" )}
/>
<DrawerItem
label="login"
label={currentUser ? "logout" : "login"}
onPress={( ) => navigation.navigate( "login" )}
/>
</DrawerContentScrollView>

View File

@@ -18,20 +18,18 @@ import {
type Props = {
item: Object,
handlePress: Function,
reviewedIds: Array<number>,
setReviewedIds: Function
}
const GridItem = ( {
item, handlePress, reviewedIds, setReviewedIds
item, reviewedIds, setReviewedIds
}: Props ): Node => {
const [showLoadingWheel, setShowLoadingWheel] = useState( false );
const commonName = item.taxon && item.taxon.preferred_common_name;
const name = item.taxon ? item.taxon.name : "unknown";
const isSpecies = item.taxon && item.taxon.rank === "species";
const wasReviewed = reviewedIds.includes( item.id );
const onPress = ( ) => handlePress( item );
// TODO: fix whatever funkiness is preventing realm mapTo from correctly
// displaying camelcased item keys on ObservationList
@@ -62,7 +60,6 @@ const GridItem = ( {
return (
<Pressable
onPress={onPress}
style={[
viewStyles.gridItem,
wasReviewed && viewStyles.markReviewed

View File

@@ -23,7 +23,6 @@ const GridView = ( {
const renderGridItem = ( { item } ) => (
<GridItem
item={item}
handlePress={( ) => console.log( "press in identify" )}
reviewedIds={reviewedIds}
setReviewedIds={setReviewedIds}
/>

View File

@@ -13,14 +13,12 @@ const SignUp = (): Node => {
const [username, setUsername] = useState( "" );
const [password, setPassword] = useState( "" );
const register = async () => {
const error = await registerUser(
const register = async ( ) => {
await registerUser(
email,
username,
password
);
console.log( "Register", error );
};
return (

View File

@@ -74,7 +74,6 @@ const AddEvidenceModal = ( {
const onRecordSound = () => {
// TODO - need to implement
console.log( "Record sound" );
};
return (

View File

@@ -17,8 +17,8 @@ import { ActivityIndicator, BackHandler } from "react-native";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { Menu } from "react-native-paper";
import Photo from "realmModels/Photo";
import useCurrentUser from "sharedHooks/useCurrentUser";
import useLocalObservation from "sharedHooks/useLocalObservation";
import useLoggedIn from "sharedHooks/useLoggedIn";
import colors from "styles/tailwindColors";
import AddEvidenceModal from "./AddEvidenceModal";
@@ -53,7 +53,7 @@ const ObsEdit = ( ): Node => {
const navigation = useNavigation( );
const { params } = useRoute( );
const localObservation = useLocalObservation( params?.uuid );
const isLoggedIn = useLoggedIn( );
const currentUser = useCurrentUser( );
const [mediaViewerVisible, setMediaViewerVisible] = useState( false );
const [initialPhotoSelected, setInitialPhotoSelected] = useState( null );
const [showAddEvidenceModal, setShowAddEvidenceModal] = useState( false );
@@ -236,7 +236,7 @@ const ObsEdit = ( ): Node => {
setLoading( false );
setNextScreen( );
}}
disabled={!isLoggedIn}
disabled={!currentUser}
/>
</View>
<AddEvidenceModal

View File

@@ -65,7 +65,6 @@ const OtherDataSection = ( { scrollToInput }: Props ): Node => {
<Button
icon="earth"
mode="text"
onPress={() => console.log( "Pressed" )}
textColor={colors.black}
>
{t( "Geoprivacy" )}
@@ -84,7 +83,6 @@ const OtherDataSection = ( { scrollToInput }: Props ): Node => {
<Button
icon="pot"
mode="text"
onPress={() => console.log( "Pressed" )}
textColor={colors.black}
>
{t( "Organism-is-wild" )}

View File

@@ -15,8 +15,8 @@ type Props = {
}
const ObsCardStats = ( { item, type, view }: Props ): Node => {
const numOfIds = item.identifications?.length || 0;
const numOfComments = item.comments?.length || 0;
const numOfIds = item.identifications?.length || "0";
const numOfComments = item.comments?.length || "0";
const qualityGrade = checkCamelAndSnakeCase( item, "qualityGrade" );
const setIconColor = ( ) => {
@@ -35,11 +35,10 @@ const ObsCardStats = ( { item, type, view }: Props ): Node => {
casual: t( "C" )
};
// console.log( item.viewed, "viewed" );
const renderIdRow = ( ) => (
<View className="flex-row items-center mr-3">
<Icon name="shield" color={setIconColor( )} size={14} />
<Text className="mx-1" style={{ color: setIconColor( ) }}>{numOfIds || 0}</Text>
<Text className="mx-1" style={{ color: setIconColor( ) }}>{numOfIds}</Text>
</View>
);
@@ -51,7 +50,7 @@ const ObsCardStats = ( { item, type, view }: Props ): Node => {
style={{ color: setIconColor( ) }}
testID="ObsList.obsCard.commentCount"
>
{numOfComments || 0}
{numOfComments}
</Text>
</View>
);

View File

@@ -6,13 +6,13 @@ import { RealmContext } from "providers/contexts";
import type { Node } from "react";
import React, { useEffect } from "react";
import useAuthenticatedQuery from "sharedHooks/useAuthenticatedQuery";
import useLoggedIn from "sharedHooks/useLoggedIn";
import useCurrentUser from "sharedHooks/useCurrentUser";
const { useRealm } = RealmContext;
const ObsList = ( ): Node => {
const realm = useRealm( );
const loggedIn = useLoggedIn( );
const currentUser = useCurrentUser( );
const updateParams = {
// TODO: viewed = false is a param in the API v2 docs
@@ -30,7 +30,7 @@ const ObsList = ( ): Node => {
["fetchObservationUpdates"],
optsWithAuth => fetchObservationUpdates( updateParams, optsWithAuth ),
{},
{ enabled: !!loggedIn }
{ enabled: !!currentUser }
);
useEffect( ( ) => {

View File

@@ -3,6 +3,7 @@
import BottomSheet from "components/SharedComponents/BottomSheet";
import type { Node } from "react";
import React from "react";
import useCurrentUser from "sharedHooks/useCurrentUser";
import useLocalObservations from "sharedHooks/useLocalObservations";
import useUploadStatus from "sharedHooks/useUploadStatus";
@@ -11,13 +12,11 @@ import UploadProgressBar from "./UploadProgressBar";
import UploadPrompt from "./UploadPrompt";
type Props = {
isLoggedIn: ?boolean,
hasScrolled: boolean
}
const ObsListBottomSheet = ( {
isLoggedIn, hasScrolled
}: Props ): Node => {
const ObsListBottomSheet = ( { hasScrolled }: Props ): Node => {
const currentUser = useCurrentUser( );
const localObservations = useLocalObservations( );
const { unuploadedObsList, allObsToUpload } = localObservations;
const numOfUnuploadedObs = unuploadedObsList?.length;
@@ -27,7 +26,7 @@ const ObsListBottomSheet = ( {
return null;
}
if ( isLoggedIn === false ) {
if ( !currentUser ) {
return (
<BottomSheet hide={hasScrolled}>
<LoginPrompt />
@@ -42,7 +41,7 @@ const ObsListBottomSheet = ( {
/>
);
}
if ( numOfUnuploadedObs > 0 && isLoggedIn ) {
if ( numOfUnuploadedObs > 0 && currentUser ) {
return (
<BottomSheet hide={hasScrolled}>
<UploadPrompt

View File

@@ -4,6 +4,7 @@ import { View } from "components/styledComponents";
import type { Node } from "react";
import React from "react";
import { Animated } from "react-native";
import useCurrentUser from "sharedHooks/useCurrentUser";
import LoggedOutCard from "./LoggedOutCard";
import Toolbar from "./Toolbar";
@@ -14,17 +15,17 @@ const { diffClamp } = Animated;
const HEADER_HEIGHT = 101;
type Props = {
isLoggedIn: ?boolean,
scrollY: any,
setView: Function
}
const ObsListHeader = ( {
isLoggedIn, scrollY, setView
scrollY, setView
}: Props ): Node => {
const currentUser = useCurrentUser( );
const scrollYClamped = diffClamp( scrollY.current, 0, HEADER_HEIGHT );
if ( isLoggedIn === null ) {
if ( currentUser === null ) {
return <View className="rounded-bl-3xl rounded-br-3xl bg-primary h-24" />;
}
@@ -37,13 +38,10 @@ const ObsListHeader = ( {
return (
// $FlowIgnore
<Animated.View style={[{ transform: [{ translateY }] }]}>
{isLoggedIn
{currentUser
? <UserCard />
: <LoggedOutCard />}
<Toolbar
isLoggedIn={isLoggedIn}
setView={setView}
/>
<Toolbar setView={setView} />
</Animated.View>
);
};

View File

@@ -8,8 +8,8 @@ import React, {
useMemo, useRef, useState
} from "react";
import { Animated, Dimensions } from "react-native";
import useCurrentUser from "sharedHooks/useCurrentUser";
import useLocalObservations from "sharedHooks/useLocalObservations";
import useLoggedIn from "sharedHooks/useLoggedIn";
import EmptyList from "./EmptyList";
import GridItem from "./GridItem";
@@ -34,7 +34,7 @@ const ObservationViews = ( ): Node => {
const localObservations = useLocalObservations( );
const [view, setView] = useState( "list" );
const navigation = useNavigation( );
const isLoggedIn = useLoggedIn( );
const currentUser = useCurrentUser( );
const { observationList } = localObservations;
const [hasScrolled, setHasScrolled] = useState( false );
const [idBelow, setIdBelow] = useState( null );
@@ -76,7 +76,7 @@ const ObservationViews = ( ): Node => {
};
const renderEmptyState = ( ) => {
if ( ( isLoggedIn === false )
if ( ( currentUser === false )
|| ( !isLoading && observationList.length === 0 ) ) {
return <EmptyList />;
}
@@ -95,14 +95,13 @@ const ObservationViews = ( ): Node => {
const renderHeader = useMemo( ( ) => (
<ObsListHeader
isLoggedIn={isLoggedIn}
scrollY={scrollY}
setView={setView}
/>
), [isLoggedIn, scrollY] );
), [scrollY] );
const renderFooter = ( ) => {
if ( isLoggedIn === false ) { return <View />; }
if ( currentUser === false ) { return <View />; }
return (
<InfiniteScrollFooter
view={view}
@@ -111,12 +110,7 @@ const ObservationViews = ( ): Node => {
);
};
const renderBottomSheet = ( ) => (
<ObsListBottomSheet
hasScrolled={hasScrolled}
isLoggedIn={isLoggedIn}
/>
);
const renderBottomSheet = ( ) => <ObsListBottomSheet hasScrolled={hasScrolled} />;
const renderItemSeparator = ( ) => <View className="border border-border" />;

View File

@@ -6,23 +6,21 @@ import type { Node } from "react";
import React, { useContext } from "react";
import { ActivityIndicator } from "react-native";
import IconMaterial from "react-native-vector-icons/MaterialIcons";
import useCurrentUser from "sharedHooks/useCurrentUser";
type Props = {
isLoggedIn: ?boolean,
setView: Function
}
const Toolbar = ( {
isLoggedIn,
setView
}: Props ): Node => {
const Toolbar = ( { setView }: Props ): Node => {
const currentUser = useCurrentUser( );
const obsEditContext = useContext( ObsEditContext );
const loading = obsEditContext?.loading;
const syncObservations = obsEditContext?.syncObservations;
return (
<View className="py-5 flex-row justify-between bg-white">
{isLoggedIn ? (
{currentUser ? (
<Pressable
onPress={syncObservations}
className="mx-3"

View File

@@ -20,7 +20,7 @@ const UploadPrompt = ( {
<Button
level="neutral"
text={t( "UPLOAD-X-OBSERVATIONS", { count: numOfUnuploadedObs } )}
className="mt-5"
className="py-1 mt-5"
onPress={( ) => {
updateUploadStatus( );
uploadObservations( );

View File

@@ -6,12 +6,10 @@ import { useEffect } from "react";
import Observation from "realmModels/Observation";
import useAuthenticatedQuery from "sharedHooks/useAuthenticatedQuery";
import useCurrentUser from "sharedHooks/useCurrentUser";
import useLoggedIn from "sharedHooks/useLoggedIn";
const { useRealm } = RealmContext;
const useInfiniteScroll = ( idBelow: ?number ): boolean => {
const isLoggedIn = useLoggedIn( );
const realm = useRealm( );
const currentUser = useCurrentUser( );
@@ -37,7 +35,7 @@ const useInfiniteScroll = ( idBelow: ?number ): boolean => {
optsWithAuth => searchObservations( params, optsWithAuth ),
{},
{
enabled: !!isLoggedIn
enabled: !!currentUser
}
);
@@ -45,7 +43,7 @@ const useInfiniteScroll = ( idBelow: ?number ): boolean => {
Observation.upsertRemoteObservations( observations, realm );
}, [realm, observations] );
return isLoading;
return currentUser ? isLoading : false;
};
export default useInfiniteScroll;

View File

@@ -71,7 +71,7 @@ const useCameraRollPhotos = (
fetchingPhotos: false
} );
} catch ( e ) {
console.log( e, "couldn't get photos from gallery" );
console.warn( e, "couldn't get photos from gallery" );
}
}, [photoFetchStatus, options] );

View File

@@ -28,7 +28,6 @@ type Props = {
// future we might want to extend this to always show a custom view before
// asking the user for a permission.
const PermissionGate = ( { children, permission, isIOS }: Props ): Node => {
console.log( "PermissionGate" );
const navigation = useNavigation( );
const { t } = useTranslation();
const [result, setResult] = useState(
@@ -54,7 +53,6 @@ const PermissionGate = ( { children, permission, isIOS }: Props ): Node => {
const requestiOSPermissions = async () => {
const r = await request( permission );
console.log( "iOS permission", permission, r );
if ( r === RESULTS.GRANTED ) {
setResult( "granted" );

View File

@@ -54,7 +54,7 @@ const SoundRecorder = ( ): Node => {
} );
setUri( cachedFile );
} catch ( e ) {
console.log( "couldn't start sound recorder:", e );
console.warn( "couldn't start sound recorder:", e );
}
};
@@ -63,7 +63,7 @@ const SoundRecorder = ( ): Node => {
await audioRecorderPlayer.resumeRecorder( );
setStatus( "recording" );
} catch ( e ) {
console.log( "couldn't resume sound recorder:", e );
console.warn( "couldn't resume sound recorder:", e );
}
};
@@ -77,7 +77,7 @@ const SoundRecorder = ( ): Node => {
recordSecs: 0
} );
} catch ( e ) {
console.log( "couldn't stop sound recorder:", e );
console.warn( "couldn't stop sound recorder:", e );
}
};
@@ -95,7 +95,7 @@ const SoundRecorder = ( ): Node => {
} );
} );
} catch ( e ) {
console.log( "can't play recording: ", e );
console.warn( "can't play recording: ", e );
}
};

View File

@@ -111,7 +111,7 @@ const UserProfile = ( ): React.Node => {
<Button
level="primary"
text={t( "Messages" )}
onPress={( ) => console.log( "open messages" )}
onPress={( ) => navigation.navigate( "Messages" )}
testID="UserProfile.messagesButton"
/>
</View>

View File

@@ -238,15 +238,12 @@ class Observation extends Realm.Object {
static markRecordUploaded = async ( recordUUID, type, response, realm ) => {
const { id } = response.results[0];
try {
const record = realm.objectForPrimaryKey( type, recordUUID );
realm?.write( ( ) => {
record.id = id;
record._synced_at = new Date( );
} );
} catch ( e ) {
console.log( e, `couldn't mark ${type} uploaded in realm` );
}
const record = realm.objectForPrimaryKey( type, recordUUID );
realm?.write( ( ) => {
record.id = id;
record._synced_at = new Date( );
} );
};
static uploadToServer = async (

View File

@@ -38,7 +38,7 @@ const fetchPlaceName = async ( lat: number, lng: number ): Promise<?string> => {
if ( results.length === 0 ) { return null; }
return setPlaceName( results );
} catch ( e ) {
console.log( e, "couldn't fetch geocoded position with coordinates: ", lat, lng );
console.warn( e, "couldn't fetch geocoded position with coordinates: ", lat, lng );
return null;
}
};

View File

@@ -13,7 +13,7 @@ const requestLocationPermissions = async ( ): Promise<?string> => {
const permission = await request( PERMISSIONS.IOS.LOCATION_WHEN_IN_USE );
return permission;
} catch ( e ) {
console.log( e, ": error requesting iOS permissions" );
console.warn( e, ": error requesting iOS permissions" );
}
}
if ( Platform.OS === "android" ) {
@@ -21,7 +21,7 @@ const requestLocationPermissions = async ( ): Promise<?string> => {
const permission = await request( PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION );
return permission;
} catch ( e ) {
console.log( e, ": error requesting android permissions" );
console.warn( e, ": error requesting android permissions" );
}
}
return null;
@@ -59,7 +59,7 @@ const fetchUserLocation = async ( ): Promise<?UserLocation> => {
positional_accuracy: coords.accuracy
};
} catch ( e ) {
console.log( e, "couldn't get latLng" );
console.warn( e, "couldn't get latLng" );
}
return null;
};

View File

@@ -24,7 +24,7 @@ const useCoords = ( location: string ): Object => {
longitude: position.lng
} );
} catch ( e ) {
console.log( e, "couldn't fetch coords by location name" );
console.warn( e, "couldn't fetch coords by location name" );
}
};

View File

@@ -45,7 +45,7 @@ const useLocationName = ( latitude: ?number, longitude: ?number ): ?string => {
if ( results.length === 0 || !isCurrent ) { return; }
setLocation( setPlaceName( results ) );
} catch ( e ) {
console.log(
console.warn(
e,
"couldn't fetch geocoded position with coordinates: ",
latitude,

View File

@@ -1,35 +0,0 @@
// @flow
import { getUsername } from "components/LoginSignUp/AuthenticationService";
import { useEffect, useState } from "react";
const useLoggedIn = ( ): ?boolean => {
const [isLoggedIn, setIsLoggedIn] = useState( null );
useEffect( ( ) => {
let isCurrent = true;
const fetchLoggedInUser = async ( ) => {
try {
const currentUserLogin = await getUsername( );
if ( !isCurrent ) { return; }
if ( currentUserLogin ) {
setIsLoggedIn( true );
} else {
setIsLoggedIn( false );
}
} catch ( e ) {
if ( !isCurrent ) { return; }
console.log( "Couldn't check whether user logged in:", e.message );
}
};
fetchLoggedInUser( );
return ( ) => {
isCurrent = false;
};
}, [] );
return isLoggedIn;
};
export default useLoggedIn;

View File

@@ -17,7 +17,7 @@ const useUserLocation = ( ): Object => {
const permission = await request( PERMISSIONS.IOS.LOCATION_WHEN_IN_USE );
return permission;
} catch ( e ) {
console.log( e, ": error requesting iOS permissions" );
console.warn( e, ": error requesting iOS permissions" );
}
}
return null;
@@ -43,7 +43,7 @@ const useUserLocation = ( ): Object => {
};
// TODO: set geolocation fetch error
const failure = error => console.log( error.code, error.message );
const failure = error => console.warn( error.code, error.message );
const options = { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 };

View File

@@ -65,18 +65,21 @@ describe( "MyObservations", ( ) => {
} );
} );
it( "should be Spanish if signed in user's locale is Spanish", async ( ) => {
const mockSpanishUser = factory( "LocalUser", {
locale: "es"
} );
expect( mockSpanishUser.locale ).toEqual( "es" );
await signIn( mockSpanishUser );
const { queryByText } = renderAppWithComponent( <ObsList /> );
await waitFor( ( ) => {
expect( queryByText( /X-Observations/ ) ).toBeFalsy( );
expect( queryByText( / Observaciones/ ) ).toBeTruthy( );
} );
} );
// commenting this out since there's another PR specifically for these locale tests
it.todo( "should be Spanish if signed in user's locale is Spanish" );
// it( "should be Spanish if signed in user's locale is Spanish", async ( ) => {
// const mockSpanishUser = factory( "LocalUser", {
// locale: "es"
// } );
// expect( mockSpanishUser.locale ).toEqual( "es" );
// await signIn( mockSpanishUser );
// const { queryByText } = renderAppWithComponent( <ObsList /> );
// await waitFor( ( ) => {
// expect( queryByText( /X-Observations/ ) ).toBeFalsy( );
// expect( queryByText( / Observaciones/ ) ).toBeTruthy( );
// } );
// } );
it.todo( "should change to es when local user locale is en but remote user locale is es" );
} );
} );

View File

@@ -32,11 +32,6 @@ jest.mock( "sharedHooks/useLocationName", ( ) => ( {
default: ( ) => mockLocationName
} ) );
jest.mock( "sharedHooks/useLoggedIn", ( ) => ( {
__esModule: true,
default: ( ) => true
} ) );
jest.mock( "@react-navigation/native", ( ) => {
const actualNav = jest.requireActual( "@react-navigation/native" );
return {

View File

@@ -27,11 +27,6 @@ jest.mock( "sharedHooks/useCurrentUser", ( ) => ( {
default: ( ) => true
} ) );
jest.mock( "sharedHooks/useLoggedIn", ( ) => ( {
__esModule: true,
default: ( ) => true
} ) );
jest.mock(
"sharedHooks/useLocalObservations",
( ) => ( {

View File

@@ -10,11 +10,6 @@ jest.mock( "inaturalistjs" );
const mockTaxon = factory( "RemoteTaxon" );
jest.mock( "../../../../src/sharedHooks/useLoggedIn", ( ) => ( {
__esModule: true,
default: ( ) => true
} ) );
jest.mock( "@react-navigation/native", ( ) => {
const actualNav = jest.requireActual( "@react-navigation/native" );
return {