diff --git a/.github/docker/scripts/run_docker_server.sh b/.github/docker/scripts/run_docker_server.sh new file mode 100755 index 00000000000..083a6b332c4 --- /dev/null +++ b/.github/docker/scripts/run_docker_server.sh @@ -0,0 +1,28 @@ +### +### Hack to make it work with MIM attack from security ... +### +sed -i 's/https/http/g' Gemfile +gem sources -r https://rubygems.org/ +yes | gem sources --add http://rubygems.org + +### +### Downloads gems for test & development +### +bundle config --delete without +bundle install + +### +### Cleans stuff if need be +### +rm -f tmp/pids/server.pid + +### +### Initialises the DB +### +bundle exec rake db:setup + + +### +### Runs Simple +### +bundle exec rails s -p 3000 -b '0.0.0.0' diff --git a/.github/docker/simple-server.compose.yml b/.github/docker/simple-server.compose.yml index c4576f81c81..af039f89e37 100644 --- a/.github/docker/simple-server.compose.yml +++ b/.github/docker/simple-server.compose.yml @@ -1,34 +1,84 @@ version: "3" services: + ### psql -h postgres -p 5432 -U postgres postgres: image: postgres:14.3-alpine environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=password - expose: - - "5432" + ports: + - "5432:5432" + + webdb: + image: webdb/app + ports: + - "22071:22071" + depends_on: + server: + condition: service_healthy redis: image: redis:5-alpine - expose: - - "6379" + ports: + - "6379:6379" + server: - image: simpledotorg/server:latest - command: bash -c "rm -f tmp/pids/server.pid && bundle exec rake db:setup; bundle exec rails s -p 3000 -b '0.0.0.0'" - expose: - - "3000" + container_name: simple-server + image: simpledotorg/server + #command: bash -c "rm -f tmp/pids/server.pid ; bundle install ; bundle exec rake db:setup ; bundle exec rails s -p 3000 -b '0.0.0.0'" + command: bash -c "bash ./run_docker_server.sh" + healthcheck: + test: "curl -f http://localhost:3000/api/v3/ping" + start_period: 10m ports: - - "8420:3000" + - "3000:3000" depends_on: - redis - postgres + volumes: + - ./scripts/run_docker_server.sh:/home/app/run_docker_server.sh environment: SIMPLE_SERVER_DATABASE_HOST: postgres SIMPLE_SERVER_DATABASE_USERNAME: postgres SIMPLE_SERVER_DATABASE_PASSWORD: password + SIMPLE_SERVER_DATABASE_NAME: SIMPLE_POC SIMPLE_SERVER_HOST_PROTOCOL: https CALL_SESSION_REDIS_HOST: redis RAILS_CACHE_REDIS_URL: redis:// + RAILS_CACHE_REDIS_PASSWORD: NONE + RAILS_ENV: test SIDEKIQ_REDIS_HOST: redis + SIDEKIQ_CONCURRENCY: 5 + SIMPLE_SERVER_HOST: localhost + SENDGRID_USERNAME: NONE + SENDGRID_PASSWORD: NONE + SENTRY_DSN: none.org + SEED_GENERATED_ACTIVE_USER_ROLE: Seed User | Active + SEED_GENERATED_ADMIN_PASSWORD: trying to fix hypertension + SEED_GENERATED_INACTIVE_USER_ROLE: Seed User | Inactive + SIMPLE_APP_SIGNATURE: + TWILIO_ACCOUNT_SID: + TWILIO_REMINDERS_ACCOUNT_SID: + SEED_TYPE: empty + SENTRY_SECURITY_HEADER_ENDPOINT: http://none.org + EXOTEL_TOKEN: + TWILIO_AUTH_TOKEN: + TWILIO_PHONE_NUMBER: + TWILIO_REMINDERS_ACCOUNT_AUTH_TOKEN: + TWILIO_REMINDERS_ACCOUNT_PHONE_NUMBER: + SIMPLE_SERVER_ENV: qa + TEMPORARY_RETENTION_DURATION_SECONDS: 60 + ANALYTICS_DASHBOARD_CACHE_TTL: 3600 + CALL_SESSION_REDIS_POOL_SIZE: 12 + CALL_SESSION_REDIS_TIMEOUT_SEC: 1 + DEFAULT_COUNTRY: US + DEFAULT_NUMBER_OF_RECORDS: 10 + EMAIL_SUBJECT_PREFIX: "[Simple DEVELOPMENT]" + HELP_SCREEN_YOUTUBE_PASSPORT_URL: https://youtu.be/aktZ1yTdDOA + HELP_SCREEN_YOUTUBE_TRAINING_URL: https://youtu.be/MC_45DoRw2g + HELP_SCREEN_YOUTUBE_VIDEO_URL: https://youtu.be/nHsQ06tiLzw + SENTRY_CURRENT_ENV: development + USER_OTP_VALID_UNTIL_DELTA_IN_MINUTES: 10 + SECRET_KEY_BASE: 6e3a553d989615581dfdfcfcb0670b002e5d9d27c38a284a5020107e8ba516789117630f9c7e0ade1d0d7b0b68aeb50df88d8b15ea55dc423246db2984f6e5ef diff --git a/.github/scripts/deploy_docker_server.sh b/.github/scripts/deploy_docker_server.sh new file mode 100755 index 00000000000..254b01a6662 --- /dev/null +++ b/.github/scripts/deploy_docker_server.sh @@ -0,0 +1,2 @@ +docker compose -f ".github/docker/simple-server.compose.yml" up -d +docker compose -f ".github/docker/simple-server.compose.yml" exec server bash -c "RAILS_ENV=test bundle exec rails runner 'Flipper.enable :auto_approve_users; Flipper.enable :fixed_otp; puts \"Features enabled!\"'" diff --git a/.github/workflows/ci_checks.yml b/.github/workflows/ci_checks.yml index 3be670e689d..2f8257f6e79 100644 --- a/.github/workflows/ci_checks.yml +++ b/.github/workflows/ci_checks.yml @@ -72,9 +72,111 @@ jobs: ./gradlew --build-cache --no-daemon test -x :app:test; ./gradlew --build-cache --no-daemon testQaDebugUnitTest; - - # TODO: Add Android integration tests once [SC-13775] is resolved + integration_tests: + runs-on: [ ubuntu-latest ] + env: + AVD_API_LEVEL: 34 + AVD_ARCH: x86_64 + steps: + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + + - name: Checkout Android source + uses: actions/checkout@v4 + + - name: Start Simple Docker server + run: | + .github/scripts/deploy_docker_server.sh + echo "CONTAINER_ID=$(docker container ls -q -f name=simple-server)" >> $GITHUB_ENV + + - name: Cache AVD + uses: actions/cache@v4 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: ${{ runner.os }}-avd-${{ env.AVD_API_LEVEL }}-${{ env.AVD_ARCH }} + + - name: create AVD and generate snapshot for caching + if: steps.avd-cache.outputs.cache-hit != 'true' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ env.AVD_API_LEVEL }} + arch: ${{ env.AVD_ARCH }} + force-avd-creation: false + emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: false + disk-size: 8G + script: echo "Generated AVD snapshot for caching." + + - name: set up JDK + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 17 + cache: 'gradle' + + - name: Create build directory + run: mkdir app/build + + - name: Build QA Test Artifacts + id: build-instrumented-tests + run: | + ./gradlew --build-cache --no-daemon -PmanifestEndpoint=http://10.0.2.2:3000/api/ assembleQaDebug assembleQaDebugAndroidTest + + - name: Android Tests + id: run-instrumented-tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ env.AVD_API_LEVEL }} + arch: ${{ env.AVD_ARCH }} + force-avd-creation: false + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: true + disk-size: 8G + script: | + adb root + mkdir -p app/build/outputs/test-artifacts + adb install app/build/outputs/apk/qa/debug/app-qa-debug.apk + adb install app/build/outputs/apk/androidTest/qa/debug/app-qa-debug-androidTest.apk + adb shell am instrument -w -e filter org.simple.clinic.benchmark.SelectBenchmarkTests -e benchmark_app_performance false org.simple.clinic.qa.debug.test/org.simple.clinic.AndroidTestJUnitRunner >app/build/outputs/test-artifacts/logs.txt 2>app/build/outputs/test-artifacts/logs.txt + cat app/build/outputs/test-artifacts/logs.txt + adb pull /storage/emulated/0/Android/data/org.simple.clinic.qa.debug/ app/build/outputs/test-artifacts/ || true + adb uninstall org.simple.clinic.qa.debug + adb uninstall org.simple.clinic.qa.debug.test + ! grep -q "FAILURES\!\!\!" app/build/outputs/test-artifacts/logs.txt + + - name: Upload failed test artifacts + if: always() && steps.run-instrumented-tests.outcome != 'success' + uses: actions/upload-artifact@v4 + with: + name: failed-test-artifacts + path: app/build/outputs/test-artifacts + + - name: Extract Docker logs + if: always() + run: | + docker cp ${{ env.CONTAINER_ID }}:/home/app/log ./docker_logs + zip -r docker_logs.zip docker_logs/ + + + - name: Upload Docker logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: docker-logs + path: docker_logs.zip + + - name: Stop Simple Docker server + run: | + docker compose -f ".github/docker/simple-server.compose.yml" down + verify_room_schemas: runs-on: [ ubuntu-latest ] diff --git a/app/src/androidTest/java/org/simple/clinic/settings/SettingsScreenTest.kt b/app/src/androidTest/java/org/simple/clinic/settings/SettingsScreenTest.kt index c27ef7d409b..223a183550a 100644 --- a/app/src/androidTest/java/org/simple/clinic/settings/SettingsScreenTest.kt +++ b/app/src/androidTest/java/org/simple/clinic/settings/SettingsScreenTest.kt @@ -233,26 +233,7 @@ class SettingsScreenTest { } @Test - fun whenLogoutFeatureIsNotEnabledThenDoNotShowLogoutButton() { - val model = SettingsModel.default( - isChangeLanguageFeatureEnabled = true, - ) - composeRule.setContent { - SettingsScreen( - model = model, - navigationIconClick = { /*no-op*/ }, - changeLanguageButtonClick = { /*no-op*/ }, - updateButtonClick = { /*no-op*/ }, - logoutButtonClick = { /*no-op*/ } - ) - } - - // then - composeRule.onNodeWithTag("SETTINGS_LOGOUT_BUTTON").assertDoesNotExist() - } - - @Test - fun whenLogoutFeatureIsEnabledThenShowLogoutButton() { + fun logoutButtonShouldBeVisible() { val model = SettingsModel.default( isChangeLanguageFeatureEnabled = true, ) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3d21ae3f6bd..28f2942fc9f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -54,10 +54,12 @@ android:allowBackup="false" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" + android:networkSecurityConfig="@xml/network_config" android:supportsRtl="true" android:theme="@style/Theme.Simple" tools:ignore="AllowBackup,DataExtractionRules,GoogleAppIndexingWarning,LockedOrientationActivity" - tools:replace="android:allowBackup"> + tools:replace="android:allowBackup" + tools:targetApi="n"> + + + 10.0.2.2 + + +