Skip to content

Commit 55f8c0c

Browse files
authored
Merge pull request #151 from ExcelDsigN-tech/feature/add-detox-e2e-tests
Feature/add detox e2e tests
2 parents 172c046 + 070f837 commit 55f8c0c

37 files changed

Lines changed: 3489 additions & 170 deletions

.detoxrc.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/** @type {Detox.DetoxConfig} */
2+
module.exports = {
3+
logger: {
4+
level: process.env.CI ? 'debug' : undefined,
5+
},
6+
testRunner: {
7+
args: {
8+
$0: 'jest',
9+
config: 'e2e/jest.config.js',
10+
},
11+
jest: {
12+
setupTimeout: 120000,
13+
},
14+
},
15+
apps: {
16+
'ios.debug': {
17+
type: 'ios.app',
18+
binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/SubTrackr.app',
19+
build:
20+
'xcodebuild -workspace ios/subtrackr.xcworkspace -scheme subtrackr -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build',
21+
},
22+
'ios.release': {
23+
type: 'ios.app',
24+
binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/SubTrackr.app',
25+
build:
26+
'xcodebuild -workspace ios/subtrackr.xcworkspace -scheme subtrackr -configuration Release -sdk iphonesimulator -derivedDataPath ios/build',
27+
},
28+
'android.debug': {
29+
type: 'android.apk',
30+
binaryPath: 'android/app/build/outputs/apk/debug/app-debug.apk',
31+
build: 'cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug',
32+
reversePorts: [8081],
33+
},
34+
'android.release': {
35+
type: 'android.apk',
36+
binaryPath: 'android/app/build/outputs/apk/release/app-release.apk',
37+
build: 'cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release',
38+
},
39+
},
40+
devices: {
41+
simulator: {
42+
type: 'ios.simulator',
43+
device: {
44+
type: 'iPhone 15',
45+
},
46+
},
47+
attached: {
48+
type: 'android.attached',
49+
device: {
50+
adbName: '.*',
51+
},
52+
},
53+
emulator: {
54+
type: 'android.emulator',
55+
device: {
56+
avdName: 'Pixel_4_API_30',
57+
},
58+
},
59+
},
60+
configurations: {
61+
'ios.sim.debug': {
62+
device: 'simulator',
63+
app: 'ios.debug',
64+
},
65+
'ios.sim.release': {
66+
device: 'simulator',
67+
app: 'ios.release',
68+
},
69+
'android.att.debug': {
70+
device: 'attached',
71+
app: 'android.debug',
72+
},
73+
'android.att.release': {
74+
device: 'attached',
75+
app: 'android.release',
76+
},
77+
'android.emu.debug': {
78+
device: 'emulator',
79+
app: 'android.debug',
80+
},
81+
'android.emu.release': {
82+
device: 'emulator',
83+
app: 'android.release',
84+
},
85+
},
86+
};

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ name: CI/CD Pipeline
22

33
on:
44
push:
5-
branches: [main, dev, develop]
5+
branches: [main, dev, develop, 'feature/*']
66
pull_request:
7-
branches: [main, dev, develop]
7+
branches: [main, dev, develop, 'feature/*']
88

99
env:
1010
NODE_VERSION: '20'
11-
RUST_VERSION: '1.85'
11+
RUST_VERSION: 'stable'
1212

1313
jobs:
1414
commitlint:

.github/workflows/e2e-detox.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: E2E Detox Tests
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
7+
jobs:
8+
test-ios:
9+
name: Detox iOS
10+
runs-on: macos-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- uses: actions/setup-node@v4
14+
with:
15+
node-version: '20'
16+
cache: 'npm'
17+
- name: Install dependencies
18+
run: npm ci --legacy-peer-deps || npm install --legacy-peer-deps
19+
- name: Expo Prebuild
20+
run: npx expo prebuild -p ios
21+
- name: Setup Ruby
22+
uses: ruby/setup-ruby@v1
23+
with:
24+
ruby-version: '3.2'
25+
- name: Install CocoaPods dependencies
26+
run: cd ios && pod install --repo-update
27+
- name: Install AppleSimulatorUtils
28+
run: brew tap wix/brew && brew install applesimutils
29+
- name: Build Detox iOS
30+
run: npm run e2e:build-ios
31+
- name: Test Detox iOS
32+
run: npm run e2e:test-ios
33+
34+
test-android:
35+
name: Detox Android
36+
runs-on: ubuntu-latest
37+
steps:
38+
- uses: actions/checkout@v4
39+
- uses: actions/setup-node@v4
40+
with:
41+
node-version: '20'
42+
cache: 'npm'
43+
- name: Install dependencies
44+
run: npm ci --legacy-peer-deps || npm install --legacy-peer-deps
45+
- name: Setup Java
46+
uses: actions/setup-java@v3
47+
with:
48+
distribution: 'zulu'
49+
java-version: '17'
50+
- name: Expo Prebuild
51+
run: npx expo prebuild -p android
52+
- name: Build Detox Android
53+
run: npm run e2e:build-android
54+
- name: Detox Android Emulator
55+
uses: reactivecircus/android-emulator-runner@v2
56+
with:
57+
api-level: 30
58+
target: default
59+
arch: x86_64
60+
profile: pixel_4
61+
script: npm run e2e:test-android

app.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@
4747
"sounds": [],
4848
"enableBackgroundRemoteNotifications": false
4949
}
50-
]
50+
],
51+
"@config-plugins/detox"
5152
]
5253
}
5354
}

contracts/DEPLOYMENT.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ export ADMIN_ADDRESS="GD..."
4646

4747
## Environment Variables
4848

49-
| Variable | Description | Required For |
50-
|---|---|---|
49+
| Variable | Description | Required For |
50+
| ----------------- | ---------------------------------------------------------------------------------- | ---------------- |
5151
| `SOROBAN_ACCOUNT` | The identity name (configured in Soroban CLI) or secret key to use for deployment. | Testnet, Mainnet |
52-
| `ADMIN_ADDRESS` | The Stellar address that will be set as the contract admin during initialization. | Testnet, Mainnet |
52+
| `ADMIN_ADDRESS` | The Stellar address that will be set as the contract admin during initialization. | Testnet, Mainnet |
5353

5454
## Verification
5555

contracts/clippy_output.txt

21.7 KB
Binary file not shown.

contracts/src/lib.rs

Lines changed: 1 addition & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -287,12 +287,7 @@ impl SubTrackrContract {
287287
}
288288

289289
/// User pauses their subscription with a specific duration
290-
pub fn pause_by_subscriber(
291-
env: Env,
292-
subscriber: Address,
293-
subscription_id: u64,
294-
duration: u64,
295-
) {
290+
pub fn pause_by_subscriber(env: Env, subscriber: Address, subscription_id: u64, duration: u64) {
296291
subscriber.require_auth();
297292

298293
let mut sub: Subscription = env
@@ -522,108 +517,6 @@ impl SubTrackrContract {
522517
);
523518
}
524519

525-
/// Request a refund for a subscription (can only be called by the subscriber)
526-
pub fn request_refund(env: Env, subscription_id: u64, amount: i128) {
527-
let mut sub: Subscription = env
528-
.storage()
529-
.persistent()
530-
.get(&DataKey::Subscription(subscription_id))
531-
.expect("Subscription not found");
532-
533-
sub.subscriber.require_auth();
534-
535-
assert!(amount > 0, "Refund amount must be positive");
536-
assert!(
537-
amount <= sub.total_paid,
538-
"Refund amount cannot exceed total paid"
539-
);
540-
541-
sub.refund_requested_amount = amount;
542-
543-
env.storage()
544-
.persistent()
545-
.set(&DataKey::Subscription(subscription_id), &sub);
546-
547-
// Publish event
548-
env.events().publish(
549-
(String::from_str(&env, "refund_requested"), subscription_id),
550-
(sub.subscriber.clone(), amount),
551-
);
552-
}
553-
554-
/// Approve a refund (can only be called by the admin)
555-
pub fn approve_refund(env: Env, subscription_id: u64) {
556-
let mut sub: Subscription = env
557-
.storage()
558-
.persistent()
559-
.get(&DataKey::Subscription(subscription_id))
560-
.expect("Subscription not found");
561-
562-
let admin: Address = env
563-
.storage()
564-
.instance()
565-
.get(&DataKey::Admin)
566-
.expect("Admin not set");
567-
admin.require_auth();
568-
569-
let amount = sub.refund_requested_amount;
570-
assert!(amount > 0, "No pending refund request");
571-
572-
let _plan: Plan = env
573-
.storage()
574-
.persistent()
575-
.get(&DataKey::Plan(sub.plan_id))
576-
.expect("Plan not found");
577-
578-
// TODO: Execute actual token transfer from merchant back to subscriber
579-
// token::Client::new(&env, &plan.token).transfer(
580-
// &plan.merchant, &sub.subscriber, &amount
581-
// );
582-
583-
sub.total_paid -= amount;
584-
sub.refund_requested_amount = 0;
585-
586-
env.storage()
587-
.persistent()
588-
.set(&DataKey::Subscription(subscription_id), &sub);
589-
590-
// Publish event
591-
env.events().publish(
592-
(String::from_str(&env, "refund_approved"), subscription_id),
593-
(sub.subscriber.clone(), amount),
594-
);
595-
}
596-
597-
/// Reject a refund (can only be called by the admin)
598-
pub fn reject_refund(env: Env, subscription_id: u64) {
599-
let mut sub: Subscription = env
600-
.storage()
601-
.persistent()
602-
.get(&DataKey::Subscription(subscription_id))
603-
.expect("Subscription not found");
604-
605-
let admin: Address = env
606-
.storage()
607-
.instance()
608-
.get(&DataKey::Admin)
609-
.expect("Admin not set");
610-
admin.require_auth();
611-
612-
assert!(sub.refund_requested_amount > 0, "No pending refund request");
613-
614-
sub.refund_requested_amount = 0;
615-
616-
env.storage()
617-
.persistent()
618-
.set(&DataKey::Subscription(subscription_id), &sub);
619-
620-
// Publish event
621-
env.events().publish(
622-
(String::from_str(&env, "refund_rejected"), subscription_id),
623-
sub.subscriber.clone(),
624-
);
625-
}
626-
627520
// ── Queries ──
628521

629522
/// Get plan details

0 commit comments

Comments
 (0)