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

Replace Jest runner with Wdio runner E2E #41218

Open
wants to merge 87 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
0484f3c
change step order, reduce no output to 5min
Othinn Oct 17, 2023
ada6a34
Add wdio.conf.js with basic functions, update package.json
Othinn Oct 25, 2023
49a00f2
Rewrite two test
Othinn Oct 25, 2023
a354699
update tests to separate files and folders
Othinn Oct 26, 2023
27fdd78
minor changes
Othinn Oct 26, 2023
9932eda
update test_e2e_ios
Othinn Oct 26, 2023
3b83c61
update capabilities to those of circleCI device farm
Othinn Oct 26, 2023
e8d76fa
This is only a temporary solution
Othinn Oct 26, 2023
06b08b0
cleaning old setup
Othinn Oct 26, 2023
2ba9442
restoring e2e config
Othinn Oct 26, 2023
8d82d7d
update Readme.md
Othinn Oct 26, 2023
f41c4d0
Adding it for greater visibility
Othinn Oct 26, 2023
b20667d
update Android E2E tests job
Othinn Oct 27, 2023
28cb6a9
Clean conf files
Othinn Oct 27, 2023
350880c
update
Othinn Oct 30, 2023
a3849db
removing appium and drivers from job
Othinn Oct 30, 2023
4309e0c
update comands
Othinn Oct 30, 2023
1fcce98
remove creating screenshots for now
Othinn Oct 30, 2023
255b327
update Readme, delete console.log
Othinn Oct 30, 2023
4c79fec
updated error handling
Othinn Oct 30, 2023
3cad9b3
rerun
Othinn Oct 30, 2023
8348cb3
uncomment e2e in pipeline selection
Othinn Oct 30, 2023
b7b0076
prettier
Othinn Oct 31, 2023
f455d50
add installing appium to steps
Othinn Oct 31, 2023
86c99b3
correct ios capa, update platform to choose correct platform
Othinn Oct 31, 2023
1e18464
updated timers, add waitForDisplayed for component header
Othinn Nov 2, 2023
0fd1213
Add timeout to checkElementExistace for more flexibility
Othinn Nov 2, 2023
12f5e13
update mocha timeout
Othinn Nov 2, 2023
03bc5dd
fix typo
Othinn Nov 2, 2023
7e6427c
update gitignore
Othinn Nov 2, 2023
55ed02b
add logs to artifacts
Othinn Nov 2, 2023
10789f7
add shorter global timers
Othinn Nov 3, 2023
596fb91
added screenshots after errors
Othinn Nov 3, 2023
c23d4d2
add screenshot on error
Othinn Nov 3, 2023
69c7e54
update names, description and added it to all commands
Othinn Nov 8, 2023
471a522
remove error in if and add mochas bait to config
Othinn Nov 8, 2023
3753306
remove appium from circleCi scripts
Othinn Nov 9, 2023
36ca1bb
Revert "remove appium from circleCi scripts"
Othinn Nov 9, 2023
7fcfb38
add correct deafult timeout, unify errors in conf
Othinn Nov 12, 2023
d17b9be
increase mocha timeout
Othinn Nov 12, 2023
f2497e6
add error shots to artifacts
Othinn Nov 12, 2023
cda30a1
lock appium and drivers version
Othinn Nov 13, 2023
40e52c7
try to prevent app to reinstall
Othinn Nov 13, 2023
eda6752
#run-e2e-tests
Othinn Nov 13, 2023
c2c9f4f
#run-e2e-tests
Othinn Nov 13, 2023
339ef7d
add fullReset to android
Othinn Nov 13, 2023
8211365
#run-e2e-tests
Othinn Nov 14, 2023
71c00c2
#run-e2e-tests
Othinn Nov 14, 2023
bd1fccb
#run-e2e-tests
Othinn Nov 14, 2023
e0ca2c8
#run-e2e-tests
Othinn Nov 15, 2023
ef80314
#run-e2e-tests
Othinn Nov 15, 2023
b3f7823
#run-e2e-tests
Othinn Nov 15, 2023
906f8df
add simulator logs
Othinn Nov 15, 2023
7a62a0a
revert add simulator logs
Othinn Nov 16, 2023
cd3dee3
#run-e2e-tests
Othinn Nov 16, 2023
3165959
add higher mocha tiemout
Othinn Nov 20, 2023
4aa3771
#run-e2e-tests
Othinn Nov 20, 2023
d8a408f
Change ios version
Othinn Nov 20, 2023
85aff57
change platform version
Othinn Nov 20, 2023
e2ef1ba
add bail to prevent major fails
Othinn Nov 20, 2023
91cc9e2
changing from isDisplayed to isClickable in scroll
Othinn Nov 21, 2023
d643913
decrease bail and increase newCommandTImeout
Othinn Nov 21, 2023
d26c6b0
increase newCommandTimeout on ios
Othinn Nov 22, 2023
2d6d890
update wdio
Othinn Nov 22, 2023
05fa408
increase timers
Othinn Nov 22, 2023
d9763b5
add retry and lock xcuitest version
Othinn Nov 22, 2023
aa35261
add start appium server ios job
Othinn Nov 23, 2023
588288d
update conf and delete run appium server job
Othinn Nov 23, 2023
9d15557
correct capas
Othinn Nov 23, 2023
84688cb
#run-e2e-tests
Othinn Nov 24, 2023
e954979
move port and add session-override to ios conf
Othinn Nov 24, 2023
cc010b9
#run-e2e-tests
Othinn Nov 24, 2023
9405126
#run-e2e-tests
Othinn Nov 26, 2023
ba4b18c
add delete session to afterSuite
Othinn Nov 26, 2023
ba85414
update test composition, add searching instead scrolling in some cases
Othinn Nov 28, 2023
b68ffb4
update android search selector
Othinn Nov 29, 2023
ab0a31e
replace scroll with search
Othinn Nov 29, 2023
ca84525
decrese timeouts
Othinn Nov 29, 2023
d5cc3b2
fix typos
Othinn Nov 30, 2023
1579c4c
increase connectionRetryTImeout
Othinn Nov 30, 2023
be2119b
update timeouts for andorid
Othinn Jan 9, 2024
5cbf257
Merge branch 'main' into wdio-runner
Othinn Jan 10, 2024
650b71a
fix style issues
Othinn Jan 22, 2024
5a29713
change android tag to default and lock uiautomator ver
Othinn Jan 22, 2024
49da014
added step to copy packages, added address to appium
Othinn Apr 7, 2024
ba322e7
make script executable
Othinn Apr 8, 2024
7c311bd
add correct path
Othinn Apr 8, 2024
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
60 changes: 23 additions & 37 deletions .circleci/configurations/jobs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,6 @@ jobs:
- checkout_code_with_cache
- run_yarn
- setup_hermes_version
- run:
name: Install appium
command: npm install appium@2.0.0 -g
- run:
name: Install appium drivers
command: |
appium driver install uiautomator2
appium driver install xcuitest
- run:
name: Start Appium server
command: appium --base-path /wd/hub
background: true
- run:
name: Start Metro
command: |
Expand All @@ -145,6 +133,12 @@ jobs:
package: cmake
- setup_ruby:
ruby_version: << parameters.ruby_version >>
- run:
name: Copy packages
command: |
cd packages/rn-tester-e2e/scripts
chmod +x copy-packages.sh
./copy-packages.sh
- run:
name: Boot iOS Simulator
command: source scripts/.tests.env && xcrun simctl boot "$IOS_DEVICE" || true
Expand All @@ -169,25 +163,26 @@ jobs:
- run:
name: Move app to correct directory
command: mv /tmp/e2e/Build/Products/Debug-iphonesimulator/RNTester.app packages/rn-tester-e2e/apps/rn-tester.app
- run:
name: Check Appium server status
command: scripts/circleci/check_appium_server_status.sh
- run:
name: Run E2E tests
no_output_timeout: 30m
no_output_timeout: 5m
command: |
cd packages/rn-tester-e2e
(yarn test-e2e ios 2>&1 | tee /tmp/test_log) || true
(yarn test-e2e-ios 2>&1 | tee /tmp/test_log) || true
- store_artifacts:
path: /tmp/test_log
- store_artifacts:
path: ~/react-native/packages/rn-tester-e2e/reports

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also include the error screenshots here. That way, the engineer can see a screenshot of the failure.

- store_artifacts:
path: ~/react-native/packages/rn-tester-e2e/reports/errorShots

# -------------------------
# JOBS: Android E2E Tests
# -------------------------
test_e2e_android:
executor:
name: android/android-machine
tag: 2023.07.1
tag: default
steps:
- checkout_code_with_cache
- run_yarn
Expand All @@ -201,17 +196,11 @@ jobs:
restore-gradle-cache-prefix: v1a
post-emulator-launch-assemble-command: ""
- run:
name: Install appium
command: npm install appium@2.0.0 -g
- run:
name: Install appium drivers
name: Copy packages
command: |
appium driver install uiautomator2@2.29.1
appium driver install xcuitest@4.32.10
- run:
name: Start Appium server
command: appium --base-path /wd/hub
background: true
cd packages/rn-tester-e2e/scripts
chmod +x copy-packages.sh
./copy-packages.sh
- run:
name: Start Metro
command: |
Expand All @@ -227,21 +216,18 @@ jobs:
- run:
name: Move app to correct directory
command: mv packages/rn-tester/android/app/build/outputs/apk/hermes/debug/app-hermes-x86_64-debug.apk packages/rn-tester-e2e/apps/rn-tester.apk
- run:
name: Check Appium server status
command: |
if ! nc -z 127.0.0.1 4723; then
echo Could not find Appium server
exit 1
fi
- run:
name: Run E2E tests
no_output_timeout: 30m
no_output_timeout: 5m
command: |
cd packages/rn-tester-e2e
(yarn test-e2e android 2>&1 | tee /tmp/test_log) || true
(yarn test-e2e-android 2>&1 | tee /tmp/test_log) || true
- store_artifacts:
path: /tmp/test_log
- store_artifacts:
path: ~/react-native/packages/rn-tester-e2e/reports
- store_artifacts:
path: ~/react-native/packages/rn-tester-e2e/reports/errorShots

# -------------------------
# JOBS: Build Android
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ vendor/
.metro-health-check*

# E2E files
/packages/rn-tester-e2e/reports
/packages/rn-tester-e2e/apps/*.apk
/packages/rn-tester-e2e/apps/*.app

Expand Down
30 changes: 5 additions & 25 deletions packages/rn-tester-e2e/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# RNTester E2E folder

In this folder we have a the setup for running E2E testing in RNTester via the usage of [Appium](https://appium.io/) and [WebDriverIO](https://webdriver.io/) and [Jest](https://jestjs.io/).
In this folder we have a the setup for running E2E testing in RNTester via the usage of [Appium](https://appium.io/) and [WebDriverIO](https://webdriver.io/).

- [Setting up locally](#setting-up-locally)
- [(one-off) Setting up Appium](#one-off-setting-up-appium)
- [Building RNTester app](#building-rntester-app)
- [Building for iOS](#building-for-ios)
- [Building for Android](#building-for-android)
Expand All @@ -13,19 +12,6 @@ In this folder we have a the setup for running E2E testing in RNTester via the u

## Setting up locally

### (one-off) Setting up Appium

The first step you need to do is to ensure to install the tooling:

```bash
npm install appium@2.0.0 -g
appium driver install uiautomator2
appium driver install xcuitest
```

> More details about drivers in Appium [here](https://appium.github.io/appium/docs/en/2.0/guides/managing-exts/) and [here](https://appium.github.io/appium/docs/en/2.0/quickstart/uiauto2-driver/)

You should not need to run install commands for drivers separately more than once, even if you bump the dep in package.json.

### Building RNTester app

Expand Down Expand Up @@ -90,13 +76,7 @@ And modify lines L24->L39 to reflect your local setup configuration (ex. `platfo

Othinn marked this conversation as resolved.
Show resolved Hide resolved
## Testing the RNTester app E2E

After you have done all the above correctly, and you have the Android/iOS apps in the `rn-tester-e2e/apps` folder, in a dedicated terminal window, run:

```bash
appium --base-path /wd/hub
```

This will start the Appium server - you will need this to keep running.
After you have done all the above correctly, and you have the Android/iOS apps in the `rn-tester-e2e/apps` folder.

Then open a second terminal window and start the Metro terminal from the `packages/rn-tester` folder, via `yarn start --reset-cache`. This terminal window also needs to keep running.

Expand All @@ -105,8 +85,8 @@ Now, make sure that the iOS simulator/the Android emulator is up and running.
Finally, you can open a third terminal window and run:

```bash
yarn test-e2e android # for android
yarn test-e2e ios # for ios
yarn test-e2e-android # for android
yarn test-e2e-ios # for ios
```

Now you should see the RNTester app being open, and the defined test being run.
Expand All @@ -119,6 +99,6 @@ This project has 2 main folders:

- `tests`, where the tests and referencing files all live. The substructure is as follows:
- `screens` -> in this folder, you will find `*.screen.js` files, where each file represents a navigation screen for RNTester. So there are 3 root ones (`apis`, `bookmarks`, `components`) and then for subscreens, there's a folder with the same name - currently, that's only `components` that contains `buttonComponent.screen.js`. The content of these files is what was earlier mentioned as "references": they provide an easy way to define all elements present in said screen, so that they can be used for tests.
- `specs` -> this folder follows a similar 1:1 mapping to the RNTester screens, but for the tests: for each screen (or subscreen) there's a dedicated `*.test.js` file (such as `buttonComponentScreen.test.js`). Ideally, in this file the Jest tests are standard, leveraging the `*.screen.js` counterpart for the details of defining how Appium/WDIO can reach those elements on screen.
- `specs` -> this folder follows a similar 1:1 mapping to the RNTester screens, but for the tests: for each screen (or subscreen) there's a dedicated folder file and within it theres test file (such as `invertedFlatList.test.js`).

When adding a new test, please ensure that you follow this pattern and add the relevant test in the right screen file / screen test file. Use the files mentioned above as examples.
18 changes: 0 additions & 18 deletions packages/rn-tester-e2e/jest.config.js

This file was deleted.

50 changes: 0 additions & 50 deletions packages/rn-tester-e2e/jest.setup.js

This file was deleted.

26 changes: 17 additions & 9 deletions packages/rn-tester-e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,28 @@
"description": "React Native E2E tester app.",
"homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/rn-tester-e2e",
"repository": {
"type": "git",
"url": "git@github.com:facebook/react-native.git",
"directory": "packages/rn-tester-e2e"
"type": "git",
"url": "git@github.com:facebook/react-native.git",
"directory": "packages/rn-tester-e2e"
},
"scripts": {
"test-e2e": "node ./../../scripts/e2e/run-e2e-tests.js"
"test-e2e-ios": "npx wdio wdio.conf.ios.js",
"test-e2e-android": "npx wdio wdio.conf.android.js"
},
"devDependencies": {
"eslint": "^8.19.0",
"jest": "^29.6.3",
"webdriverio": "^7.32.0",
"@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/plugin-transform-flow-strip-types": "^7.20.0",
"@types/jest": "^29.5.3"
"@babel/preset-env": "^7.20.0",
"@wdio/appium-service": "^8.10.5",
"@wdio/cli": "^8.10.5",
"@wdio/local-runner": "^8.10.5",
"@wdio/mocha-framework": "8.10.4",
"@wdio/spec-reporter": "8.8.7",
"appium": "2.0.0",
"appium-uiautomator2-driver": "2.29.0",
"appium-xcuitest-driver": "5.6.0",
"eslint": "^8.23.1",
"ts-node": "^10.9.1",
"typescript": "^5.3.2"
}
}
15 changes: 15 additions & 0 deletions packages/rn-tester-e2e/scripts/copy-packages.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

SOURCE_DIR=../../../node_modules
DEST_DIR=../node_modules

# List of package directories to copy
PACKAGES=("appium" "appium-uiautomator2-driver" "appium-xcuitest-driver" "@wdio")

# Copy each package directory
for PACKAGE in "${PACKAGES[@]}"; do
echo "Copying $PACKAGE..."
cp -R "$SOURCE_DIR/$PACKAGE" "$DEST_DIR"
done

echo "Copying completed."
28 changes: 15 additions & 13 deletions packages/rn-tester-e2e/tests/helpers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,42 @@
* @format
*/

import {driver} from '../../jest.setup';

type PlatformsReference = {
ios: string,
android: string,
};

class Utils {
async checkElementExistence(locator: string): Promise<boolean> {
await driver.$(locator).waitForDisplayed();
return driver.$(locator).isDisplayed();
await $(locator).waitForDisplayed();
Copy link

@samuelfreiberg samuelfreiberg Apr 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: In all these helper methods, I suggest utilizing the errorMsg parameter in waitForDisplayed(). You can pass in the specific locator string so the error message is specific. If not, it will be confusing when debugging to see where it failed and which component.

For example,
await $(locator).waitForDisplayed({ timeout: 15000, timeoutMsg: "The element with locator=" + locator + " was not found"});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It helps debugging a ton

return $(locator).isDisplayed();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just return await $(locator).waitForDisplayed();. Such as return await $(locator).waitForDisplayed();.

waitForDisplayed throws an error if it fails, or returns true if it succeeds. Adding return $(locator).isDisplayed(); is unnecessary and will decrease perf by adding another API call.

}

async clickElement(locator: string): Promise<void> {
await driver.$(locator).waitForDisplayed();
await driver.$(locator).click();
await $(locator).waitForDisplayed();
await $(locator).click();
}

async getElementText(locator: string): Promise<string> {
await driver.$(locator).waitForDisplayed();
return driver.$(locator).getText();
await $(locator).waitForDisplayed();
return $(locator).getText();
}

async setElementText(locator: string, text: string): Promise<void> {
await $(locator).waitForDisplayed();
return $(locator).setValue(text);
}

platformSelect(platforms: PlatformsReference): string {
// if something goes wrong, we fallback to ios. But it should never happent, the process will fail way earlier.
return platforms[process?.env?.E2E_DEVICE || 'ios'];
return platforms[browser.capabilities.platformName.toLowerCase()];
}

async scrollToElement(locator: string): Promise<void> {
let {width, height} = await driver.getWindowSize();
let elementIsFound;
try {
elementIsFound = await driver.$(locator).isDisplayed();
while (!elementIsFound) {
elementIsFound = await $(locator).isClickable();
while (!(await elementIsFound)) {
driver.touchPerform([
{
action: 'press',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest changing this scroll logic completely. Taking the window size and performing mathematical operations on it to determine touches is prone to error. Here's a better way:

    await browser.waitUntil(
      async () => {
        await driver.execute('mobile: scroll', { direction: 'down' });
        return await $(locator).isDisplayed();
      },
    );

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tried to change scroll logic with your or similar solutions, but after testing, the current implementation is less flak, at least in the local environment.

Expand All @@ -67,7 +69,7 @@ class Utils {
action: 'release',
},
]);
elementIsFound = await driver.$(locator).isDisplayed();
elementIsFound = await $(locator).isClickable();
}
} catch (err) {
console.log('Element is not found');
Expand Down
Loading
Loading