diff --git a/.detoxrc.js b/.detoxrc.js index 9d62e1c0a..042511a0a 100644 --- a/.detoxrc.js +++ b/.detoxrc.js @@ -1,3 +1,6 @@ +// run iPhone 14 on local machine, iPhone 15 Pro on mac mini +const iOSDevice = process.env.MACMINI ? 'iPhone 15 Pro' : 'iPhone 14'; + module.exports = { testRunner: { $0: 'jest', @@ -37,7 +40,7 @@ module.exports = { simulator: { type: 'ios.simulator', device: { - type: 'iPhone 14 Pro', + type: iOSDevice, }, }, emulator: { diff --git a/.github/workflows/e2e-ios-macmini.yml b/.github/workflows/e2e-ios-macmini.yml new file mode 100644 index 000000000..0e4c7241d --- /dev/null +++ b/.github/workflows/e2e-ios-macmini.yml @@ -0,0 +1,106 @@ +name: e2e-ios-macmini + +on: pull_request + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + NO_FLIPPER: 1 + E2E_TESTS: 1 # build without transform-remove-console babel plugin + DEBUG: 'lnurl* lnurl server' + MACMINI: 1 # use iPhone 15 in .detoxrc + +jobs: + e2e: + runs-on: self-hosted + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 1 + + - name: Reset testing enviroment + continue-on-error: true + run: | + pkill -f react-native || echo 0 + pkill -f Simulator || echo 0 + rm -rf /tmp/lock/* + cd docker && docker compose down -v + + - name: Docker info + run: | + docker --version + docker volume ls + docker ps + + - name: Run regtest setup + run: | + cd docker + mkdir lnd && chmod 777 lnd + docker-compose pull --quiet + docker compose up -d + + - name: Wait for electrum server + timeout-minutes: 10 + run: while ! nc -z '127.0.0.1' 60001; do sleep 1; done + + - name: Activate enviroment variables + run: cp .env.test.template .env + + - name: Yarn Install + run: yarn --no-audit --prefer-offline || yarn --no-audit --prefer-offline + env: + HUSKY: 0 + + - name: Pod Install + run: pod install --project-directory=ios || pod install --project-directory=ios + + - name: Build + run: yarn e2e:build:ios-release || yarn e2e:build:ios-release + + - name: Test attempt 1 + continue-on-error: true + id: test1 + run: yarn e2e:test:ios-release --record-videos all --take-screenshots all --record-logs all + + - name: Test attempt 2 + continue-on-error: true + id: test2 + if: steps.test1.outcome != 'success' + run: yarn e2e:test:ios-release --record-videos all --take-screenshots all --record-logs all + + - name: Test attempt 3 + continue-on-error: true + id: test3 + if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success' + run: yarn e2e:test:ios-release --record-videos all --take-screenshots all --record-logs all + + - name: Restart docker before last attempt + if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success' && steps.test3.outcome != 'success' + run: | + cd docker && docker compose down -t 60 && docker compose up --quiet-pull -d && cd .. + while ! nc -z '127.0.0.1' 60001; do sleep 1; done + + - name: Test attempt 4 + id: test4 + if: steps.test1.outcome != 'success' && steps.test2.outcome != 'success' && steps.test3.outcome != 'success' + run: yarn e2e:test:ios-release --record-videos all --take-screenshots all --record-logs all + + - uses: actions/upload-artifact@v3 + if: failure() + # if: ${{ always() }} + with: + name: e2e-test-videos + path: ./artifacts/ + + - name: Dump docker logs on failure + if: failure() + uses: jwalton/gh-docker-logs@v2 + + - name: Clean docker + if: ${{ always() }} + run: | + cd docker && docker compose down -v diff --git a/e2e/helpers.js b/e2e/helpers.js index c1e6de14b..80bc4b0f2 100644 --- a/e2e/helpers.js +++ b/e2e/helpers.js @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; -const LOCK_PATH = '/tmp/'; +const LOCK_PATH = '/tmp/lock/'; export const bitcoinURL = 'http://polaruser:polarpass@127.0.0.1:43782'; export const electrumHost = '127.0.0.1'; @@ -31,6 +31,7 @@ export const markComplete = (name) => { return; } + fs.mkdirSync(LOCK_PATH, { recursive: true }); fs.writeFileSync(path.join(LOCK_PATH, 'lock-' + name), '1'); }; @@ -97,6 +98,9 @@ export const launchAndWait = async () => { }); // wait for AssetsTitle to appear and be accessible + await waitFor(element(by.id('AssetsTitle'))) + .toBeVisible() + .withTimeout(300000); // 5 min for (let i = 0; i < 60; i++) { try { await element(by.id('AssetsTitle')).tap(); diff --git a/e2e/settings.e2e.js b/e2e/settings.e2e.js index 90216c9e8..fea176d29 100644 --- a/e2e/settings.e2e.js +++ b/e2e/settings.e2e.js @@ -1,5 +1,4 @@ import jestExpect from 'expect'; -import parse from 'url-parse'; import { sleep, @@ -537,12 +536,8 @@ d('Settings', () => { by.id('ConnectedUrl'), ).getAttributes(); - // add port to url - const url = parse(origRelay, true); - url.set('hostname', url.hostname + ':443'); - const relayUrl = url.toString(); - - await element(by.id('UrlInput')).replaceText(relayUrl); + const alteredRelay = origRelay + '/'; + await element(by.id('UrlInput')).replaceText(alteredRelay); await element(by.id('Status')).tap(); // close keyboard await element(by.id('ConnectToUrl')).tap(); await sleep(1000); @@ -552,7 +547,7 @@ d('Settings', () => { by.id('ConnectedUrl'), ).getAttributes(); - jestExpect(newRelay).toBe(relayUrl); + jestExpect(newRelay).toBe(alteredRelay); // now change it back await element(by.id('UrlInput')).replaceText(origRelay);