@purchasely/cordova-plugin-purchasely 5.7.2 → 6.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -8
- package/__tests__/Purchasely.test.js +307 -92
- package/example/config.xml +0 -10
- package/example/e2e/README.md +44 -0
- package/example/e2e/helpers/driver.js +70 -0
- package/example/e2e/package.json +19 -0
- package/example/e2e/specs/bridge.e2e.js +51 -0
- package/example/e2e/specs/dismiss.e2e.js +37 -0
- package/example/e2e/tools/ci_run_e2e.sh +49 -0
- package/example/e2e/tools/ci_run_e2e_ios.sh +46 -0
- package/example/e2e/wdio.android.conf.js +21 -0
- package/example/e2e/wdio.ios.conf.js +19 -0
- package/example/e2e/wdio.shared.conf.js +28 -0
- package/example/package-lock.json +66 -209
- package/example/package.json +9 -5
- package/example/www/index.html +1 -7
- package/example/www/js/index.js +113 -92
- package/package.json +1 -1
- package/plugin.xml +3 -22
- package/src/android/PurchaselyPlugin.kt +529 -440
- package/src/ios/CDVPurchasely+Events.h +1 -1
- package/src/ios/CDVPurchasely+UserAttributes.h +1 -1
- package/src/ios/CDVPurchasely+UserAttributes.m +2 -0
- package/src/ios/CDVPurchasely.h +21 -16
- package/src/ios/CDVPurchasely.m +493 -257
- package/www/Purchasely.js +208 -40
- package/src/android/PLYProductActivity.kt +0 -168
- package/src/android/PLYSubscriptionsActivity.java +0 -37
- package/src/android/activity_ply_product_activity.xml +0 -6
- package/src/android/activity_ply_subscriptions_activity.xml +0 -6
- package/src/android/theme_purchasely_fullscreen.xml +0 -6
- package/src/android/theme_purchasely_fullscreen_v23.xml +0 -6
- package/src/android/theme_purchasely_fullscreen_v23_light_status_bar.xml +0 -7
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Purchasely Cordova — End-to-End tests
|
|
2
|
+
|
|
3
|
+
Device-level E2E tests for the example app, driving the **real** Purchasely 6.0 native
|
|
4
|
+
SDK through the Cordova bridge. Built with **Appium + WebdriverIO**:
|
|
5
|
+
|
|
6
|
+
- **WEBVIEW context** — calls `window.Purchasely.*` and asserts the results directly
|
|
7
|
+
(the deterministic `bridge` suite).
|
|
8
|
+
- **NATIVE_APP context** — injects OS-level touches (interceptor / dismiss suites).
|
|
9
|
+
|
|
10
|
+
These mirror the Flutter `integration_test` suite (`E2E_TEST_INDEX.md`) adapted to the
|
|
11
|
+
Cordova imperative API. They are **not** part of the PR-gating `ci.yml`; they run via the
|
|
12
|
+
`E2E Android` / `E2E iOS` workflows (`workflow_dispatch`, nightly `schedule`, and scoped
|
|
13
|
+
`pull_request`).
|
|
14
|
+
|
|
15
|
+
## Suites & gating
|
|
16
|
+
|
|
17
|
+
| Suite | File | Gate | Notes |
|
|
18
|
+
|-------|------|------|-------|
|
|
19
|
+
| bridge | `specs/bridge.e2e.js` | **hard** | anonymous id, allProducts, fetchPresentationForPlacement, synchronize completion, user-attribute round-trip |
|
|
20
|
+
| dismiss | `specs/dismiss.e2e.js` | best-effort | present placement + programmatic close → dismiss outcome + `closeReason` (needs a paywall to render) |
|
|
21
|
+
|
|
22
|
+
Best-effort suites emit `::warning::` on failure and do not fail the job (native/paywall
|
|
23
|
+
rendering is flaky in CI — same policy as the Flutter suite). Each suite retries up to 3×.
|
|
24
|
+
|
|
25
|
+
## Requirements to go green
|
|
26
|
+
|
|
27
|
+
1. The placement `PURCHASELY_E2E_PLACEMENT` (default `ONBOARDING`) must exist on the
|
|
28
|
+
backend the example API key (`www/js/index.js`) points to, for app id
|
|
29
|
+
`com.purchasely.demo`. Override with the env var if your integration placement differs.
|
|
30
|
+
2. Android: an emulator with Google APIs (the workflow uses API 34, `pixel_6`).
|
|
31
|
+
3. iOS: an iPhone 16/15 simulator (the workflow discovers one).
|
|
32
|
+
|
|
33
|
+
## Run locally
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Android (emulator already booted, apk already built via `cordova build android`)
|
|
37
|
+
cd purchasely/example/e2e && npm install
|
|
38
|
+
bash ./tools/ci_run_e2e.sh emulator-5554
|
|
39
|
+
|
|
40
|
+
# iOS (simulator booted, app built via `cordova build ios --emulator`)
|
|
41
|
+
bash ./tools/ci_run_e2e_ios.sh <simulator-udid>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Logs are written to `purchasely/example/e2e/ci-logs/` (uploaded as CI artifacts).
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Helpers for driving the Purchasely Cordova example app under Appium/WebdriverIO.
|
|
2
|
+
//
|
|
3
|
+
// Two contexts are used:
|
|
4
|
+
// * WEBVIEW — run JS against `window.Purchasely` (the cordova.exec bridge) and read
|
|
5
|
+
// results directly; used for the deterministic "bridge" assertions.
|
|
6
|
+
// * NATIVE_APP — inject OS-level touches (tap purchase button, press back) for the
|
|
7
|
+
// interceptor / dismiss suites.
|
|
8
|
+
|
|
9
|
+
async function switchToWebview() {
|
|
10
|
+
await browser.waitUntil(async () => {
|
|
11
|
+
const contexts = await browser.getContexts();
|
|
12
|
+
return contexts.some((c) => (typeof c === 'string' ? c : c.id).includes('WEBVIEW'));
|
|
13
|
+
}, { timeout: 60000, timeoutMsg: 'WEBVIEW context never appeared' });
|
|
14
|
+
|
|
15
|
+
const contexts = await browser.getContexts();
|
|
16
|
+
const webview = contexts
|
|
17
|
+
.map((c) => (typeof c === 'string' ? c : c.id))
|
|
18
|
+
.find((id) => id.includes('WEBVIEW'));
|
|
19
|
+
await browser.switchContext(webview);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function switchToNative() {
|
|
23
|
+
await browser.switchContext('NATIVE_APP');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Wait until the Purchasely bridge is available (deviceready fired + plugin clobbered).
|
|
27
|
+
async function waitForPurchaselyReady() {
|
|
28
|
+
await switchToWebview();
|
|
29
|
+
await browser.waitUntil(
|
|
30
|
+
async () => browser.execute(() => typeof window.Purchasely !== 'undefined'),
|
|
31
|
+
{ timeout: 60000, timeoutMsg: 'window.Purchasely never became available' }
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Invoke a Purchasely method that takes trailing (success, error) callbacks and resolve
|
|
36
|
+
// with { ok, value } on success or { ok:false, error } on error. `args` are the leading
|
|
37
|
+
// positional arguments before the callbacks.
|
|
38
|
+
async function callBridge(method, args = [], timeoutMs = 30000) {
|
|
39
|
+
return browser.executeAsync(
|
|
40
|
+
function (method, args, timeoutMs, done) {
|
|
41
|
+
var settled = false;
|
|
42
|
+
var finish = function (payload) {
|
|
43
|
+
if (settled) return;
|
|
44
|
+
settled = true;
|
|
45
|
+
done(payload);
|
|
46
|
+
};
|
|
47
|
+
setTimeout(function () { finish({ ok: false, error: 'timeout' }); }, timeoutMs);
|
|
48
|
+
try {
|
|
49
|
+
var fn = window.Purchasely[method];
|
|
50
|
+
if (typeof fn !== 'function') {
|
|
51
|
+
return finish({ ok: false, error: 'no such method: ' + method });
|
|
52
|
+
}
|
|
53
|
+
fn.apply(
|
|
54
|
+
window.Purchasely,
|
|
55
|
+
args.concat([
|
|
56
|
+
function (value) { finish({ ok: true, value: value }); },
|
|
57
|
+
function (error) { finish({ ok: false, error: String(error) }); },
|
|
58
|
+
])
|
|
59
|
+
);
|
|
60
|
+
} catch (e) {
|
|
61
|
+
finish({ ok: false, error: String(e) });
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
method,
|
|
65
|
+
args,
|
|
66
|
+
timeoutMs
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { switchToWebview, switchToNative, waitForPurchaselyReady, callBridge };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "purchasely-cordova-e2e",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "End-to-end tests for the Purchasely Cordova example app (Appium + WebdriverIO). Drives the real native Purchasely 6.0 SDK inside the WebView (bridge assertions) and injects OS-level touches (interceptor / dismiss).",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test:android": "wdio run ./wdio.android.conf.js",
|
|
8
|
+
"test:ios": "wdio run ./wdio.ios.conf.js"
|
|
9
|
+
},
|
|
10
|
+
"devDependencies": {
|
|
11
|
+
"@wdio/cli": "^9.0.0",
|
|
12
|
+
"@wdio/local-runner": "^9.0.0",
|
|
13
|
+
"@wdio/mocha-framework": "^9.0.0",
|
|
14
|
+
"@wdio/spec-reporter": "^9.0.0",
|
|
15
|
+
"appium": "^2.11.0",
|
|
16
|
+
"appium-uiautomator2-driver": "^3.9.0",
|
|
17
|
+
"appium-xcuitest-driver": "^7.28.0"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Deterministic Dart<->native bridge assertions (no native taps). HARD gate — these
|
|
2
|
+
// must pass. Mirrors the Flutter E2E_TEST_INDEX suite T1/T3/T5/T6 adapted to the
|
|
3
|
+
// Cordova imperative API.
|
|
4
|
+
const { waitForPurchaselyReady, callBridge } = require('../helpers/driver');
|
|
5
|
+
|
|
6
|
+
const PLACEMENT = process.env.PURCHASELY_E2E_PLACEMENT || 'ONBOARDING';
|
|
7
|
+
|
|
8
|
+
describe('Purchasely bridge (WEBVIEW context)', () => {
|
|
9
|
+
before(async () => {
|
|
10
|
+
await waitForPurchaselyReady();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// T1 — anonymous user id
|
|
14
|
+
it('getAnonymousUserId returns a non-empty id', async () => {
|
|
15
|
+
const res = await callBridge('getAnonymousUserId');
|
|
16
|
+
expect(res.ok).toBe(true);
|
|
17
|
+
expect(typeof res.value).toBe('string');
|
|
18
|
+
expect(res.value.length).toBeGreaterThan(0);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// T5 — catalog
|
|
22
|
+
it('allProducts returns a list', async () => {
|
|
23
|
+
const res = await callBridge('allProducts');
|
|
24
|
+
expect(res.ok).toBe(true);
|
|
25
|
+
expect(Array.isArray(res.value)).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// T3 — preload a presentation for a placement
|
|
29
|
+
it('fetchPresentationForPlacement returns a presentation object', async () => {
|
|
30
|
+
const res = await callBridge('fetchPresentationForPlacement', [PLACEMENT, null]);
|
|
31
|
+
expect(res.ok).toBe(true);
|
|
32
|
+
expect(res.value).toBeDefined();
|
|
33
|
+
// v6 presentation carries an id/type so it can later be displayed.
|
|
34
|
+
expect(res.value === null || typeof res.value === 'object').toBe(true);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// T6 — synchronize now reports completion (v6 change). On a bare emulator/simulator
|
|
38
|
+
// with no billing, exactly one of success/error must fire (no fire-and-forget).
|
|
39
|
+
it('synchronize resolves exactly one callback', async () => {
|
|
40
|
+
const res = await callBridge('synchronize');
|
|
41
|
+
expect(typeof res.ok).toBe('boolean');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// user-attribute round-trip (set then read back)
|
|
45
|
+
it('setUserAttributeWithString then userAttribute round-trips', async () => {
|
|
46
|
+
await callBridge('setUserAttributeWithString', ['e2e_key', 'e2e_value', 'ESSENTIAL']);
|
|
47
|
+
const res = await callBridge('userAttribute', ['e2e_key']);
|
|
48
|
+
expect(res.ok).toBe(true);
|
|
49
|
+
expect(res.value).toBe('e2e_value');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Presentation display + dismiss outcome. BEST-EFFORT (non-blocking in CI): depends on
|
|
2
|
+
// a paywall actually rendering for the configured placement against the real backend.
|
|
3
|
+
// Mirrors E2E_TEST_INDEX T8/T12 adapted to the Cordova imperative API.
|
|
4
|
+
const { waitForPurchaselyReady, callBridge, switchToNative } = require('../helpers/driver');
|
|
5
|
+
|
|
6
|
+
const PLACEMENT = process.env.PURCHASELY_E2E_PLACEMENT || 'ONBOARDING';
|
|
7
|
+
|
|
8
|
+
describe('Presentation dismiss outcome', () => {
|
|
9
|
+
before(async () => {
|
|
10
|
+
await waitForPurchaselyReady();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// T8/T12 — the present* success callback IS the per-presentation dismiss outcome.
|
|
14
|
+
// Present a placement, close it programmatically, and assert the outcome fires with a
|
|
15
|
+
// closeReason.
|
|
16
|
+
it('presentPresentationForPlacement + closePresentation delivers a dismiss outcome', async () => {
|
|
17
|
+
// Kick off the presentation; do NOT await (the callback resolves at dismiss).
|
|
18
|
+
const outcomePromise = callBridge(
|
|
19
|
+
'presentPresentationForPlacement',
|
|
20
|
+
[PLACEMENT, null, 'fullScreen'],
|
|
21
|
+
90000
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Give the paywall time to render, then close it programmatically from the bridge.
|
|
25
|
+
await browser.pause(6000);
|
|
26
|
+
await callBridge('closePresentation');
|
|
27
|
+
|
|
28
|
+
const outcome = await outcomePromise;
|
|
29
|
+
expect(outcome.ok).toBe(true);
|
|
30
|
+
expect(outcome.value).toBeDefined();
|
|
31
|
+
// v6 outcome carries a closeReason; programmatic close => 'programmatic' (Android).
|
|
32
|
+
if (outcome.value && outcome.value.closeReason) {
|
|
33
|
+
expect(typeof outcome.value.closeReason).toBe('string');
|
|
34
|
+
}
|
|
35
|
+
await switchToNative().catch(() => {});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Android E2E runner. Assumes:
|
|
3
|
+
# * an emulator is already booted (serial passed as $1, e.g. emulator-5554)
|
|
4
|
+
# * the debug apk has been built (cordova build android)
|
|
5
|
+
# * node deps for purchasely/example/e2e are installed
|
|
6
|
+
#
|
|
7
|
+
# Gating mirrors the Flutter suite: the deterministic `bridge` suite HARD-gates the job;
|
|
8
|
+
# `dismiss` (needs a paywall to render against the real backend) is BEST-EFFORT and only
|
|
9
|
+
# emits ::warning:: on failure.
|
|
10
|
+
set -uo pipefail
|
|
11
|
+
|
|
12
|
+
SERIAL="${1:-emulator-5554}"
|
|
13
|
+
HERE="$(cd "$(dirname "$0")/.." && pwd)"
|
|
14
|
+
LOGDIR="$HERE/ci-logs"
|
|
15
|
+
mkdir -p "$LOGDIR"
|
|
16
|
+
export ANDROID_SERIAL="$SERIAL"
|
|
17
|
+
|
|
18
|
+
echo "== Starting Appium =="
|
|
19
|
+
npx appium --log "$LOGDIR/appium-android.log" --log-level info &
|
|
20
|
+
APPIUM_PID=$!
|
|
21
|
+
trap 'kill $APPIUM_PID 2>/dev/null || true' EXIT
|
|
22
|
+
# Wait for Appium to accept connections.
|
|
23
|
+
for i in $(seq 1 30); do
|
|
24
|
+
curl -sf http://127.0.0.1:4723/status >/dev/null 2>&1 && break
|
|
25
|
+
sleep 1
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
run_suite() { # $1 = spec glob, $2 = hard|soft
|
|
29
|
+
local spec="$1" gate="$2" tries=3 n=1
|
|
30
|
+
while [ $n -le $tries ]; do
|
|
31
|
+
echo "== [$gate] $spec (attempt $n/$tries) =="
|
|
32
|
+
if PURCHASELY_E2E_SPEC="$spec" npx wdio run ./wdio.android.conf.js --spec "$spec" 2>&1 | tee "$LOGDIR/wdio-$(basename "$spec").log"; then
|
|
33
|
+
return 0
|
|
34
|
+
fi
|
|
35
|
+
n=$((n+1))
|
|
36
|
+
done
|
|
37
|
+
if [ "$gate" = "hard" ]; then
|
|
38
|
+
echo "::error::E2E suite failed (hard gate): $spec"
|
|
39
|
+
return 1
|
|
40
|
+
fi
|
|
41
|
+
echo "::warning::E2E suite failed (best-effort): $spec"
|
|
42
|
+
return 0
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
cd "$HERE"
|
|
46
|
+
rc=0
|
|
47
|
+
run_suite "./specs/bridge.e2e.js" hard || rc=1
|
|
48
|
+
run_suite "./specs/dismiss.e2e.js" soft || true
|
|
49
|
+
exit $rc
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# iOS E2E runner. Assumes:
|
|
3
|
+
# * a simulator is already booted (udid passed as $1)
|
|
4
|
+
# * the simulator .app has been built (cordova build ios --emulator)
|
|
5
|
+
# * node deps for purchasely/example/e2e are installed
|
|
6
|
+
#
|
|
7
|
+
# Same gating as Android: `bridge` HARD-gates; `dismiss` is BEST-EFFORT.
|
|
8
|
+
set -uo pipefail
|
|
9
|
+
|
|
10
|
+
UDID="${1:-booted}"
|
|
11
|
+
HERE="$(cd "$(dirname "$0")/.." && pwd)"
|
|
12
|
+
LOGDIR="$HERE/ci-logs"
|
|
13
|
+
mkdir -p "$LOGDIR"
|
|
14
|
+
export PURCHASELY_E2E_UDID="$UDID"
|
|
15
|
+
|
|
16
|
+
echo "== Starting Appium =="
|
|
17
|
+
npx appium --log "$LOGDIR/appium-ios.log" --log-level info &
|
|
18
|
+
APPIUM_PID=$!
|
|
19
|
+
trap 'kill $APPIUM_PID 2>/dev/null || true' EXIT
|
|
20
|
+
for i in $(seq 1 30); do
|
|
21
|
+
curl -sf http://127.0.0.1:4723/status >/dev/null 2>&1 && break
|
|
22
|
+
sleep 1
|
|
23
|
+
done
|
|
24
|
+
|
|
25
|
+
run_suite() { # $1 = spec, $2 = hard|soft
|
|
26
|
+
local spec="$1" gate="$2" tries=3 n=1
|
|
27
|
+
while [ $n -le $tries ]; do
|
|
28
|
+
echo "== [$gate] $spec (attempt $n/$tries) =="
|
|
29
|
+
if npx wdio run ./wdio.ios.conf.js --spec "$spec" 2>&1 | tee "$LOGDIR/wdio-$(basename "$spec").log"; then
|
|
30
|
+
return 0
|
|
31
|
+
fi
|
|
32
|
+
n=$((n+1))
|
|
33
|
+
done
|
|
34
|
+
if [ "$gate" = "hard" ]; then
|
|
35
|
+
echo "::error::E2E suite failed (hard gate): $spec"
|
|
36
|
+
return 1
|
|
37
|
+
fi
|
|
38
|
+
echo "::warning::E2E suite failed (best-effort): $spec"
|
|
39
|
+
return 0
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
cd "$HERE"
|
|
43
|
+
rc=0
|
|
44
|
+
run_suite "./specs/bridge.e2e.js" hard || rc=1
|
|
45
|
+
run_suite "./specs/dismiss.e2e.js" soft || true
|
|
46
|
+
exit $rc
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { config } = require('./wdio.shared.conf');
|
|
3
|
+
|
|
4
|
+
// Path to the debug apk built by `cordova build android`.
|
|
5
|
+
const APK = process.env.PURCHASELY_E2E_APK ||
|
|
6
|
+
path.resolve(__dirname, '../platforms/android/app/build/outputs/apk/debug/app-debug.apk');
|
|
7
|
+
|
|
8
|
+
exports.config = Object.assign({}, config, {
|
|
9
|
+
capabilities: [{
|
|
10
|
+
platformName: 'Android',
|
|
11
|
+
'appium:automationName': 'UiAutomator2',
|
|
12
|
+
'appium:app': APK,
|
|
13
|
+
'appium:appPackage': 'com.purchasely.demo',
|
|
14
|
+
'appium:newCommandTimeout': 240,
|
|
15
|
+
'appium:autoGrantPermissions': true,
|
|
16
|
+
// The Cordova WebView is debuggable in the debug build, so Appium can attach
|
|
17
|
+
// chromedriver and expose the WEBVIEW context.
|
|
18
|
+
'appium:ensureWebviewsHavePages': true,
|
|
19
|
+
'appium:nativeWebScreenshot': true,
|
|
20
|
+
}],
|
|
21
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { config } = require('./wdio.shared.conf');
|
|
3
|
+
|
|
4
|
+
// Path to the .app built by `cordova build ios --emulator` (simulator build).
|
|
5
|
+
const APP = process.env.PURCHASELY_E2E_APP ||
|
|
6
|
+
path.resolve(__dirname, '../platforms/ios/build/emulator/HelloCordova.app');
|
|
7
|
+
|
|
8
|
+
exports.config = Object.assign({}, config, {
|
|
9
|
+
capabilities: [{
|
|
10
|
+
platformName: 'iOS',
|
|
11
|
+
'appium:automationName': 'XCUITest',
|
|
12
|
+
'appium:app': APP,
|
|
13
|
+
'appium:bundleId': 'com.purchasely.demo',
|
|
14
|
+
'appium:deviceName': process.env.PURCHASELY_E2E_SIM || 'iPhone 16',
|
|
15
|
+
'appium:platformVersion': process.env.PURCHASELY_E2E_IOS_VERSION || undefined,
|
|
16
|
+
'appium:newCommandTimeout': 240,
|
|
17
|
+
'appium:autoAcceptAlerts': true,
|
|
18
|
+
}],
|
|
19
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Shared WebdriverIO config for the Purchasely Cordova E2E suite.
|
|
2
|
+
// Platform-specific configs (wdio.android.conf.js / wdio.ios.conf.js) extend this
|
|
3
|
+
// and set `capabilities`.
|
|
4
|
+
//
|
|
5
|
+
// The example app boots the Purchasely SDK on `deviceready` (see www/js/index.js).
|
|
6
|
+
// Tests switch to the WEBVIEW context and call `window.Purchasely.*` directly, and
|
|
7
|
+
// switch to NATIVE_APP to inject OS-level touches for the interceptor / dismiss suites.
|
|
8
|
+
exports.config = {
|
|
9
|
+
runner: 'local',
|
|
10
|
+
specs: ['./specs/**/*.e2e.js'],
|
|
11
|
+
maxInstances: 1,
|
|
12
|
+
logLevel: 'info',
|
|
13
|
+
bail: 0,
|
|
14
|
+
waitforTimeout: 20000,
|
|
15
|
+
connectionRetryTimeout: 120000,
|
|
16
|
+
connectionRetryCount: 2,
|
|
17
|
+
framework: 'mocha',
|
|
18
|
+
reporters: ['spec'],
|
|
19
|
+
mochaOpts: {
|
|
20
|
+
ui: 'bdd',
|
|
21
|
+
timeout: 120000,
|
|
22
|
+
},
|
|
23
|
+
// Appium is started as a service by the CI runner scripts (tools/ci_run_e2e*.sh),
|
|
24
|
+
// so we point WDIO at the already-running server rather than the @wdio/appium-service.
|
|
25
|
+
hostname: '127.0.0.1',
|
|
26
|
+
port: 4723,
|
|
27
|
+
path: '/',
|
|
28
|
+
};
|