Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Andrew fix e2e fork #13

Closed
wants to merge 48 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d69426c
Fix path to build Android correctly
AndrewGable Aug 11, 2023
85f0d93
Add `IS_MERGED` output
AndrewGable Aug 11, 2023
45dd2b4
Add two more missing outputs
AndrewGable Aug 11, 2023
20c1e05
Temp comment out fork checkout
AndrewGable Aug 11, 2023
0cd2754
Another temporary fix
AndrewGable Aug 11, 2023
f7f3a45
Tweak path
AndrewGable Aug 15, 2023
bd51745
Try fixing path yet again!
AndrewGable Aug 15, 2023
64e4eff
Undo test commit
AndrewGable Aug 15, 2023
9debab5
Testing full flow
AndrewGable Aug 15, 2023
e1b500b
Add more logs
AndrewGable Aug 16, 2023
6a93aeb
Add more logs
AndrewGable Aug 16, 2023
25af145
Fix logs 🙈
AndrewGable Aug 16, 2023
028b384
Only navigate to search bar once sidebar is loaded
AndrewGable Aug 16, 2023
8537d3e
Merge branch 'main' of github.com:margelo/expensify-app-fork into and…
hannojg Aug 31, 2023
1dd1863
point to correct .env file in build.gradle
hannojg Aug 31, 2023
bc17ec7
fix e2e build locally
hannojg Sep 1, 2023
cdd8111
fix local e2e build paths
hannojg Sep 1, 2023
9406c50
fix lines being printed twice
hannojg Sep 1, 2023
1b16f1d
fix local app path
hannojg Sep 1, 2023
88ce367
set correct app package name
hannojg Sep 1, 2023
282197b
fix repackaging APK in e2e development mode
hannojg Sep 1, 2023
c3c32e4
give more explanation
hannojg Sep 1, 2023
ff37429
explain debugging
hannojg Sep 1, 2023
32940c4
Improve DX if any config is wrong
hannojg Sep 1, 2023
bc114f9
move app loading to end
hannojg Sep 1, 2023
37d93ff
fix running tests in debug mode
hannojg Sep 1, 2023
232a2e2
fix tests
hannojg Sep 1, 2023
ea62c3c
add development flag back
hannojg Sep 1, 2023
f9144ed
Fix main index import
ospfranco Sep 12, 2023
b9df629
fix shell script
hannojg Sep 19, 2023
153174c
Merge branch 'main' of github.com:Expensify/App into andrew-fix-e2e-fork
hannojg Sep 19, 2023
f5f1175
add baseline building back + fix app path
hannojg Sep 21, 2023
475d75c
aws job depend on buildBaseline
hannojg Sep 21, 2023
ca47840
--allow-unrelated-histories
hannojg Sep 21, 2023
d646cdf
use absolute path to entry file
hannojg Sep 21, 2023
1daca9d
dev: check for file
hannojg Sep 21, 2023
3b31e1e
dev: are the files there?
hannojg Sep 21, 2023
c0794bd
invoke command manually
hannojg Sep 21, 2023
25d9c0a
revert change
hannojg Sep 22, 2023
8e25f3d
Test a different path for entry file
ospfranco Sep 22, 2023
86d7490
Add tmate
AndrewGable Sep 25, 2023
905b180
Adjust tests
AndrewGable Sep 25, 2023
e903857
Remove tmate, adjust file path
AndrewGable Sep 25, 2023
7f8fc19
Add more debugging
AndrewGable Sep 25, 2023
e3bc7ad
Add tmate back in
AndrewGable Sep 25, 2023
c18e19b
Remove file check
AndrewGable Sep 25, 2023
50f6401
Checkout test branch
AndrewGable Sep 25, 2023
c577451
TESTING: build action from branch
hannojg Sep 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/actions/composite/buildAndroidAPK/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ runs:

- uses: ruby/setup-ruby@eae47962baca661befdfd24e4d6c34ade04858f7
with:
ruby-version: '2.7'
ruby-version: "2.7"
bundler-cache: true

- uses: gradle/gradle-build-action@3fbe033aaae657f011f88f29be9e65ed26bd29ef
Expand All @@ -26,4 +26,4 @@ runs:
uses: actions/upload-artifact@65d862660abb392b8c4a3d1195a2108db131dd05
with:
name: ${{ inputs.ARTIFACT_NAME }}
path: android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk
path: android/app/build/outputs/apk/e2e/release/app-e2e-release.apk
6 changes: 6 additions & 0 deletions .github/actions/javascript/getPullRequestDetails/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ inputs:
outputs:
MERGE_COMMIT_SHA:
description: 'The merge_commit_sha of the given pull request'
HEAD_COMMIT_SHA:
description: 'The head_commit_sha of the given pull request'
MERGE_ACTOR:
description: 'The actor who merged the pull request'
IS_MERGED:
description: 'True if the pull request is merged'
FORKED_REPO_URL:
description: 'Output forked repo URL if PR includes changes from a fork'
runs:
using: 'node16'
main: './index.js'
45 changes: 31 additions & 14 deletions .github/workflows/e2ePerformanceTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,31 @@ jobs:
- name: Checkout "Baseline" commit (last release)
if: ${{ !fromJSON(steps.checkForExistingArtifact.outputs.exists) }}
run: |
git fetch origin tag ${{ steps.getMostRecentRelease.outputs.VERSION }} --no-tags --depth=1
git switch --detach ${{ steps.getMostRecentRelease.outputs.VERSION }}
git fetch origin andrew-fix-e2e-fork
git checkout andrew-fix-e2e-fork

# TODO: Uncomment before merging
# run: |
# git fetch origin tag ${{ steps.getMostRecentRelease.outputs.VERSION }} --no-tags --depth=1
# git switch --detach ${{ steps.getMostRecentRelease.outputs.VERSION }}

- name: Configure MapBox SDK
run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }}

- name: Build APK
if: ${{ !fromJSON(steps.checkForExistingArtifact.outputs.exists) }}
uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main
# TODO: Change back before merging:
#uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main
uses: Expensify/App/.github/actions/composite/buildAndroidAPK@andrew-fix-e2e-fork
with:
ARTIFACT_NAME: baseline-apk-${{ steps.getMostRecentRelease.outputs.VERSION }}

- name: Setup tmate session
if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true

buildDelta:
runs-on: ubuntu-latest-xl
name: Build apk from delta ref
Expand Down Expand Up @@ -84,12 +97,7 @@ jobs:
- name: Unmerged PR - Fetch head ref of unmerged PR
if: ${{ !fromJSON(steps.getPullRequestDetails.outputs.IS_MERGED) }}
run: |
if [[ ${{ steps.getPullRequestDetails.outputs.FORKED_REPO_URL }} != '' ]]; then
git remote add pr_remote ${{ steps.getPullRequestDetails.outputs.FORKED_REPO_URL }}
git fetch pr_remote ${{ steps.getPullRequestDetails.outputs.HEAD_COMMIT_SHA }} --no-tags --depth=1
else
git fetch origin ${{ steps.getPullRequestDetails.outputs.HEAD_COMMIT_SHA }} --no-tags --depth=1
fi
git fetch origin ${{ steps.getPullRequestDetails.outputs.HEAD_COMMIT_SHA }} --no-tags --depth=1

- name: Unmerged PR - Set dummy git credentials before merging
if: ${{ !fromJSON(steps.getPullRequestDetails.outputs.IS_MERGED) }}
Expand All @@ -101,7 +109,7 @@ jobs:
if: ${{ !fromJSON(steps.getPullRequestDetails.outputs.IS_MERGED) }}
id: getMergeCommitShaIfUnmergedPR
run: |
git merge --no-commit ${{ steps.getPullRequestDetails.outputs.HEAD_COMMIT_SHA }}
git merge --allow-unrelated-histories --no-commit ${{ steps.getPullRequestDetails.outputs.HEAD_COMMIT_SHA }}
git checkout ${{ steps.getPullRequestDetails.outputs.HEAD_COMMIT_SHA }}
env:
GITHUB_TOKEN: ${{ github.token }}
Expand All @@ -119,10 +127,18 @@ jobs:
run: ./scripts/setup-mapbox-sdk.sh ${{ secrets.MAPBOX_SDK_DOWNLOAD_TOKEN }}

- name: Build APK
uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main
# TODO: Change back before merging:
#uses: Expensify/App/.github/actions/composite/buildAndroidAPK@main
uses: Expensify/App/.github/actions/composite/buildAndroidAPK@andrew-fix-e2e-fork
with:
ARTIFACT_NAME: delta-apk-${{ steps.getDeltaRef.outputs.DELTA_REF }}

- name: Setup tmate session
if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true

runTestsInAWS:
runs-on: ubuntu-latest
needs: [buildBaseline, buildDelta]
Expand All @@ -140,18 +156,19 @@ jobs:
name: baseline-apk-${{ needs.buildBaseline.outputs.VERSION }}
path: zip

# The downloaded artifact will be a file named "app-e2eRelease.apk" so we have to rename it
# The downloaded artifact will be a file named "app-e2e-release.apk" so we have to rename it
- name: Rename baseline APK
run: mv "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2eRelease.apk" "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2eRelease-baseline.apk"
run: mv "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2e-release.apk" "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2eRelease-baseline.apk"

- name: Download delta APK
uses: actions/download-artifact@e9ef242655d12993efdcda9058dee2db83a2cb9b
id: downloadDeltaAPK
with:
name: delta-apk-${{ needs.buildDelta.outputs.DELTA_REF }}
path: zip

- name: Rename delta APK
run: mv "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2eRelease.apk" "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2eRelease-compare.apk"
run: mv "${{steps.downloadDeltaAPK.outputs.download-path}}/app-e2e-release.apk" "${{steps.downloadDeltaAPK.outputs.download-path}}/app-e2eRelease-compare.apk"

- name: Copy e2e code into zip folder
run: cp -r tests/e2e zip
Expand Down
14 changes: 12 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ project.ext.envConfigFiles = [
adhocRelease: ".env.adhoc",
developmentRelease: ".env",
developmentDebug: ".env",
e2eRelease: ".env.production"
e2eRelease: "tests/e2e/.env.e2e"
]

/**
Expand Down Expand Up @@ -136,10 +136,20 @@ android {
signingConfig signingConfigs.debug
}
release {
signingConfig signingConfigs.release
productFlavors.production.signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"

signingConfig null
// buildTypes take precedence over productFlavors when it comes to the signing configuration,
// thus we need to manually set the signing config, so that the e2e uses the debug config again.
// In other words, the signingConfig setting above will be ignored when we build the flavor in release mode.
productFlavors.all { flavor ->
// All release builds should be signed with the release config ...
flavor.signingConfig signingConfigs.release
}
// ... except for the e2e flavor, which we maybe want to build locally:
productFlavors.e2e.signingConfig signingConfigs.debug
}
}

Expand Down
2 changes: 1 addition & 1 deletion fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ platform :android do
desc "Generate a new local APK for e2e testing"
lane :build_e2e do
ENV["ENVFILE"]="tests/e2e/.env.e2e"
ENV["ENTRY_FILE"]="#{Dir.pwd}/../src/libs/E2E/reactNativeLaunchingTest.js"
ENV["ENTRY_FILE"]="src/libs/E2E/reactNativeLaunchingTest.js"
ENV["E2E_TESTING"]="true"

gradle(
Expand Down
3 changes: 2 additions & 1 deletion scripts/android-repackage-app-bundle-and-sign.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/bin/bash
source ./scripts/shellUtils.sh

###
# Takes an android app that has been built with the debug keystore,
Expand Down Expand Up @@ -41,7 +42,7 @@ if [ ! -f "$NEW_BUNDLE_FILE" ]; then
echo "Bundle file not found: $NEW_BUNDLE_FILE"
exit 1
fi
OUTPUT_APK=$(realpath "$OUTPUT_APK")
OUTPUT_APK=$(get_abs_path "$OUTPUT_APK")
# check if "apktool" command is available
if ! command -v apktool &> /dev/null
then
Expand Down
43 changes: 43 additions & 0 deletions scripts/shellUtils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,46 @@ function join_by_string {
shift
printf "%s" "$first" "${@/#/$separator}"
}

# Usage: get_abs_path <path>
# Will make a path absolute, resolving any relative paths
# example: get_abs_path "./foo/bar"
get_abs_path() {
local the_path=$1
local -a path_elements
IFS='/' read -ra path_elements <<< "$the_path"

# If the path is already absolute, start with an empty string.
# We'll prepend the / later when reconstructing the path.
if [[ "$the_path" = /* ]]; then
abs_path=""
else
abs_path="$(pwd)"
fi

# Handle each path element
for element in "${path_elements[@]}"; do
if [ "$element" = "." ] || [ -z "$element" ]; then
continue
elif [ "$element" = ".." ]; then
# Remove the last element from abs_path
abs_path=$(dirname "$abs_path")
else
# Append element to the absolute path
abs_path="${abs_path}/${element}"
fi
done

# Remove any trailing '/'
while [[ $abs_path == */ ]]; do
abs_path=${abs_path%/}
done

# Special case for root
[ -z "$abs_path" ] && abs_path="/"

# Special case to remove any starting '//' when the input path was absolute
abs_path=${abs_path/#\/\//\/}

echo "$abs_path"
}
1 change: 1 addition & 0 deletions src/libs/E2E/API.mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const mocks = {
BeginSignIn: mockBeginSignin,
SigninUser: mockSigninUser,
OpenApp: mockOpenApp,
ReconnectApp: mockOpenApp,
OpenReport: mockOpenReport,
AuthenticatePusher: mockAuthenticatePusher,
};
Expand Down
56 changes: 35 additions & 21 deletions src/libs/E2E/reactNativeLaunchingTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
*/

import Performance from '../Performance';

// start the usual app
Performance.markStart('regularAppStart');
import '../../../index';
Performance.markEnd('regularAppStart');
import * as Metrics from '../Metrics';

import E2EConfig from '../../../tests/e2e/config';
import E2EClient from './client';
Expand All @@ -19,6 +15,11 @@ console.debug('==========================');
console.debug('==== Running e2e test ====');
console.debug('==========================');

// Check if the performance module is available
if (!Metrics.canCapturePerformanceMetrics()) {
throw new Error('Performance module not available! Please set CAPTURE_METRICS=true in your environment file!');
}

// import your test here, define its name and config first in e2e/config.js
const tests = {
[E2EConfig.TEST_NAMES.AppStartTime]: require('./tests/appStartTimeTest.e2e').default,
Expand All @@ -36,20 +37,33 @@ const appReady = new Promise((resolve) => {
});
});

E2EClient.getTestConfig().then((config) => {
const test = tests[config.name];
if (!test) {
// instead of throwing, report the error to the server, which is better for DX
return E2EClient.submitTestResults({
name: config.name,
error: `Test '${config.name}' not found`,
});
}
console.debug(`[E2E] Configured for test ${config.name}. Waiting for app to become ready`);

appReady.then(() => {
console.debug('[E2E] App is ready, running test…');
Performance.measureFailSafe('appStartedToReady', 'regularAppStart');
test();
E2EClient.getTestConfig()
.then((config) => {
const test = tests[config.name];
if (!test) {
// instead of throwing, report the error to the server, which is better for DX
return E2EClient.submitTestResults({
name: config.name,
error: `Test '${config.name}' not found`,
});
}

console.debug(`[E2E] Configured for test ${config.name}. Waiting for app to become ready`);
appReady
.then(() => {
console.debug('[E2E] App is ready, running test…');
Performance.measureFailSafe('appStartedToReady', 'regularAppStart');
test();
})
.catch((error) => {
console.error('[E2E] Error while waiting for app to become ready', error);
});
})
.catch((error) => {
console.error("[E2E] Error while running test. Couldn't get test config!", error);
});
});

// start the usual app
Performance.markStart('regularAppStart');
import '../../../index';
Performance.markEnd('regularAppStart');
23 changes: 20 additions & 3 deletions src/libs/E2E/tests/openSearchPageTest.e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,41 @@ import CONST from '../../../CONST';

const test = () => {
// check for login (if already logged in the action will simply resolve)
console.debug('[E2E] Logging in for search');

E2ELogin().then((neededLogin) => {
if (neededLogin) {
// we don't want to submit the first login to the results
return E2EClient.submitTestDone();
}

console.debug('[E2E] Logged in, getting search metrics and submitting them…');

Performance.subscribeToMeasurements((entry) => {
if (entry.name === CONST.TIMING.SIDEBAR_LOADED) {
console.debug(`[E2E] Sidebar loaded, navigating to search route…`);
Navigation.navigate(ROUTES.SEARCH);
return;
}

console.debug(`[E2E] Entry: ${JSON.stringify(entry)}`);
if (entry.name !== CONST.TIMING.SEARCH_RENDER) {
return;
}

console.debug(`[E2E] Submitting!`);
E2EClient.submitTestResults({
name: 'Open Search Page TTI',
duration: entry.duration,
}).then(E2EClient.submitTestDone);
})
.then(() => {
console.debug('[E2E] Done with search, exiting…');
E2EClient.submitTestDone();
})
.catch((err) => {
console.debug('[E2E] Error while submitting test results:', err);
});
});

Navigation.navigate(ROUTES.SEARCH);
});
};

Expand Down
Loading
Loading