From 14705b526fafad4755107810294777f957dbf7fa Mon Sep 17 00:00:00 2001 From: Steve Galili Date: Tue, 16 Jan 2024 16:51:48 +0100 Subject: [PATCH] feat: add flashlist (#57) * add flashlist * e2e fix(1) * e2e fix(2) bundle install fix * e2e fix(2) bundle install fix * e2e fix(3) install java version 17 * e2e fix(3) install java version 17 * remove test warnings * increase to api-level 33 e2e test * maestro cloud addition to e2e testing in ci/cd * maestro cloud addition to e2e testing in ci/cd 2 * maestro cloud addition to e2e testing in ci/cd 3 * maestro cloud addition to e2e testing in ci/cd 4 * create .gradle folder and global properties * correct working folder for android activities * correct working folder for android activities * correct working folder for android activities * correct app-file * correct app-file * initial build_ios + correct app-file destin. * initial build_ios + correct app-file destin. * correct xcode version * correct xcode version * correct xcode version * correct xcode version * correct xcode version * build android unified in one job * correct apk name * try to find apk location * use absolute url * e2e name .maestro dir --- .eslintrc.js | 2 +- .github/actions/bootstrap/action.yml | 89 --------------- .github/workflows/e2e-testing.yml | 99 +++++----------- {e2e => .maestro}/flow.yaml | 12 +- {e2e => .maestro}/setup.js | 0 {e2e => .maestro/subFlows}/goBackHome.yaml | 0 Gemfile | 3 + Gemfile.lock | 106 +++++++++--------- __tests__/FlatList.test.tsx | 50 ++++----- __tests__/Home.test.tsx | 10 +- android/app/build.gradle | 8 ++ ios/Podfile.lock | 6 + .../project.pbxproj | 6 + package.json | 11 +- yarn.lock | 31 ++++- 15 files changed, 178 insertions(+), 255 deletions(-) delete mode 100644 .github/actions/bootstrap/action.yml rename {e2e => .maestro}/flow.yaml (91%) rename {e2e => .maestro}/setup.js (100%) rename {e2e => .maestro/subFlows}/goBackHome.yaml (100%) diff --git a/.eslintrc.js b/.eslintrc.js index a33cc3b..c72c85e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,5 +1,5 @@ module.exports = { root: true, extends: '@react-native', - ignorePatterns: ['e2e/', 'coverage'], + ignorePatterns: ['.maestro/', 'coverage'], }; diff --git a/.github/actions/bootstrap/action.yml b/.github/actions/bootstrap/action.yml deleted file mode 100644 index 220164d..0000000 --- a/.github/actions/bootstrap/action.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: 'Bootstrap' -description: 'Bootstrap Dependencies' -runs: - using: 'composite' - steps: - - run: echo "IMAGE=${ImageOS}-${ImageVersion}" >> $GITHUB_ENV - shell: bash - - - uses: actions/setup-node@v3 - if: ${{ env.INSTALL_NODE == 'true' }} - with: - node-version: 18.x - cache: 'yarn' - - - name: Install Yarn Dependencies - if: ${{ env.INSTALL_NODE == 'true' }} - run: yarn install --immutable - shell: bash - - - name: Cache pods - uses: actions/cache@v3 - if: ${{ env.INSTALL_PODS == 'true' }} - with: - path: ios/Pods - key: ${{ env.IMAGE }}-pods-${{ hashFiles('ios/Podfile.lock') }} - restore-keys: | - ${{ runner.os }}-pods- - - - uses: ruby/setup-ruby@v1 - with: - ruby-version: 3.1 - bundler-cache: true - - - name: Cache Gradle - if: ${{ env.INSTALL_JAVA == 'true' }} - uses: actions/cache@v3 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ env.IMAGE }}-gradle-${{ hashFiles('*.gradle*', 'gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - - uses: actions/setup-java@v3 - if: ${{ env.INSTALL_JAVA == 'true' }} - with: - distribution: 'zulu' - java-version: '11' - check-latest: true - - - name: Install pods - if: ${{ env.INSTALL_PODS == 'true' }} - run: bundle exec fastlane pod_install - shell: bash - - # Retrieve the cached emulator snapshot - - uses: actions/cache@v3 - if: ${{ env.INSTALL_ANDROID_EMULATOR == 'true' }} - id: avd-cache - with: - path: | - ~/.android/avd/* - ~/.android/adb* - key: ${{ env.IMAGE }}-android-emulator - - # Required for Maestro on iOS - - uses: actions/setup-python@v4.3.0 - if: ${{ env.INSTALL_PYTHON == 'true' }} - with: - python-version: 3.8 - cache: 'pip' - - # Required to run E2E testing - - name: Install Maestro - if: ${{ env.INSTALL_MAESTRO == 'true' }} - shell: bash - run: | - if [ "${{ env.INSTALL_PYTHON }}" = "true" ]; then - brew install facebook/fb/idb-companion - pip install fb-idb - fi - env MAESTRO_VERSION="1.29.0" curl -Ls 'https://get.maestro.mobile.dev' | bash - echo "$HOME/.maestro/bin" >> $GITHUB_PATH - - # Required to capture Android video during E2E testing - - name: Install FFmpeg - if: ${{ env.INSTALL_FFMPEG == 'true' }} - uses: FedericoCarboni/setup-ffmpeg@v2 diff --git a/.github/workflows/e2e-testing.yml b/.github/workflows/e2e-testing.yml index 0b61c42..9cfd19b 100644 --- a/.github/workflows/e2e-testing.yml +++ b/.github/workflows/e2e-testing.yml @@ -10,82 +10,45 @@ concurrency: jobs: build_android: - name: Build Android - timeout-minutes: 60 + name: Build & Test Android + timeout-minutes: 15 runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: ./.github/actions/bootstrap - timeout-minutes: 15 - env: - INSTALL_NODE: true - INSTALL_JAVA: true - - - name: Build - run: bundle exec fastlane build_android - - name: Upload .apk - uses: actions/upload-artifact@v3 + - name: Set up JDK 17 + uses: actions/setup-java@v3 with: - name: apk - path: '**/dist/*.apk' - - test_android: - name: Test Android - needs: build_android - timeout-minutes: 100 - runs-on: macos-latest - steps: - - uses: actions/checkout@v3 - - uses: ./.github/actions/bootstrap - timeout-minutes: 15 - env: - INSTALL_NODE: true - INSTALL_FFMPEG: true - INSTALL_MAESTRO: true - INSTALL_ANDROID_EMULATOR: true + distribution: 'zulu' + java-version: '17' + check-latest: true - - name: Download .apk - uses: actions/download-artifact@v3 + - name: Setup Node + uses: actions/setup-node@v3 with: - name: apk + node-version: '18' - - name: Create AVD Snapshot - if: steps.avd-cache.outputs.cache-hit != 'true' - uses: reactivecircus/android-emulator-runner@v2 - with: - api-level: 30 - arch: x86_64 - target: google_apis - profile: pixel_5 - force-avd-creation: false - avd-name: test - ram-size: 8192M - disk-size: 2048M - emulator-boot-timeout: 1000 - emulator-options: -no-window -no-boot-anim -no-audio -no-snapshot-load -gpu swiftshader_indirect - script: echo 'AVD snapshot is generated and will be cached for the future runs.' + - name: Run Yarn Install + run: yarn install - - name: Test - uses: reactivecircus/android-emulator-runner@v2 - with: - api-level: 30 - arch: x86_64 - target: google_apis - profile: pixel_5 - force-avd-creation: false - avd-name: test - ram-size: 8192M - disk-size: 2048M - emulator-boot-timeout: 1000 - emulator-options: -no-window -no-boot-anim -no-audio -no-snapshot-load -gpu swiftshader_indirect - script: bundle exec fastlane test_android + - name: Build Release APK + run: cd android && ./gradlew assembleRelease - - uses: actions/upload-artifact@v3 - if: failure() + - name: Upload to Maestro Cloud + uses: mobile-dev-inc/action-maestro-cloud@v1.8.0 with: - name: Android Test Data - path: | - **/fastlane/recordings - ~/.maestro/tests - + api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }} + app-file: /home/runner/work/react-native-testing/react-native-testing/android/app/build/outputs/apk/release/app-release.apk + + build_ios: + name: Build IOS + timeout-minutes: 60 + runs-on: macos-latest + steps: + - name: Archive iOS app + run: echo "To be implemented" +# - uses: actions/checkout@v2 +# - uses: maxim-lobanov/setup-xcode@v1.6.0 +# with: +# xcode-version: 14.2.0 +# - run: cd ios && xcodebuild -project reactnativetesting.xcodeproj -scheme reactnativetesting -destination 'platform=iOS Simulator,name=iPhone 11' diff --git a/e2e/flow.yaml b/.maestro/flow.yaml similarity index 91% rename from e2e/flow.yaml rename to .maestro/flow.yaml index e993249..042f0b7 100644 --- a/e2e/flow.yaml +++ b/.maestro/flow.yaml @@ -12,7 +12,7 @@ appId: com.reactnativetesting - assertVisible: ${output.screens.counter.currentCountIs1} - tapOn: ${output.screens.counter.decrementButton} - assertVisible: ${output.screens.counter.currentCountIs0} -- runFlow: goBackHome.yaml +- runFlow: ./subFlows/goBackHome.yaml # test Login screen flow - tapOn: ${output.screens.home.loginButton} - tapOn: ${output.screens.login.usernamePlaceholder} @@ -27,7 +27,7 @@ appId: com.reactnativetesting - tapOn: ${output.screens.easyButton.button} - assertVisible: ${output.screens.easyButton.modalDescription} - tapOn: ${output.screens.easyButton.modalDismissButton} -- runFlow: goBackHome.yaml +- runFlow: ./subFlows/goBackHome.yaml # test Video screen flow - tapOn: ${output.screens.home.videoButton} - assertVisible: ${output.screens.video.playerA11yId} @@ -35,14 +35,14 @@ appId: com.reactnativetesting - tapOn: ${output.screens.video.pauseStartButton} - tapOn: ${output.screens.video.exitFullScreen} - tapOn: ${output.screens.video.pauseStartButton} -- runFlow: goBackHome.yaml +- runFlow: ./subFlows/goBackHome.yaml # test Modal screen flow - tapOn: ${output.screens.home.modalButton} - tapOn: ${output.screens.modal.showButton} - assertVisible: ${output.screens.modal.description} - tapOn: ${output.screens.modal.hideButton} - assertVisible: ${output.screens.modal.showButton} -- runFlow: goBackHome.yaml +- runFlow: ./subFlows/goBackHome.yaml # flat list screen flow - tapOn: ${output.screens.home.flatListButton} - assertVisible: ${output.screens.flatList.firstItemPage1} @@ -52,12 +52,12 @@ appId: com.reactnativetesting - scrollUntilVisible: element: ${output.screens.flatList.fifthItemPage2} direction: "DOWN" -- runFlow: goBackHome.yaml +- runFlow: ./subFlows/goBackHome.yaml # ListWithFetch screen flow - tapOn: ${output.screens.home.listWithFetchButton} - assertVisible: ${output.screens.listWitchFetch.firstItemId} - scrollUntilVisible: element: ${output.screens.listWitchFetch.fifteenthItemId} direction: "DOWN" -- runFlow: goBackHome.yaml +- runFlow: ./subFlows/goBackHome.yaml - assertVisible: ${output.screens.home.title} diff --git a/e2e/setup.js b/.maestro/setup.js similarity index 100% rename from e2e/setup.js rename to .maestro/setup.js diff --git a/e2e/goBackHome.yaml b/.maestro/subFlows/goBackHome.yaml similarity index 100% rename from e2e/goBackHome.yaml rename to .maestro/subFlows/goBackHome.yaml diff --git a/Gemfile b/Gemfile index da59192..5079236 100644 --- a/Gemfile +++ b/Gemfile @@ -6,3 +6,6 @@ ruby ">= 2.6.10" gem 'cocoapods', '~> 1.13' gem 'fastlane' gem 'activesupport', '>= 6.1.7.3', '< 7.1.0' + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/Gemfile.lock b/Gemfile.lock index 4620532..dda000b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,42 +3,43 @@ GEM specs: CFPropertyList (3.0.6) rexml - activesupport (7.0.5) + activesupport (6.1.7.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - addressable (2.8.4) + zeitwerk (~> 2.3) + addressable (2.8.6) public_suffix (>= 2.0.2, < 6.0) algoliasearch (1.27.5) httpclient (~> 2.8, >= 2.8.3) json (>= 1.5.1) artifactory (3.0.15) atomos (0.1.3) - aws-eventstream (1.2.0) - aws-partitions (1.822.0) - aws-sdk-core (3.181.0) - aws-eventstream (~> 1, >= 1.0.2) + aws-eventstream (1.3.0) + aws-partitions (1.876.0) + aws-sdk-core (3.190.1) + aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.651.0) - aws-sigv4 (~> 1.5) + aws-sigv4 (~> 1.8) jmespath (~> 1, >= 1.6.1) - aws-sdk-kms (1.71.0) - aws-sdk-core (~> 3, >= 3.177.0) + aws-sdk-kms (1.75.0) + aws-sdk-core (~> 3, >= 3.188.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.134.0) - aws-sdk-core (~> 3, >= 3.181.0) + aws-sdk-s3 (1.142.0) + aws-sdk-core (~> 3, >= 3.189.0) aws-sdk-kms (~> 1) - aws-sigv4 (~> 1.6) - aws-sigv4 (1.6.0) + aws-sigv4 (~> 1.8) + aws-sigv4 (1.8.0) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) claide (1.1.0) - cocoapods (1.12.1) + cocoapods (1.14.3) addressable (~> 2.8) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.12.1) + cocoapods-core (= 1.14.3) cocoapods-deintegrate (>= 1.0.3, < 2.0) - cocoapods-downloader (>= 1.6.0, < 2.0) + cocoapods-downloader (>= 2.1, < 3.0) cocoapods-plugins (>= 1.0.0, < 2.0) cocoapods-search (>= 1.0.0, < 2.0) cocoapods-trunk (>= 1.6.0, < 2.0) @@ -50,8 +51,8 @@ GEM molinillo (~> 0.8.0) nap (~> 1.0) ruby-macho (>= 2.3.0, < 3.0) - xcodeproj (>= 1.21.0, < 2.0) - cocoapods-core (1.12.1) + xcodeproj (>= 1.23.0, < 2.0) + cocoapods-core (1.14.3) activesupport (>= 5.0, < 8) addressable (~> 2.8) algoliasearch (~> 1.0) @@ -62,7 +63,7 @@ GEM public_suffix (~> 4.0) typhoeus (~> 1.0) cocoapods-deintegrate (1.0.5) - cocoapods-downloader (1.6.3) + cocoapods-downloader (2.1) cocoapods-plugins (1.0.0) nap cocoapods-search (1.0.1) @@ -85,7 +86,7 @@ GEM escape (0.0.4) ethon (0.16.0) ffi (>= 1.15.0) - excon (0.103.0) + excon (0.109.0) faraday (1.10.3) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -114,8 +115,8 @@ GEM faraday-retry (1.0.3) faraday_middleware (1.2.0) faraday (~> 1.0) - fastimage (2.2.7) - fastlane (2.214.0) + fastimage (2.3.0) + fastlane (2.218.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -136,33 +137,34 @@ GEM google-apis-playcustomapp_v1 (~> 0.1) google-cloud-storage (~> 1.31) highline (~> 2.0) + http-cookie (~> 1.0.5) json (< 3.0.0) jwt (>= 2.1.0, < 3) mini_magick (>= 4.9.4, < 5.0.0) multipart-post (>= 2.0.0, < 3.0.0) naturally (~> 2.2) - optparse (~> 0.1.1) + optparse (>= 0.1.1) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) security (= 0.1.3) simctl (~> 1.6.3) terminal-notifier (>= 2.0.0, < 3.0.0) - terminal-table (>= 1.4.5, < 2.0.0) + terminal-table (~> 3) tty-screen (>= 0.6.3, < 1.0.0) tty-spinner (>= 0.8.0, < 1.0.0) word_wrap (~> 1.0.0) xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.3.0) xcpretty-travis-formatter (>= 0.0.3) - fastlane-plugin-stream_actions (0.3.19) + fastlane-plugin-stream_actions (0.3.25) xctest_list (= 1.2.1) - ffi (1.15.5) + ffi (1.16.3) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.49.0) + google-apis-androidpublisher_v3 (0.54.0) google-apis-core (>= 0.11.0, < 2.a) - google-apis-core (0.11.1) + google-apis-core (0.11.2) addressable (~> 2.5, >= 2.5.1) googleauth (>= 0.16.2, < 2.a) httpclient (>= 2.8.1, < 3.a) @@ -175,23 +177,23 @@ GEM google-apis-core (>= 0.11.0, < 2.a) google-apis-playcustomapp_v1 (0.13.0) google-apis-core (>= 0.11.0, < 2.a) - google-apis-storage_v1 (0.19.0) - google-apis-core (>= 0.9.0, < 2.a) - google-cloud-core (1.6.0) - google-cloud-env (~> 1.0) + google-apis-storage_v1 (0.29.0) + google-apis-core (>= 0.11.0, < 2.a) + google-cloud-core (1.6.1) + google-cloud-env (>= 1.0, < 3.a) google-cloud-errors (~> 1.0) google-cloud-env (1.6.0) faraday (>= 0.17.3, < 3.0) google-cloud-errors (1.3.1) - google-cloud-storage (1.44.0) + google-cloud-storage (1.45.0) addressable (~> 2.8) digest-crc (~> 0.4) google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.19.0) + google-apis-storage_v1 (~> 0.29.0) google-cloud-core (~> 1.6) googleauth (>= 0.16.2, < 2.a) mini_mime (~> 1.0) - googleauth (1.8.0) + googleauth (1.8.1) faraday (>= 0.17.3, < 3.a) jwt (>= 1.4, < 3.0) multi_json (~> 1.11) @@ -201,14 +203,14 @@ GEM http-cookie (1.0.5) domain_name (~> 0.5) httpclient (2.8.3) - i18n (1.13.0) + i18n (1.14.1) concurrent-ruby (~> 1.0) jmespath (1.6.2) - json (2.6.3) + json (2.7.1) jwt (2.7.1) mini_magick (4.12.0) mini_mime (1.1.5) - minitest (5.18.0) + minitest (5.20.0) molinillo (0.8.0) multi_json (1.15.0) multipart-post (2.3.0) @@ -216,17 +218,17 @@ GEM nap (1.1.0) naturally (2.2.1) netrc (0.11.0) - optparse (0.1.1) + optparse (0.4.0) os (1.1.4) - plist (3.7.0) + plist (3.7.1) public_suffix (4.0.7) - rake (13.0.6) + rake (13.1.0) representable (3.2.0) declarative (< 0.1.0) trailblazer-option (>= 0.1.1, < 0.2.0) uber (< 0.2.0) retriable (3.1.2) - rexml (3.2.5) + rexml (3.2.6) rouge (2.0.7) ruby-macho (2.5.1) ruby2_keywords (0.0.5) @@ -241,25 +243,25 @@ GEM CFPropertyList naturally terminal-notifier (2.0.0) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) trailblazer-option (0.1.2) tty-cursor (0.7.1) - tty-screen (0.8.1) + tty-screen (0.8.2) tty-spinner (0.9.3) tty-cursor (~> 0.7) - typhoeus (1.4.0) + typhoeus (1.4.1) ethon (>= 0.9.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.8.2) - unicode-display_width (1.8.0) + unf_ext (0.0.9.1) + unicode-display_width (2.5.0) webrick (1.8.1) word_wrap (1.0.0) - xcodeproj (1.22.0) + xcodeproj (1.23.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) @@ -271,17 +273,19 @@ GEM xcpretty-travis-formatter (1.0.1) xcpretty (~> 0.2, >= 0.0.7) xctest_list (1.2.1) + zeitwerk (2.6.12) PLATFORMS ruby DEPENDENCIES - cocoapods (~> 1.12, >= 1.12.1) + activesupport (>= 6.1.7.3, < 7.1.0) + cocoapods (~> 1.13) fastlane fastlane-plugin-stream_actions RUBY VERSION - ruby 2.7.5p203 + ruby 2.6.10p210 BUNDLED WITH 2.3.21 diff --git a/__tests__/FlatList.test.tsx b/__tests__/FlatList.test.tsx index 353ecdb..c1b9313 100644 --- a/__tests__/FlatList.test.tsx +++ b/__tests__/FlatList.test.tsx @@ -2,36 +2,27 @@ import React from 'react'; import { act, cleanup, - // fireEvent, render, screen, + userEvent, waitForElementToBeRemoved, } from '@testing-library/react-native'; import SectionList from '../src/components/FlatList'; -// const SCREEN_SIZE = { -// height: 500, -// width: 300, -// }; -// const eventData = { -// nativeEvent: { -// contentOffset: { -// y: SCREEN_SIZE.height, -// }, -// // Dimensions of the scrollable content -// contentSize: SCREEN_SIZE, -// // Dimensions of the device -// layoutMeasurement: SCREEN_SIZE, -// }, -// }; +const SCREEN_SIZE = {width: 240, height: 480}; +const scrollDownEventData = { + y: 300, + contentSize: SCREEN_SIZE, + layoutMeasurement: SCREEN_SIZE, +}; afterEach(cleanup); jest.useFakeTimers(); it('scrolls to bottom and loads more items', async () => { // Render the SectionList component render(); - // First dish is visible + expect(screen.getByText(/pizza/i)).toBeOnTheScreen(); // First dish from 2nd page is not visible yet expect(() => screen.getByText(/the impossible burger/i)).toThrow( @@ -41,20 +32,21 @@ it('scrolls to bottom and loads more items', async () => { expect(() => screen.getByText(/loading more dishes/i)).toThrow( 'Unable to find an element with text: /loading more dishes/i', ); - // Simulate scrolling to the bottom of the list - // TODO: fix this test case when this issue is resolved - // https://github.com/callstack/react-native-testing-library/issues/1549 - // fireEvent.scroll(screen.getByLabelText('dishes-list'), eventData); - // await waitForElementToBeRemoved( - // () => screen.getByText(/loading more dishes/i), - // { - // timeout: 1500, - // }, - // ); - // - // expect(await screen.findByText(/the impossible burger/i)).toBeOnTheScreen(); + const user = userEvent.setup(); + await user.scrollTo( + screen.getByLabelText('dishes-list'), + scrollDownEventData, + ); + await waitForElementToBeRemoved( + () => screen.getByText(/loading more dishes/i), + { + timeout: 1500, + }, + ); + + expect(await screen.findByText(/the impossible burger/i)).toBeOnTheScreen(); }); it('refreshes when scrolling to the top', async () => { diff --git a/__tests__/Home.test.tsx b/__tests__/Home.test.tsx index 1c1d492..46184a5 100644 --- a/__tests__/Home.test.tsx +++ b/__tests__/Home.test.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { cleanup, - fireEvent, render, screen, + userEvent, } from '@testing-library/react-native'; import App from '../App'; @@ -14,8 +14,9 @@ const mockedSetItem = jest.fn(); jest.mock('@react-native-community/async-storage', () => ({ setItem: mockedSetItem, })); +jest.useFakeTimers(); -it('renders/navigates throughout app screens', () => { +it('renders/navigates throughout app screens', async () => { // Render the app from teh root render(); @@ -23,7 +24,8 @@ it('renders/navigates throughout app screens', () => { expect(screen.getByText(/home/i)).toBeOnTheScreen(); // Navigate to counter screen by pressing on button - fireEvent.press(screen.getByText(/counter/i)); - // Check that navigation was succeeded by inspecting correspondeing text on the screen + const user = userEvent.setup(); + await user.press(screen.getByText(/counter/i)); + // Check that navigation was succeeded by inspecting corresponding text on the screen expect(screen.getByText(/current count: 0/i)).toBeOnTheScreen(); }); diff --git a/android/app/build.gradle b/android/app/build.gradle index 7de762a..59423ac 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -87,6 +87,14 @@ android { keyAlias 'androiddebugkey' keyPassword 'android' } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + storeFile file('release.keystore') + storePassword 'your_key_alias' + keyAlias '!igF-.z6Tw@BscKx' + keyPassword '!igF-.z6Tw@BscKx' + } } buildTypes { debug { diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 5a69425..fa63a8a 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1126,6 +1126,8 @@ PODS: - React-Core - RNCMaskedView (0.1.11): - React + - RNFlashList (1.6.3): + - React-Core - RNGestureHandler (2.14.0): - glog - RCT-Folly (= 2022.05.16.00) @@ -1214,6 +1216,7 @@ DEPENDENCIES: - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)" - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" + - "RNFlashList (from `../node_modules/@shopify/flash-list`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) - RNScreens (from `../node_modules/react-native-screens`) - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) @@ -1340,6 +1343,8 @@ EXTERNAL SOURCES: :path: "../node_modules/@react-native-community/async-storage" RNCMaskedView: :path: "../node_modules/@react-native-community/masked-view" + RNFlashList: + :path: "../node_modules/@shopify/flash-list" RNGestureHandler: :path: "../node_modules/react-native-gesture-handler" RNScreens: @@ -1413,6 +1418,7 @@ SPEC CHECKSUMS: ReactCommon: ddb128564dcbfa0287d3d1a2d10f8c7457c971f6 RNCAsyncStorage: b03032fdbdb725bea0bd9e5ec5a7272865ae7398 RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 + RNFlashList: 4b4b6b093afc0df60ae08f9cbf6ccd4c836c667a RNGestureHandler: 61bfdfc05db9b79dd61f894dcd29d3dcc6db3c02 RNScreens: b582cb834dc4133307562e930e8fa914b8c04ef2 SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 diff --git a/ios/reactnativetesting.xcodeproj/project.pbxproj b/ios/reactnativetesting.xcodeproj/project.pbxproj index 319c55c..b233c72 100644 --- a/ios/reactnativetesting.xcodeproj/project.pbxproj +++ b/ios/reactnativetesting.xcodeproj/project.pbxproj @@ -168,6 +168,7 @@ 00E356F51AD99517003FC87E /* PBXTargetDependency */, ); name = reactnativetestingTests; + productName = reactnativetestingTests; productReference = 00E356EE1AD99517003FC87E /* reactnativetestingTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; @@ -485,6 +486,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = TW5TFWL2UD; ENABLE_BITCODE = NO; INFOPLIST_FILE = reactnativetesting/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = reactnativetesting; @@ -512,7 +514,10 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = TW5TFWL2UD; INFOPLIST_FILE = reactnativetesting/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = reactnativetesting; LD_RUNPATH_SEARCH_PATHS = ( @@ -527,6 +532,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.reactnativetesting; PRODUCT_NAME = reactnativetesting; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; diff --git a/package.json b/package.json index 3d5578d..5d6fc0f 100644 --- a/package.json +++ b/package.json @@ -10,15 +10,16 @@ "test:unit": "jest", "test:unit:dev": "jest --watch", "test:unit:coverage": "jest --coverage", - "test:e2e": "maestro test e2e/flow.yaml", - "test:e2e:dev": "maestro test -c e2e/flow.yaml", - "test:e2e:record": "maestro record e2e/flow.yaml" + "test:e2e": "maestro test .maestro/flow.yaml", + "test:e2e:dev": "maestro test -c .maestro/flow.yaml", + "test:e2e:record": "maestro record .maestro/flow.yaml" }, "dependencies": { "@react-native-community/async-storage": "^1.12.1", "@react-native-community/masked-view": "^0.1.11", "@react-navigation/native": "^6.1.7", "@react-navigation/stack": "^6.3.17", + "@shopify/flash-list": "^1.6.3", "react": "18.2.0", "react-native": "0.73.1", "react-native-gesture-handler": "^2.14.0", @@ -30,15 +31,15 @@ "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", "@babel/runtime": "^7.20.0", + "@react-native/babel-preset": "^0.73.18", "@react-native/eslint-config": "^0.73.1", "@react-native/metro-config": "^0.73.2", + "@react-native/typescript-config": "^0.73.1", "@testing-library/react-native": "^12.4.3", "@types/jest": "^29.5.4", "@types/react": "^18.2.6", "@types/react-native-video": "^5.0.15", "@types/react-test-renderer": "^18.0.0", - "@react-native/typescript-config": "^0.73.1", - "@react-native/babel-preset": "^0.73.18", "axios": "^1.6.0", "babel-jest": "^29.6.3", "eslint": "^8.19.0", diff --git a/yarn.lock b/yarn.lock index edff04e..597d099 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2522,6 +2522,14 @@ color "^4.2.3" warn-once "^0.1.0" +"@shopify/flash-list@^1.6.3": + version "1.6.3" + resolved "https://registry.yarnpkg.com/@shopify/flash-list/-/flash-list-1.6.3.tgz#463dc1703815bf916f8173afc22c852bf26337ad" + integrity sha512-XM2iu4CeD9SOEUxaGG3UkxfUxGPWG9yacga1yQSgskAjUsRDFTsD3y4Dyon9n8MfDwgrRpEwuijd+7NeQQoWaQ== + dependencies: + recyclerlistview "4.2.0" + tslib "2.4.0" + "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -5715,7 +5723,7 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.debounce@^4.0.8: +lodash.debounce@4.0.8, lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== @@ -6548,7 +6556,7 @@ prompts@^2.0.1, prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@*, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@*, prop-types@15.8.1, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -6776,6 +6784,15 @@ recast@^0.21.0: source-map "~0.6.1" tslib "^2.0.1" +recyclerlistview@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/recyclerlistview/-/recyclerlistview-4.2.0.tgz#a140149aaa470c9787a1426452651934240d69ef" + integrity sha512-uuBCi0c+ggqHKwrzPX4Z/mJOzsBbjZEAwGGmlwpD/sD7raXixdAbdJ6BTcAmuWG50Cg4ru9p12M94Njwhr/27A== + dependencies: + lodash.debounce "4.0.8" + prop-types "15.8.1" + ts-object-utils "0.0.5" + redent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" @@ -7446,6 +7463,16 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +ts-object-utils@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/ts-object-utils/-/ts-object-utils-0.0.5.tgz#95361cdecd7e52167cfc5e634c76345e90a26077" + integrity sha512-iV0GvHqOmilbIKJsfyfJY9/dNHCs969z3so90dQWsO1eMMozvTpnB1MEaUbb3FYtZTGjv5sIy/xmslEz0Rg2TA== + +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"