Add activity indicator to fetch location (#639)

* Add activity indicator to fetch location

* Add e2e location mock (#643)

Adds a mock for fetchUserLocation intended to be used with e2e tests. `MOCK_MODE=e2e` must be in the ENV for this to work.

---------

Co-authored-by: Ken-ichi Ueda <kenichi.ueda@gmail.com>

---------

Co-authored-by: Johannes Klein <johannes.t.klein@gmail.com>
Co-authored-by: Ken-ichi Ueda <kenichi.ueda@gmail.com>
This commit is contained in:
Amanda Bullington
2023-05-25 17:13:31 -07:00
committed by GitHub
parent 5d1644bde3
commit cc78f06b04
9 changed files with 66 additions and 18 deletions

View File

@@ -34,14 +34,14 @@ module.exports = {
binaryPath: `android/app/build/outputs/apk/debug/${apkFilenamePrefix}-debug.apk`,
testBinaryPath: `android/app/build/outputs/apk/androidTest/debug/${apkFilenamePrefix}-debug-androidTest.apk`,
build:
"cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd ..",
"(cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug)",
},
"android.release": {
type: "android.apk",
binaryPath: `android/app/build/outputs/apk/release/${apkFilenamePrefix}-release.apk`,
testBinaryPath: `android/app/build/outputs/apk/androidTest/release/${apkFilenamePrefix}-release-androidTest.apk`,
build:
"cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release && cd ..",
"(cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release)",
},
},
devices: {

View File

@@ -127,7 +127,7 @@ jobs:
# Start the Android e2e tests with extensive logging and screen captures for failing tests
- name: Android Detox
run: npm run e2e:test:android -- --debug-synchronization 500 --take-screenshots failing --record-videos failing -l trace
run: npm run e2e:test:android -- --take-screenshots failing --record-videos failing -l debug
# The artifacts for the failing tests are available for download on github.com on the page of the individual actions run
- name: Store Detox artifacts on test failure

View File

@@ -88,6 +88,11 @@ jobs:
JWT_ANONYMOUS_API_SECRET: ${{ secrets.JWT_ANONYMOUS_API_SECRET }}
run: printf 'API_URL=https://stagingapi.inaturalist.org/v2\nOAUTH_API_URL=https://staging.inaturalist.org\nJWT_ANONYMOUS_API_SECRET=%s\nOAUTH_CLIENT_ID=%s\nOAUTH_CLIENT_SECRET=%s\nE2E_TEST_USERNAME=%s\nE2E_TEST_PASSWORD=%s\n' "JWT_ANONYMOUS_API_SECRET" "$OAUTH_CLIENT_ID" "$OAUTH_CLIENT_SECRET" "$E2E_TEST_USERNAME" "$E2E_TEST_PASSWORD" > .env
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable
# This will be available for all subsequent steps
- name: Set MOCK_MODE to e2e
run: echo "MOCK_MODE=e2e" >> "$GITHUB_ENV"
# Install prerequisites for detox and build app, and test
- run: brew tap wix/brew
- run: brew install applesimutils
@@ -96,7 +101,7 @@ jobs:
run: npm run e2e:build:ios
- name: Run e2e test
run: npm run e2e:test:ios -- --cleanup --debug-synchronization 200 --take-screenshots failing --record-videos failing -l trace
run: npm run e2e:test:ios -- --cleanup --take-screenshots failing --record-videos failing -l debug
# The artifacts for the failing tests are available for download on github.com on the page of the individual actions run
- name: Store Detox artifacts on test failure

View File

@@ -10,6 +10,17 @@ unless File.exist?( appfile_path )
NO_APPFILE_ERROR
end
forbidden_env_vars = [
"MOCK_MODE"
]
forbidden_env_vars.each do | env_var |
next unless ENV[env_var].to_s.size.positive?
UI.abort_with_message! <<~NO_ENV_ERROR.gsub( /\s+/, " " ).strip
ENV is set #{env_var}. Remove the value from your ENV before running fastlane.
NO_ENV_ERROR
end
required_env_vars = [
"IOS_PROVISIONING_PROFILE_NAME",
"IOS_SHARE_BUNDLE_ID",

View File

@@ -25,7 +25,10 @@ module.exports = ( async () => {
},
resolver: {
assetExts: assetExts.filter( ext => ext !== "svg" ),
sourceExts: [...sourceExts, "svg"]
sourceExts:
process.env.MOCK_MODE === "e2e"
? ["e2e-mock.js", ...sourceExts, "svg"]
: [...sourceExts, "svg"]
}
};
} )();

View File

@@ -15,12 +15,12 @@
"postinstall": "husky install && patch-package",
"translate": "node src/i18n/i18ncli.js build",
"e2e:android": "npm run e2e:build:android && npm run e2e:test:android",
"e2e:build:android": "npx detox build --configuration android.release",
"e2e:build:ios": "npx detox build --configuration ios.release",
"e2e:build:android": "MOCK_MODE=e2e npx detox build --configuration android.release",
"e2e:build:ios": "MOCK_MODE=e2e npx detox build --configuration ios.release",
"e2e:build": "npm run e2e:build:ios && npm run e2e:build:android",
"e2e:ios": "npm run e2e:build:ios && npm run e2e:test:ios",
"e2e:test:android": "npx detox test --configuration android.release",
"e2e:test:ios": "npx detox test --configuration ios.release",
"e2e:test:android": "MOCK_MODE=e2e npx detox test --configuration android.release",
"e2e:test:ios": "MOCK_MODE=e2e npx detox test --configuration ios.release",
"e2e:test": "npm run e2e:test:ios && npm run e2e:test:android",
"e2e": "npm run e2e:build && npm run e2e:test",
"icons": "./scripts/update-icon-font.sh"

View File

@@ -1,7 +1,7 @@
// @flow
import { Body3, DateTimePicker, INatIcon } from "components/SharedComponents";
import { Pressable } from "components/styledComponents";
import { Pressable, View } from "components/styledComponents";
import { ObsEditContext } from "providers/contexts";
import type { Node } from "react";
import React, { useContext, useState } from "react";
@@ -45,9 +45,11 @@ const DatePicker = ( { currentObservation }: Props ): Node => {
onPress={openModal}
className="flex-row flex-nowrap items-center"
>
<INatIcon size={14} name="clock-outline" />
<View className="w-[30px] items-center mr-1">
<INatIcon size={14} name="clock-outline" />
</View>
{/* $FlowIgnore */}
<Body3 testID="ObsEdit.time" className={`ml-5 ${!displayDate( ) && "color-warningRed"}`}>
<Body3 testID="ObsEdit.time" className={!displayDate( ) && "color-warningRed"}>
{displayDate( ) || t( "Add-Date-Time" )}
</Body3>
</Pressable>

View File

@@ -17,7 +17,7 @@ import React, {
useCallback,
useContext, useEffect, useRef, useState
} from "react";
import { useTheme } from "react-native-paper";
import { ActivityIndicator, useTheme } from "react-native-paper";
import Photo from "realmModels/Photo";
import useLocationFetching from "sharedHooks/useLocationFetching";
import useTranslation from "sharedHooks/useTranslation";
@@ -179,9 +179,18 @@ const EvidenceSection = ( ): Node => {
photoUris={photoUris}
handleAddEvidence={handleAddEvidence}
/>
<View className="flex-row flex-nowrap my-4">
<INatIcon size={14} name="map-marker-outline" />
<Pressable accessibilityRole="button" className="ml-5" onPress={navToLocationPicker}>
<Pressable
accessibilityRole="button"
className="flex-row flex-nowrap my-3"
onPress={navToLocationPicker}
>
<View className="w-[30px] items-center mr-1">
{shouldFetchLocation && <ActivityIndicator />}
<View className={shouldFetchLocation && "bottom-5"}>
<INatIcon size={14} name="map-marker-outline" />
</View>
</View>
<View>
{displayPlaceName( ) && (
<Body3 className={( !latitude || !longitude ) && "color-warningRed"}>
{displayPlaceName( )}
@@ -191,8 +200,9 @@ const EvidenceSection = ( ): Node => {
<Body4 className={( !latitude || !longitude ) && "color-warningRed"}>
{displayLocation( )}
</Body4>
</Pressable>
</View>
</View>
</Pressable>
<DatePicker currentObservation={currentObservation} />
</View>
);

View File

@@ -0,0 +1,17 @@
type UserLocation = {
latitude: number,
longitude: number,
positional_accuracy: number,
place_guess: string
}
const fetchUserLocation = async ( ): Promise<UserLocation> => new Promise( resolve => {
setTimeout( ( ) => resolve( {
place_guess: "San Francisco",
latitude: -122.4194,
longitude: 37.7749,
positional_accuracy: 5
} ), 1000 );
} );
export default fetchUserLocation;