Skip to content

Commit

Permalink
Merge pull request #1446 from zhyd1997/ci/ticket-889-1700974455106
Browse files Browse the repository at this point in the history
ci: fixed detox tests.
  • Loading branch information
mshima authored Feb 22, 2024
2 parents 7a78816 + 03d824c commit ff342b5
Show file tree
Hide file tree
Showing 19 changed files with 204 additions and 59 deletions.
108 changes: 108 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/configuration-reference
version: 2.1

orbs:
# The Node.js orb contains a set of prepackaged CircleCI configuration you can utilize
# Orbs reduce the amount of configuration required for common tasks.
# See the orb documentation here: https://circleci.com/developer/orbs/orb/circleci/node
node: circleci/[email protected]
macos: circleci/macos@2

jobs:
# Below is the definition of your job to build and test your app, you can rename and customize it as you want.
generate:
# These next lines define a Docker executor: https://circleci.com/docs/executor-types/
# You can specify an image from Dockerhub or use one of our Convenience Images from CircleCI's Developer Hub.
# A list of available CircleCI Docker Convenience Images are available here: https://circleci.com/developer/images/image/cimg/node
macos:
xcode: 15.1.0
environment:
GITHUB_WORKSPACE: '.'
JHI_REACT_NATIVE_APP_NAME: 'JwtHealthPointsApp'
JHI_AUTH_TYPE: 'jwt'
JHI_DTO: 'false'
JHIPSTER_VERSION: 7
JHI_ENTITY_JDL: 'entities-21points.jdl'
SCRIPT_DIR: ./test/scripts
PLATFORM: ios
JHI_RECORD_VIDEO: ${{ github.event.inputs.recordVideo || 'false' }}
JHI_SCREENSHOTS: ${{ github.event.inputs.screenshots || 'false' }}
# Then run your tests!
# CircleCI will report the results back to your VCS provider.
steps:
# Checkout the code as the first step.
- checkout
- node/install:
node-version: '16'
- run: node --version
- run: git --no-pager log -n 10 --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue) <%an>%Creset' --abbrev-commit
- run:
name: Install Homebrew
command: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- run:
name: Verify Homebrew installation
command: brew --version && brew update
# - run:
# name: Install Java 11
# command: brew install java11 && sudo ln -sfn /usr/local/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk
# - run:
# name: Verify Java Version
# command: java --version
- run:
name: 'TOOLS: installing Detox and its dependencies'
command: $SCRIPT_DIR/install-detox.sh
- run:
name: Config git variables
command: $SCRIPT_DIR/git-config.sh
- run:
name: 'TOOLS: install node dependencies'
command: $SCRIPT_DIR/install-node-dependencies.sh
# - node/install-packages:
# # If you are using yarn, change the line below from "npm" to "yarn"
# pkg-manager: npm
- run:
name: 'TOOLS: display tools'
command: $SCRIPT_DIR/display-tools.sh
- run:
name: 'TOOLS: npm install and link in generator-jhipster-react-native'
command: npm i && npm link
- run:
name: 'SETUP: copy the JDL file for the backend and app'
command: $SCRIPT_DIR/copy-jdl-file.sh
- run:
name: 'GENERATING: generate jhipster backend'
command: $SCRIPT_DIR/generate-jhipster-backend.sh
- run:
name: 'GENERATING: generate react-native app'
command: $SCRIPT_DIR/generate-react-native-app.sh
# - macos/preboot-simulator:
# version: "17.0"
# platform: "iOS"
# device: "iPhone 15"
- run:
name: 'TESTING: run detox tests'
command: pwd && ls && $SCRIPT_DIR/run-detox-tests.sh
- run:
name: 'TESTING: rename detox screenshots to a valid filename'
command: $SCRIPT_DIR/rename-detox-screenshots.sh
# Next, the node orb's install-packages step will install the dependencies from a package.json.
# The orb install-packages step will also automatically cache them for faster future runs.
# - node/install-packages:
# # If you are using yarn, change the line below from "npm" to "yarn"
# pkg-manager: npm

workflows:
# Below is the definition of your workflow.
# Inside the workflow, you provide the jobs you want to run, e.g this workflow runs the build-and-test job above.
# CircleCI will run this workflow on every commit.
# For more details on extending your workflow, see the configuration docs: https://circleci.com/docs/configuration-reference/#workflows
iOS-E2E:
jobs:
- generate
# # - jhipster
# - generate:
# requires:
# - jhipster
# For running simple node tests, you could optionally use the node/test job from the orb to replicate and replace the job above in fewer lines.
# - node/test
23 changes: 21 additions & 2 deletions .github/workflows/ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ concurrency:
# Cancel intermediate pull request builds
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
jobs:
generate:
applications:
name: e2e-${{ matrix.app_type }}-${{ matrix.jhipster_version }}
runs-on: macos-12
runs-on: macos-13
if: "!contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.pull_request.title, '[skip ci]') && !contains(github.event.pull_request.title, '[ci skip]') && !contains(github.event.ref_type, '[tag]')"
timeout-minutes: 90
strategy:
Expand Down Expand Up @@ -84,6 +84,9 @@ jobs:
name: Config git variables
- run: $SCRIPT_DIR/install-node-dependencies.sh
name: 'TOOLS: install node dependencies'
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest
- uses: nick-invision/[email protected]
name: 'TOOLS: installing Detox and its dependencies'
with:
Expand Down Expand Up @@ -113,3 +116,19 @@ jobs:
${{ runner.workspace }}/${{ matrix.app_type }}/**/*
!${{ runner.workspace }}/${{ matrix.app_type }}/node_modules
!${{ runner.workspace }}/${{ matrix.app_type }}/e2e/Exponent.app
ios-result:
permissions:
contents: none
runs-on: ubuntu-latest
needs: [applications]
if: always()
steps:
- run: |
echo '${{ toJSON(needs) }}'
if ([ 'skipped' == '${{ needs.applications.result }}' ] || [ 'success' == '${{ needs.applications.result }}' ]); then
exit 0
fi
if [ 'closed' == '${{ github.event.action }}' ]; then
exit 0
fi
exit 1
1 change: 0 additions & 1 deletion generators/app/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,6 @@ const files = {
condition: generator => generator.context.detox === true,
templates: [
'.detoxrc.json',
'e2e/environment.js',
'e2e/config.json',
'e2e/home-screen.spec.js',
'e2e/utils.js',
Expand Down
2 changes: 1 addition & 1 deletion generators/app/resources/expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"expo-web-browser": "~12.3.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.72.6",
"react-native": "0.72.10",
"react-native-gesture-handler": "~2.12.0",
"react-native-reanimated": "~3.3.0",
"react-native-safe-area-context": "4.6.3",
Expand Down
26 changes: 21 additions & 5 deletions generators/app/templates/.detoxrc.json.ejs
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
{
"configurations": {
"ios.sim.release": {
"device": "simulator",
"app": "myApp.ios",
}
},
"apps": {
"myApp.ios": {
"type": "ios.app",
"binaryPath": "e2e/Exponent.app",
},
},
"devices": {
"simulator": {
"type": "ios.simulator",
"device": {
"type": "iPhone 12"
}
}
"type": "iPhone 15",
},
},
},
"artifacts": {
"rootDir": ".artifacts",
Expand All @@ -20,6 +31,11 @@
}
}
},
"test-runner": "jest",
"runner-config": "./e2e/config.json"
"testRunner": {
"$0": "jest",
"args": {
"config": "./e2e/config.json"
},
"_": ["e2e"]
}
}
3 changes: 2 additions & 1 deletion generators/app/templates/app/navigation/entity-stack.js.ejs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { createStackNavigator, HeaderBackButton } from '@react-navigation/stack';
import { createStackNavigator } from '@react-navigation/stack';
import { HeaderBackButton } from '@react-navigation/elements';
import { Ionicons } from '@expo/vector-icons';

import { DrawerButton } from './drawer/drawer-button';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const {
waitThenTapButton,
} = require('../utils');

describe('Change Password Screen Tests', () => {
describe.skip('Change Password Screen Tests', () => {
const password = process.env.E2E_PASSWORD || 'user';
const updatedPassword = process.env.E2E_NEW_PASSWORD || 'new-password';

Expand Down
10 changes: 7 additions & 3 deletions generators/app/templates/e2e/config.json.ejs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{
"testEnvironment": "./environment",
"rootDir": "..",
"testMatch": ["<rootDir>/e2e/**/*.spec.js"],
"reporters": ["detox/runners/jest/reporter"],
"testEnvironment": "detox/runners/jest/testEnvironment",
"globalSetup": "detox/runners/jest/globalSetup",
"globalTeardown": "detox/runners/jest/globalTeardown",
"testRunner": "jest-circus/runner",
"testTimeout": 300000,
"testRegex": "\\.spec\\.js$",
"reporters": ["detox/runners/jest/streamlineReporter"],
"maxWorkers": 1,
"verbose": true
}
21 changes: 0 additions & 21 deletions generators/app/templates/e2e/environment.js.ejs

This file was deleted.

2 changes: 1 addition & 1 deletion generators/app/templates/e2e/scripts/download-expo.sh.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ if [ ! -d $APP_PATH ]; then
mkdir $APP_PATH

# query expo.io to find most recent ipaUrl
IPA_URL=$(curl --silent --show-error https://expo.io/--/api/v2/versions | jq -r ".iosUrl")
IPA_URL=$(curl --silent --show-error https://expo.io/--/api/v2/versions | jq -r '.sdkVersions."49.0.0".iosClientUrl')

# download tar.gz
TMP_PATH=./exponent.tar.gz
Expand Down
4 changes: 2 additions & 2 deletions generators/app/templates/e2e/scripts/setup.sh.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ echo 'Checking for Expo App...'
./e2e/scripts/download-expo.sh

# get ios device name from detox config
IOS_DEVICE_NAME=$(cat .detoxrc.json | jq -rc '.configurations | .[] | .device | .type')
IOS_DEVICE_NAME=$(cat .detoxrc.json | jq -rc '.devices | .[] | .device | .type')
# get simulator matching that name
DEVICE_ID=$(xcrun simctl list devices -j | jq -rc ".[] | .[] | .[] | select( .name == \"$IOS_DEVICE_NAME\" ) | select( .isAvailable == true ) | .udid")

Expand All @@ -18,7 +18,7 @@ xcrun simctl install $DEVICE_ID e2e/Exponent.app

echo 'Fetching App Bundle from Expo Packager...'
# warm up the app - prebuild the bundle with dev=false and minify=true, otherwise it times out at start of detox test
rep=$(curl -fs "http://127.0.0.1:19000/node_modules/expo/AppEntry.bundle?platform=ios&dev=false&hot=false&minify=true")
rep=$(curl -fs "http://127.0.0.1:8081/node_modules/expo/AppEntry.bundle?platform=ios&dev=false&hot=false&minify=true")
status=$?

if [ "$status" -ne 0 ]; then
Expand Down
47 changes: 34 additions & 13 deletions generators/app/templates/e2e/utils.js.ejs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const DetoxExpoHelpers = require('@ruddell/detox-expo-helpers');

const execSync = require('child_process').execSync;
const username = process.env.E2E_USERNAME || 'user';
const password = process.env.E2E_PASSWORD || 'user';
const expoPublishedUrl = process.env.E2E_EXPO_URL || 'exp://localhost:19000';
const expoPublishedUrl = process.env.E2E_EXPO_URL || 'exp://localhost:8081';

const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

Expand All @@ -12,6 +11,7 @@ const waitThenTapButton = async (buttonId, ms = 1000) => {
};

const openAndTapDrawerMenuItemByLabel = async (label) => {
await wait(2000);
// matching the drawer button is flaky, so open it with a swipe from the left
await element(by.id('drawerButtonWrapper')).atIndex(0).swipe('right', 'fast', 0.7, 0.01);
await waitForElementToBeVisibleById('drawerContentScrollView');
Expand Down Expand Up @@ -77,7 +77,7 @@ const toggleSwitchToValue = async (switchId, targetValue) => {
const scrollTo = async (fieldId, listId, size = 0.15, direction = 'up', speed = 'slow') => {
await waitFor(element(by.id(fieldId)))
.toBeVisible()
.whileElement(by.type('ABI42_0_0RCTCustomScrollView').withAncestor(by.id(listId)))
.whileElement(by.type('ABI49_0_0RCTScrollView').withAncestor(by.id(listId)))
.scroll(500, 'down');
};

Expand Down Expand Up @@ -105,20 +105,41 @@ const waitForElementToBeVisibleById = async (elementId, timeout = 5000) => {
await waitFor(element(by.id(elementId))).toBeVisible().withTimeout(timeout);
}

const closeDeveloperMenu = async () => {
await wait(3000);

await waitFor(element(by.text('Continue')))
.toBeVisible()
.withTimeout(3000);
await element(by.text('Continue')).tap();

await waitFor(element(by.text('Reload')))
.toBeVisible()
.withTimeout(3000);
await element(by.text('Reload')).tap();

await wait(3000);
};

const reloadApp = async (bailOnFailure) => {
try {
// disabling Detox synchronization - broken for Expo apps in Detox 18+, speeds up tests at the cost of using waitFor
await DetoxExpoHelpers.reloadApp({ url: expoPublishedUrl, launchArgs: { detoxEnableSynchronization: false } });
// if you eject from expo, you should replace the line above with:
// device.reloadReactNative()
await waitForElementToBeVisibleById('homeScreen', 15000);
await waitForElementToBeVisibleById('drawerButton', 15000);
if (device.getPlatform() === 'ios') {
// disable password autofill
execSync(
`plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles/Library/ConfigurationProfiles/UserSettings.plist`,
);
execSync(
`plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/EffectiveUserSettings.plist`,
);
execSync(
`plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/${device.id}/data/Library/UserConfigurationProfiles/PublicInfo/PublicEffectiveUserSettings.plist`,
);
}
await device.launchApp({ url: expoPublishedUrl, newInstance: true, launchArgs: { detoxEnableSynchronization: false } });
await closeDeveloperMenu();
} catch (e) {
console.warn('Reloading app failed, retrying once');
console.warn(e);
if (!bailOnFailure) {
await reloadApp(true);
}
}
};

Expand Down
2 changes: 0 additions & 2 deletions generators/app/templates/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
},
"devDependencies": {
"@react-native-community/eslint-config": "3.2.0",
"@ruddell/detox-expo-helpers": "0.7.0",
"@storybook/addons": "7.6.13",
"@storybook/react-native": "6.5.7",
"@storybook/theming": "7.6.13",
Expand All @@ -48,7 +47,6 @@
"eslint-config-prettier": "9.1.0",
"eslint-plugin-prettier": "4.2.1",
"expect": "29.7.0",
"expo-detox-hook": "1.0.10",
"jest": "29.7.0",
"jest-circus": "29.7.0",
"lint-staged": "15.2.2",
Expand Down
2 changes: 0 additions & 2 deletions generators/app/templates/package.json.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@
"buffer": "REPLACE_WITH_VERSION",
<%_ if (context.detox) { _%>
"detox": "REPLACE_WITH_VERSION",
"@ruddell/detox-expo-helpers": "REPLACE_WITH_VERSION",
"expo-detox-hook": "REPLACE_WITH_VERSION",
"jest-circus": "REPLACE_WITH_VERSION",
<%_ } _%>
"eslint": "REPLACE_WITH_VERSION",
Expand Down
Loading

0 comments on commit ff342b5

Please sign in to comment.