* only return observations from useLocalObs
* remove unnecessary var
* export unsync'd filter
* remove obsoleted numUnuploadedObservations zustand state
* tests, typo
* fix tests
* add sync fields to keypaths & depp array
* consistent naming
* handle only ids downstream
* switch over to useIds
* restore ids return
* memoize realm mapping result
* extract realm hooks mocks into factory-available helper
* reapply to myobsresults
* reapply to myobsresults
* go back to wrapped ids for list parity
* fix test
* restrict mocked prop for more accurate MyObsSimple test
* comment cleanup
* fix fake timer flake w/ corrected setup
Claude:
1. withAnimatedTimeTravelEnabled({ skipFakeTimers: true }) does NOT call jest.useFakeTimers(), but still calls jest.setSystemTime(new Date(0)) in beforeEach — which requires fake timers.
2. Both SoundRecorder.test.js and PhotoDeletionExisting.test.js (and ObsEdit.test.js) call global.timeTravel(300) inside waitFor, which also requires fake timers.
3. Tests pass flakily when fake timers accidentally leak from another test file running in the same Jest worker. When they don't leak, timeTravel throws.
4. FadeInView is fully mocked to a plain View (instant) and Reanimated uses setUpTests(), so the 300ms timeTravel isn't actually advancing any real animation — it's just broken.
The fix: guard setSystemTime with the same check, and remove the timeTravel(300) calls from waitFor in tests that use skipFakeTimers: true.
* fix remaining time travel uses
* reset / restore timers to fix leaking fake timers
* Move one broken test and switch back to toBeVisible
* Remove comments
* Move without changes
* Add helper function
* Call mock helper in beforeAll
* Add fileName to mock assets
* Refactor navigateToPhotoImporter into helper
* Use fake timers and time travel
* File move without changes
* Add import
* Update addObsBottomSheet.js
* Refactor navigation steps into new helpers
* Add layout setup
* Use skipFakeTimers here
* Remove setup
* Replace final expectation
* Add mock for Mortal in a new helper file
* Sort imports
* Remove superfluous act
* Move file without changes
* Add time travel to final expect
* Use Mortal mock
* Change one test expect
TODO: is this still the same behaviour tested, toBeNull can be of other reasons as well?
* Refactor nav to Standard camera into new helpers
* Replace fireEvent with userEvent
* Update imports
* Move file without changesUpdate firebase mock
* Move file without changes
* Add Mortal mock
* Use toBeVisible again
* Use toBeVisible
* Refactor nav to AI camera into helpers
* Refactor take photo and na into helpers
* Refactor an action of the two previous combined actions
* Somehow there were two identical describe
* Wrong order
* No longer needed
* Refactor last expect of this test into helper
* Use global time travel here
* Remove import
* Move file without changes
* Use toBeVisible again
* Use Mortal mock
* Re-use already made helper fct here
* Fix imports
* Move file without changes
* Enable animated time travel
* Use toBeVisible
* Add time travel to last expects
* Remove double checks for being on the correct screen
* Move file without changes
* Add fileName to mock assets
* Switch back to toBeVisible
* Enable animated time travel
* Add time travel to last expect
* Re-use new navigation helper
* Add mock for InteractionManager
* Move file without changes
* Use toBeVisible again
* Add InteractionManager mock
* Add animate time travel
* Missing import
* Remove from previous commit
* Add helper shell
* Move the Save button press
* Move missing evidence sheet dismissal
* Update MyObservations.test.js
* Set screen after photo import
* Remove import
* Sort imports
* Add a mock for ImagePicker
* Navigate to PhotoImported instead of No evidence option
Does not matter for this test where the new obs comes from
* Re-use helper fct
* Arg name
* Disable lint
* Move file without changes
* Replace with new helper fct
* Enable animated time travel
* Replace also below with new helper
* Move fct call
* Use toBeVisible again
* Use toBeVisible again
* Use toBeVisible again with different find strategy
* Remove trip through Suggestions for this test
* Add InteractionManager mock
* Move beforeEach
* Move function call
* Re-use new helper function
* Handle saveOptions
* Missing imports
* Add helper function
* Wait for toolbar helper
* Wait for the element like we did before this PR
* Wait for one more element
* Update PhotoImport.test.js
* Comment out optional wait
* Rename arg
* File move without changes
* Re-use new helper function
* Re-use new helper function
* Use toBeVisible again
* Enable animated time travel
* Add a new find
* New helper fct
* Remove local version of confirm
* New take photo helper does more, so restrict to not confirm the photo yet here
* Update PhotoDeletion.test.js
* Update PhotoDeletion.test.js
* Remove fake timers
* Missing imports
* Add Mortal mock
* Update PhotoDeletion.test.js
* Update PhotoDeletion.test.js
* Copy PhotoDeletion test into new file to split out tests about existing photos
* Remove other todo test
* Add InteractionManager mock
* Remove Mortal mock
* Remove new photo test
* Delete new photo test
* Remove existing photo test
* Remove existing photo test
* Remove helper fct
* Remove import
* This should not have been deleted
* Refactor to use new helpers to create an obs with photo and wait on ObsEdit
* Add the part until we wait on ObsEdit
* Remove double await
* Rename describe
* This was wrongly inserted here
* Wait with time travel to be on camera
* At this point we have two photos, so tap on first one
* Update PhotoDeletionExisting.test.js
* Move beforeEach
* That was wrong, we should not have taken a second photo
* Remove cv mock
* Add import
* Add import
* Add import
* Remove location mock
* Update PhotoDeletionExisting.test.js
* Move file without changes
* Switch back to toBeVisible again
* Re-use new helper fct
* Add Mortal mock
* Move broken tests without changes
* Mock Mortal
* Use toBeVisible again
* Re-use new helper fct
* Enable animated time trael
* Camera needs different layout state
* This was pressing twice
* Remove tiny local helper
* Re-use local helper
* Remove unused code
* Remove ignore Paths
Yay
* Remove unused helper
* Update react-native-fs.ts
* Move fct out of try/catch
* Revert "Move fct out of try/catch"
This reverts commit f9a138e0dd.
* Only have find text in try catch
* Add mock for useObject
* Remove broken test
---------
Co-authored-by: Johannes Klein <17345891+jtklein@users.noreply.github.com>
* Add react-native-legal
* Update package-lock.json
* Update Podfile.lock
* Git ignore the results of the license gathering script
* Run "npx react-native legal-generate"
* Update .gitignore
* Type navigation in About
* Add link to About to show licenses
* Update strings.ftl
* Add step into build process
* Add jest mock
* Add npm script for legal-generate
* Update project.pbxproj
* Update package.json
* Update AppDelegate.mm
* Update Podfile
* Update .gitignore
* Update link-inat-model-files.sh
* Add plist file to project
* Update project.pbxproj
* Add analytics package
* Update project.pbxproj
* Update PrivacyInfo.xcprivacy
* Basic screen tracking
* Basic button press logging to firebase
* Update package-lock.json
* Update Podfile.lock
* Add Android setup
* Update .gitignore
* Add analytics mock
* Ignore rubocop warning here
* Create GoogleService-Info.example.plist
* Create google-services.example.json
* Add instructions to set up Firebase configs
* Update e2e_ios.yml
* Update e2e_android.yml
* Better plural
* Use specific XCode version in e2e CI
* Update GoogleService-Info.example.plist
* Revert "Update GoogleService-Info.example.plist"
This reverts commit 0bc0ed4862.
* We need an actual real app id or we get a crash during app start
* My bad, we do need both files for building
* Also set API key
* Add comments
* Add comment
* Update Podfile.lock
* Revert "Use specific XCode version in e2e CI"
This reverts commit cbd63d1b5d.
* Upgrade helper: package.json
* Upgrade helper: gems
* Upgrade helper: Android
* Update AppDelegate
* Fix error in compiling
* Update package-lock.json
* Update Podfile.lock
* Update package-lock.json
* Update Podfile.lock
* Remove no longer needed mock
* Comment out entire test and not only the expect call
* Most other unit tests use this render helper function that
wraps the component in the entire app.
* Mock react-native exports as esModule
* Update .flowconfig
* Update Gemfile
* Revert "Comment out entire test and not only the expect call"
This reverts commit 8785f81529.
* Don't require TS extensions in imports
* Resolve all import extension errors
* Remove file extension from import paths used in mocks
* Remove .d of type definition file paths
* Remove .d of type definition file and import as type
---------
Co-authored-by: Johannes Klein <johannes.t.klein@gmail.com>
* Repair integration test
* Repair Explore.test.js
* Move no longer broken test
* Mock the fadeInView that does screen transitions in tests
* Mock another fade in view
* Update navigators and create util for tabstack navigation
* Changes for react navigation 7
* Refactor to use navigateToTabStack throughout app
* Add comment about unmountOnBlur
* Get all unit tests passing; remove navutils & mock HeaderBackButton
* Fix animation issues in tests
* Temporarily remove parts of tests with back functionality
* Fix tests
* Delete ios/iNaturalistReactNative.xcodeproj/project.pbxproj
* Fix pbxproj
* Code cleanup; minimize unnecessary changes
* Fix tests
* Downgrade react-native-screens to v4.4.0 (#2918)
react-native-screens version 4.5.0 increases the react native version that it supports to 0.74.0+ (https://github.com/software-mansion/react-native-screens/pull/2613/files). So, by using 4.4.0 we are still able to build the app on Android as we are still on 0.73 for now (have tested and it works).
Have not seen any effect on the changes related to the latest react-navigation versions.
* Make requested changes
* Speed up Explore nearby tile loading (#2912)
* Create a performance tracker to show urltile load time in debug mode
* Set default radius to 1km, not 50km
* Code cleanup & TypeScript definitions
* Fix TypeError
* Address eslint error
* Make github actions happy
---------
Co-authored-by: Johannes Klein <johannes.t.klein@gmail.com>
* New Crowdin translations by GitHub Action (#2920)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
* MOB-690 - Add error context to 401 errors (#2921)
* MOB-690 - Add error context to 401 errors
* Add Object.defineProperty like in the other error classes
* Add logger line
* Also throw 401 error if the error object has no response property
---------
Co-authored-by: Yaron Budowski <budowski@gmail.com>
* v1.0.4+164
* Rebase with latest version of RN screens. Remove unused code and packages, add eslint package for TS, suppress TS errors (#2924)
* New Crowdin translations by GitHub Action (#2926)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
* New Crowdin translations by GitHub Action (#2929)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
* Use 3 separate initial routes for tabs; hide animations on drawer screens
* Fix test
---------
Co-authored-by: Johannes Klein <johannes.t.klein@gmail.com>
Co-authored-by: Ken-ichi <kenichi.ueda@gmail.com>
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
Co-authored-by: Yaron Budowski <budowski@gmail.com>
* Add debounce to Button to make sure users can't double tap any buttons / navigate twice
* Fix tests by mocking the Button component with a quick debounce
* Fix#2212 - use physical volume buttons to capture photo
* Fixed tests (mocking VolumeManager)
* Fixed tests (mocking VolumeManager)
* #2212 - physical volume buttons for camera capture - also in AI camera
* #2212 - additional fixes for AI camera
* Update pods
* Update pods
---------
Co-authored-by: Amanda Bullington <albullington@gmail.com>
Note that offsetting the onboarding images ended up being a bit hard. We're
mostly doing so with a cropped version of one of the images.
Closes#1906
Also tried to de-flake some tests:
* Use fake timers when possible
* Ensure time travel helper doesn't un-fake our timers
* Wait for time travel helper to finish so changes don't happen outside of
act
* Stop mocking useCurrentUser in integration tests; that's app code and should
not be mocked when integrating all parts of the app; instead use signIn /
signOut helpers
* Remove unnecessary direct uses of act()
* Mocked some inatjs calls to prevent React Query complaints about undefined
query return values
* Close onboarding before all e2e tests
---------
Co-authored-by: Ken-ichi Ueda <kenichi.ueda@gmail.com>
* Use system locale on install
* Check for system locale when app comes to foreground (required in Android
b/c app doesn't get restarted when system locale changes)
* Create a constant of SUPPORTED_LOCALES in loadTranslations.js
* Restart app on sign out
* Use existing transaction when writing to Realm if available (might also
consider an approach that waits for the existing transaction to complete)
* Make value returned by useCurrentUser actually reactive
Closes#2243
* Catch and squelch "Network request failed" errors that happen during logging itself (#1639)
* Log around RNSI access to resolve when/where those errors occur (#1639)
* Log around JWT retrieval to resolve when/where JWT missing errors occur (#2155)
* Disable animations on tab bar screens
* Fade in pages accessible from the tab bar
* Add fade in view to stack navigator screens
* Use time travel to step through frames of animation for SoundRecorder
* Use time travel to fix all tests with fade in navigation
* Nav fix
* Get a few mocks working in __mocks__ folder
* Move more mocks into __mocks__
* Move mocks
* Move zustand mock
* Add more mocks to __mocks__
* More mocks
* Move more files to __mocks__ and audit existing mocks
* Mock react navigation in __mocks__
* Restore test to help with imports after jest env torn down
* Add fake timer to integration test with userEvent
* Add RN paper mock
* Write some failing navigation tests for MyObs navigation
* Add one more failing test to check for empty screen after all obs are deleted
* Update what happens on blur
* Changes to focus effect
* Revert "Changes to focus effect"
This reverts commit c779504cdf.
* Test: toolbar status reset when user leaves screen
* Unmock useFocusEffect in Jest; fix tests
* Minor nav mocking updates
* Fix import
* Refactor to use watchPosition
* Update useWatchPosition with permissions/retry
* Replace useUserLocation with useWatchPosition and fix tests; return userLocation from watch position hook
* Only update observation keys when there's an observation
* Improve TypeScript definitions
* Revert TypeScript commit
* Revert "Only update observation keys when there's an observation"
This reverts commit a4cd17a513.
* Code cleanup: make useWatchPosition more modular
* Code cleanup; location permission in ObsEdit instead of subcomponent
* Use correct accuracy in Camera photos
* Camera fixes
* Fixes to watching position in ObsEdit
* Fix useWatchPosition tests
* Fix tests
* Make sure state updates when renavigating to OsEdit; test fixes
* Restore photo deletion
* Rename methods for accessing media files
* Added integration test for photo deletion
* Cleaned up some accessibility labels
Closes#1429
* (Re-)Fix bug where shared photo got deleted before it could be used
* Only run cleanup when MyObs has focus
* Only run cleanup once a minute
* Only delete files that are a day old or more
* Refactor upload code into hook and zustand slice
* Create a single source of truth for toolbar and individual progress
* Fix unit tests
* Fix more tests
* Continue trying to simplify upload progress and status code
* Continued overhaul of upload code
* Fix exclamation point in Toolbar
* Fix total toolbar progress
* Fix tests
* Update snapshots
* Code cleanup
* Update MyObs test
* Fix most tests by not deleting realm
* Keep attempting to make toolbar text clear in subsequent tests
* Mock Zustand and reset state after all tests
In theory this should make testing with Zustand simpler. The real kicker is
that resetting state will fail if we're not careful about manually replacing
nested objects in Zustand state updates.
* Bugfix: removeAllFilesFromDirectory works with File objects, not raw paths
* Update status text when uploads canceled
* Only show red exclamation rotating icon after all uploads attempted
* Fix progress bar with zustand nested object
* Fix toolbar progress
---------
Co-authored-by: Ken-ichi Ueda <kenichi.ueda@gmail.com>
* Catch 401 errors when we try to fetch remotely deleted obs for signed out
users
* Skip the check to see if a user is a friend on UserProfile when signed out
* Replace uses of RNFS.unlink() with a wrapper that ignores errors about files
not existing
* Tried to get safeRealmWrite to preserve error type before re-throwing
* Refactor image-resizer into helper function for easy logging
* Create a folder for computerVisionSuggestions
* Display iNat app directories in Debug
* Delete old images from computerVisionSuggestions/ when navigating away from Suggestions
* Fix online suggestions API call
* Fix tests
* Clear computer vision directory when landing on Suggestions screen
* Update camera and plugin packages
* Remove one patch
* Replace deprecated function
* Update runAsync patch
Removing this patch leads to non-functioning frame processors in release builds. Contrary to what the original issue's solution states.