@croacroa/react-native-template 1.0.0 → 2.0.0
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/.github/workflows/ci.yml +187 -184
- package/.github/workflows/eas-build.yml +55 -55
- package/.github/workflows/eas-update.yml +50 -50
- package/CHANGELOG.md +106 -106
- package/CONTRIBUTING.md +377 -377
- package/README.md +399 -399
- package/__tests__/components/snapshots.test.tsx +131 -0
- package/__tests__/integration/auth-api.test.tsx +227 -0
- package/__tests__/performance/VirtualizedList.perf.test.tsx +362 -0
- package/app/(public)/onboarding.tsx +5 -5
- package/app.config.ts +45 -2
- package/assets/images/.gitkeep +7 -7
- package/components/onboarding/OnboardingScreen.tsx +370 -370
- package/components/onboarding/index.ts +2 -2
- package/components/providers/SuspenseBoundary.tsx +357 -0
- package/components/providers/index.ts +13 -0
- package/components/ui/Avatar.tsx +316 -316
- package/components/ui/Badge.tsx +416 -416
- package/components/ui/BottomSheet.tsx +307 -307
- package/components/ui/Checkbox.tsx +261 -261
- package/components/ui/OptimizedImage.tsx +369 -369
- package/components/ui/Select.tsx +240 -240
- package/components/ui/VirtualizedList.tsx +285 -0
- package/components/ui/index.ts +23 -18
- package/constants/config.ts +97 -54
- package/docs/adr/001-state-management.md +79 -79
- package/docs/adr/002-styling-approach.md +130 -130
- package/docs/adr/003-data-fetching.md +155 -155
- package/docs/adr/004-auth-adapter-pattern.md +144 -144
- package/docs/adr/README.md +78 -78
- package/hooks/index.ts +27 -25
- package/hooks/useApi.ts +102 -5
- package/hooks/useAuth.tsx +82 -0
- package/hooks/useBiometrics.ts +295 -295
- package/hooks/useDeepLinking.ts +256 -256
- package/hooks/useMFA.ts +499 -0
- package/hooks/useNotifications.ts +39 -0
- package/hooks/useOffline.ts +32 -2
- package/hooks/usePerformance.ts +434 -434
- package/hooks/useTheme.tsx +76 -0
- package/hooks/useUpdates.ts +358 -358
- package/i18n/index.ts +194 -77
- package/i18n/locales/ar.json +101 -0
- package/i18n/locales/de.json +101 -0
- package/i18n/locales/en.json +101 -101
- package/i18n/locales/es.json +101 -0
- package/i18n/locales/fr.json +101 -101
- package/jest.config.js +4 -4
- package/maestro/README.md +113 -113
- package/maestro/config.yaml +35 -35
- package/maestro/flows/login.yaml +62 -62
- package/maestro/flows/mfa-login.yaml +92 -0
- package/maestro/flows/mfa-setup.yaml +86 -0
- package/maestro/flows/navigation.yaml +68 -68
- package/maestro/flows/offline-conflict.yaml +101 -0
- package/maestro/flows/offline-sync.yaml +128 -0
- package/maestro/flows/offline.yaml +60 -60
- package/maestro/flows/register.yaml +94 -94
- package/package.json +175 -170
- package/services/analytics.ts +428 -428
- package/services/api.ts +340 -340
- package/services/authAdapter.ts +333 -333
- package/services/backgroundSync.ts +626 -0
- package/services/index.ts +54 -22
- package/services/security.ts +229 -0
- package/tailwind.config.js +47 -47
- package/utils/accessibility.ts +446 -446
- package/utils/index.ts +52 -43
- package/utils/withAccessibility.tsx +272 -0
package/maestro/README.md
CHANGED
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
# Maestro E2E Tests
|
|
2
|
-
|
|
3
|
-
This directory contains end-to-end tests using [Maestro](https://maestro.mobile.dev/).
|
|
4
|
-
|
|
5
|
-
## Setup
|
|
6
|
-
|
|
7
|
-
### Install Maestro
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
# macOS
|
|
11
|
-
brew install maestro
|
|
12
|
-
|
|
13
|
-
# Or using curl
|
|
14
|
-
curl -Ls "https://get.maestro.mobile.dev" | bash
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
### Prerequisites
|
|
18
|
-
|
|
19
|
-
- iOS Simulator or Android Emulator running
|
|
20
|
-
- App built and installed on the device/emulator
|
|
21
|
-
|
|
22
|
-
## Running Tests
|
|
23
|
-
|
|
24
|
-
### Run all tests
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
maestro test maestro/flows/
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
### Run a specific test
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
maestro test maestro/flows/login.yaml
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### Run with a specific app ID
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
APP_ID=com.yourcompany.app maestro test maestro/flows/
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Run in CI mode
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
maestro test --format junit --output results.xml maestro/flows/
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## Test Structure
|
|
49
|
-
|
|
50
|
-
```
|
|
51
|
-
maestro/
|
|
52
|
-
├── config.yaml # Global configuration
|
|
53
|
-
├── README.md # This file
|
|
54
|
-
└── flows/
|
|
55
|
-
├── login.yaml # Login flow tests
|
|
56
|
-
├── register.yaml # Registration flow tests
|
|
57
|
-
├── navigation.yaml # Navigation tests
|
|
58
|
-
└── offline.yaml # Offline mode tests
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Writing Tests
|
|
62
|
-
|
|
63
|
-
### Basic test structure
|
|
64
|
-
|
|
65
|
-
```yaml
|
|
66
|
-
appId: ${APP_ID}
|
|
67
|
-
name: My Test
|
|
68
|
-
tags:
|
|
69
|
-
- smoke
|
|
70
|
-
---
|
|
71
|
-
- launchApp
|
|
72
|
-
- tapOn: "Button Text"
|
|
73
|
-
- assertVisible: "Expected Text"
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Common commands
|
|
77
|
-
|
|
78
|
-
- `launchApp` - Launch the app
|
|
79
|
-
- `tapOn` - Tap on an element
|
|
80
|
-
- `inputText` - Enter text
|
|
81
|
-
- `assertVisible` - Assert element is visible
|
|
82
|
-
- `scrollUntilVisible` - Scroll until element is found
|
|
83
|
-
- `waitForAnimationToEnd` - Wait for animations
|
|
84
|
-
- `back` - Press back button
|
|
85
|
-
|
|
86
|
-
### Tips
|
|
87
|
-
|
|
88
|
-
1. Use `waitForAnimationToEnd` after navigation
|
|
89
|
-
2. Use `clearState: true` in `launchApp` for clean tests
|
|
90
|
-
3. Use `optional: true` for elements that may not always appear
|
|
91
|
-
4. Use tags to organize and filter tests
|
|
92
|
-
|
|
93
|
-
## CI Integration
|
|
94
|
-
|
|
95
|
-
### GitHub Actions example
|
|
96
|
-
|
|
97
|
-
```yaml
|
|
98
|
-
- name: Run E2E Tests
|
|
99
|
-
run: |
|
|
100
|
-
maestro test --format junit --output results.xml maestro/flows/
|
|
101
|
-
|
|
102
|
-
- name: Upload Test Results
|
|
103
|
-
uses: actions/upload-artifact@v3
|
|
104
|
-
with:
|
|
105
|
-
name: e2e-results
|
|
106
|
-
path: results.xml
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
## Resources
|
|
110
|
-
|
|
111
|
-
- [Maestro Documentation](https://maestro.mobile.dev/)
|
|
112
|
-
- [CLI Reference](https://maestro.mobile.dev/reference/cli)
|
|
113
|
-
- [Command Reference](https://maestro.mobile.dev/reference/commands)
|
|
1
|
+
# Maestro E2E Tests
|
|
2
|
+
|
|
3
|
+
This directory contains end-to-end tests using [Maestro](https://maestro.mobile.dev/).
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
### Install Maestro
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# macOS
|
|
11
|
+
brew install maestro
|
|
12
|
+
|
|
13
|
+
# Or using curl
|
|
14
|
+
curl -Ls "https://get.maestro.mobile.dev" | bash
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Prerequisites
|
|
18
|
+
|
|
19
|
+
- iOS Simulator or Android Emulator running
|
|
20
|
+
- App built and installed on the device/emulator
|
|
21
|
+
|
|
22
|
+
## Running Tests
|
|
23
|
+
|
|
24
|
+
### Run all tests
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
maestro test maestro/flows/
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Run a specific test
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
maestro test maestro/flows/login.yaml
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Run with a specific app ID
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
APP_ID=com.yourcompany.app maestro test maestro/flows/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Run in CI mode
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
maestro test --format junit --output results.xml maestro/flows/
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Test Structure
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
maestro/
|
|
52
|
+
├── config.yaml # Global configuration
|
|
53
|
+
├── README.md # This file
|
|
54
|
+
└── flows/
|
|
55
|
+
├── login.yaml # Login flow tests
|
|
56
|
+
├── register.yaml # Registration flow tests
|
|
57
|
+
├── navigation.yaml # Navigation tests
|
|
58
|
+
└── offline.yaml # Offline mode tests
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Writing Tests
|
|
62
|
+
|
|
63
|
+
### Basic test structure
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
appId: ${APP_ID}
|
|
67
|
+
name: My Test
|
|
68
|
+
tags:
|
|
69
|
+
- smoke
|
|
70
|
+
---
|
|
71
|
+
- launchApp
|
|
72
|
+
- tapOn: "Button Text"
|
|
73
|
+
- assertVisible: "Expected Text"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Common commands
|
|
77
|
+
|
|
78
|
+
- `launchApp` - Launch the app
|
|
79
|
+
- `tapOn` - Tap on an element
|
|
80
|
+
- `inputText` - Enter text
|
|
81
|
+
- `assertVisible` - Assert element is visible
|
|
82
|
+
- `scrollUntilVisible` - Scroll until element is found
|
|
83
|
+
- `waitForAnimationToEnd` - Wait for animations
|
|
84
|
+
- `back` - Press back button
|
|
85
|
+
|
|
86
|
+
### Tips
|
|
87
|
+
|
|
88
|
+
1. Use `waitForAnimationToEnd` after navigation
|
|
89
|
+
2. Use `clearState: true` in `launchApp` for clean tests
|
|
90
|
+
3. Use `optional: true` for elements that may not always appear
|
|
91
|
+
4. Use tags to organize and filter tests
|
|
92
|
+
|
|
93
|
+
## CI Integration
|
|
94
|
+
|
|
95
|
+
### GitHub Actions example
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
- name: Run E2E Tests
|
|
99
|
+
run: |
|
|
100
|
+
maestro test --format junit --output results.xml maestro/flows/
|
|
101
|
+
|
|
102
|
+
- name: Upload Test Results
|
|
103
|
+
uses: actions/upload-artifact@v3
|
|
104
|
+
with:
|
|
105
|
+
name: e2e-results
|
|
106
|
+
path: results.xml
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Resources
|
|
110
|
+
|
|
111
|
+
- [Maestro Documentation](https://maestro.mobile.dev/)
|
|
112
|
+
- [CLI Reference](https://maestro.mobile.dev/reference/cli)
|
|
113
|
+
- [Command Reference](https://maestro.mobile.dev/reference/commands)
|
package/maestro/config.yaml
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
# Maestro Configuration
|
|
2
|
-
# https://maestro.mobile.dev/reference/configuration
|
|
3
|
-
|
|
4
|
-
# Default app ID (can be overridden with env vars)
|
|
5
|
-
appId: com.croacroa.app
|
|
6
|
-
|
|
7
|
-
# Environment variables
|
|
8
|
-
env:
|
|
9
|
-
APP_ID: ${APP_ID:-com.croacroa.app}
|
|
10
|
-
API_URL: ${API_URL:-http://localhost:3000}
|
|
11
|
-
|
|
12
|
-
# Test execution settings
|
|
13
|
-
executionOrder:
|
|
14
|
-
continueOnFailure: false
|
|
15
|
-
retryFailedTests: 1
|
|
16
|
-
|
|
17
|
-
# Screenshots
|
|
18
|
-
screenshots:
|
|
19
|
-
enabled: true
|
|
20
|
-
directory: ./maestro/screenshots
|
|
21
|
-
|
|
22
|
-
# Video recording
|
|
23
|
-
video:
|
|
24
|
-
enabled: true
|
|
25
|
-
directory: ./maestro/videos
|
|
26
|
-
|
|
27
|
-
# Timeouts
|
|
28
|
-
timeouts:
|
|
29
|
-
launchApp: 30000
|
|
30
|
-
waitForAnimationToEnd: 5000
|
|
31
|
-
|
|
32
|
-
# Device settings
|
|
33
|
-
device:
|
|
34
|
-
locale: en_US
|
|
35
|
-
orientation: portrait
|
|
1
|
+
# Maestro Configuration
|
|
2
|
+
# https://maestro.mobile.dev/reference/configuration
|
|
3
|
+
|
|
4
|
+
# Default app ID (can be overridden with env vars)
|
|
5
|
+
appId: com.croacroa.app
|
|
6
|
+
|
|
7
|
+
# Environment variables
|
|
8
|
+
env:
|
|
9
|
+
APP_ID: ${APP_ID:-com.croacroa.app}
|
|
10
|
+
API_URL: ${API_URL:-http://localhost:3000}
|
|
11
|
+
|
|
12
|
+
# Test execution settings
|
|
13
|
+
executionOrder:
|
|
14
|
+
continueOnFailure: false
|
|
15
|
+
retryFailedTests: 1
|
|
16
|
+
|
|
17
|
+
# Screenshots
|
|
18
|
+
screenshots:
|
|
19
|
+
enabled: true
|
|
20
|
+
directory: ./maestro/screenshots
|
|
21
|
+
|
|
22
|
+
# Video recording
|
|
23
|
+
video:
|
|
24
|
+
enabled: true
|
|
25
|
+
directory: ./maestro/videos
|
|
26
|
+
|
|
27
|
+
# Timeouts
|
|
28
|
+
timeouts:
|
|
29
|
+
launchApp: 30000
|
|
30
|
+
waitForAnimationToEnd: 5000
|
|
31
|
+
|
|
32
|
+
# Device settings
|
|
33
|
+
device:
|
|
34
|
+
locale: en_US
|
|
35
|
+
orientation: portrait
|
package/maestro/flows/login.yaml
CHANGED
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
appId: ${APP_ID}
|
|
2
|
-
name: Login Flow
|
|
3
|
-
tags:
|
|
4
|
-
- auth
|
|
5
|
-
- smoke
|
|
6
|
-
---
|
|
7
|
-
# Login Flow Test
|
|
8
|
-
# Tests the complete login experience
|
|
9
|
-
|
|
10
|
-
- launchApp:
|
|
11
|
-
clearState: true
|
|
12
|
-
|
|
13
|
-
# Wait for app to load
|
|
14
|
-
- waitForAnimationToEnd
|
|
15
|
-
|
|
16
|
-
# Verify we're on the login screen
|
|
17
|
-
- assertVisible: "Sign In"
|
|
18
|
-
- assertVisible: "Sign in to continue"
|
|
19
|
-
|
|
20
|
-
# Test empty form submission
|
|
21
|
-
- tapOn: "Sign In"
|
|
22
|
-
- assertVisible: "required"
|
|
23
|
-
|
|
24
|
-
# Enter invalid email
|
|
25
|
-
- tapOn:
|
|
26
|
-
text: "Email"
|
|
27
|
-
- inputText: "invalid-email"
|
|
28
|
-
- tapOn: "Sign In"
|
|
29
|
-
- assertVisible: "valid email"
|
|
30
|
-
|
|
31
|
-
# Clear and enter valid credentials
|
|
32
|
-
- clearText
|
|
33
|
-
- inputText: "test@example.com"
|
|
34
|
-
|
|
35
|
-
# Enter password
|
|
36
|
-
- tapOn:
|
|
37
|
-
text: "Password"
|
|
38
|
-
- inputText: "password123"
|
|
39
|
-
|
|
40
|
-
# Toggle password visibility
|
|
41
|
-
- tapOn:
|
|
42
|
-
id: "password-toggle"
|
|
43
|
-
- assertVisible: "password123"
|
|
44
|
-
- tapOn:
|
|
45
|
-
id: "password-toggle"
|
|
46
|
-
|
|
47
|
-
# Submit the form
|
|
48
|
-
- tapOn:
|
|
49
|
-
text: "Sign In"
|
|
50
|
-
index: 1
|
|
51
|
-
|
|
52
|
-
# Wait for loading
|
|
53
|
-
- waitForAnimationToEnd:
|
|
54
|
-
timeout: 5000
|
|
55
|
-
|
|
56
|
-
# Verify successful login (should see home screen)
|
|
57
|
-
- assertVisible: "Welcome back"
|
|
58
|
-
|
|
59
|
-
# Verify we're on the authenticated section
|
|
60
|
-
- assertVisible:
|
|
61
|
-
text: "Home"
|
|
62
|
-
optional: true
|
|
1
|
+
appId: ${APP_ID}
|
|
2
|
+
name: Login Flow
|
|
3
|
+
tags:
|
|
4
|
+
- auth
|
|
5
|
+
- smoke
|
|
6
|
+
---
|
|
7
|
+
# Login Flow Test
|
|
8
|
+
# Tests the complete login experience
|
|
9
|
+
|
|
10
|
+
- launchApp:
|
|
11
|
+
clearState: true
|
|
12
|
+
|
|
13
|
+
# Wait for app to load
|
|
14
|
+
- waitForAnimationToEnd
|
|
15
|
+
|
|
16
|
+
# Verify we're on the login screen
|
|
17
|
+
- assertVisible: "Sign In"
|
|
18
|
+
- assertVisible: "Sign in to continue"
|
|
19
|
+
|
|
20
|
+
# Test empty form submission
|
|
21
|
+
- tapOn: "Sign In"
|
|
22
|
+
- assertVisible: "required"
|
|
23
|
+
|
|
24
|
+
# Enter invalid email
|
|
25
|
+
- tapOn:
|
|
26
|
+
text: "Email"
|
|
27
|
+
- inputText: "invalid-email"
|
|
28
|
+
- tapOn: "Sign In"
|
|
29
|
+
- assertVisible: "valid email"
|
|
30
|
+
|
|
31
|
+
# Clear and enter valid credentials
|
|
32
|
+
- clearText
|
|
33
|
+
- inputText: "test@example.com"
|
|
34
|
+
|
|
35
|
+
# Enter password
|
|
36
|
+
- tapOn:
|
|
37
|
+
text: "Password"
|
|
38
|
+
- inputText: "password123"
|
|
39
|
+
|
|
40
|
+
# Toggle password visibility
|
|
41
|
+
- tapOn:
|
|
42
|
+
id: "password-toggle"
|
|
43
|
+
- assertVisible: "password123"
|
|
44
|
+
- tapOn:
|
|
45
|
+
id: "password-toggle"
|
|
46
|
+
|
|
47
|
+
# Submit the form
|
|
48
|
+
- tapOn:
|
|
49
|
+
text: "Sign In"
|
|
50
|
+
index: 1
|
|
51
|
+
|
|
52
|
+
# Wait for loading
|
|
53
|
+
- waitForAnimationToEnd:
|
|
54
|
+
timeout: 5000
|
|
55
|
+
|
|
56
|
+
# Verify successful login (should see home screen)
|
|
57
|
+
- assertVisible: "Welcome back"
|
|
58
|
+
|
|
59
|
+
# Verify we're on the authenticated section
|
|
60
|
+
- assertVisible:
|
|
61
|
+
text: "Home"
|
|
62
|
+
optional: true
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
appId: ${APP_ID}
|
|
2
|
+
name: MFA Login Flow
|
|
3
|
+
tags:
|
|
4
|
+
- auth
|
|
5
|
+
- mfa
|
|
6
|
+
- security
|
|
7
|
+
---
|
|
8
|
+
# MFA Login Test
|
|
9
|
+
# Tests login with MFA verification required
|
|
10
|
+
|
|
11
|
+
- launchApp:
|
|
12
|
+
clearState: true
|
|
13
|
+
|
|
14
|
+
# Wait for app to load
|
|
15
|
+
- waitForAnimationToEnd
|
|
16
|
+
|
|
17
|
+
# Enter credentials
|
|
18
|
+
- tapOn:
|
|
19
|
+
text: "Email"
|
|
20
|
+
- inputText: "mfa-user@example.com"
|
|
21
|
+
- tapOn:
|
|
22
|
+
text: "Password"
|
|
23
|
+
- inputText: "password123"
|
|
24
|
+
|
|
25
|
+
# Submit login
|
|
26
|
+
- tapOn:
|
|
27
|
+
text: "Sign In"
|
|
28
|
+
index: 1
|
|
29
|
+
- waitForAnimationToEnd:
|
|
30
|
+
timeout: 5000
|
|
31
|
+
|
|
32
|
+
# Verify MFA screen appears
|
|
33
|
+
- assertVisible:
|
|
34
|
+
text:
|
|
35
|
+
- "verification"
|
|
36
|
+
- "code"
|
|
37
|
+
- "2FA"
|
|
38
|
+
- "authenticator"
|
|
39
|
+
optional: true
|
|
40
|
+
|
|
41
|
+
# Enter MFA code
|
|
42
|
+
- tapOn:
|
|
43
|
+
id: "mfa-input"
|
|
44
|
+
optional: true
|
|
45
|
+
- inputText: "123456"
|
|
46
|
+
|
|
47
|
+
# Or enter in OTP input fields
|
|
48
|
+
- tapOn:
|
|
49
|
+
id: "otp-input-0"
|
|
50
|
+
optional: true
|
|
51
|
+
- inputText: "1"
|
|
52
|
+
- tapOn:
|
|
53
|
+
id: "otp-input-1"
|
|
54
|
+
optional: true
|
|
55
|
+
- inputText: "2"
|
|
56
|
+
- tapOn:
|
|
57
|
+
id: "otp-input-2"
|
|
58
|
+
optional: true
|
|
59
|
+
- inputText: "3"
|
|
60
|
+
- tapOn:
|
|
61
|
+
id: "otp-input-3"
|
|
62
|
+
optional: true
|
|
63
|
+
- inputText: "4"
|
|
64
|
+
- tapOn:
|
|
65
|
+
id: "otp-input-4"
|
|
66
|
+
optional: true
|
|
67
|
+
- inputText: "5"
|
|
68
|
+
- tapOn:
|
|
69
|
+
id: "otp-input-5"
|
|
70
|
+
optional: true
|
|
71
|
+
- inputText: "6"
|
|
72
|
+
|
|
73
|
+
# Submit MFA code
|
|
74
|
+
- tapOn:
|
|
75
|
+
text: "Verify"
|
|
76
|
+
optional: true
|
|
77
|
+
- waitForAnimationToEnd:
|
|
78
|
+
timeout: 5000
|
|
79
|
+
|
|
80
|
+
# Verify successful login
|
|
81
|
+
- assertVisible:
|
|
82
|
+
text:
|
|
83
|
+
- "Home"
|
|
84
|
+
- "Welcome"
|
|
85
|
+
- "Dashboard"
|
|
86
|
+
optional: true
|
|
87
|
+
|
|
88
|
+
# Test backup code flow
|
|
89
|
+
- runFlow:
|
|
90
|
+
when:
|
|
91
|
+
visible: "Use backup code"
|
|
92
|
+
file: mfa-backup-code.yaml
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
appId: ${APP_ID}
|
|
2
|
+
name: MFA Setup Flow
|
|
3
|
+
tags:
|
|
4
|
+
- auth
|
|
5
|
+
- mfa
|
|
6
|
+
- security
|
|
7
|
+
---
|
|
8
|
+
# MFA Setup Test
|
|
9
|
+
# Tests the complete MFA (2FA) setup experience
|
|
10
|
+
|
|
11
|
+
- launchApp:
|
|
12
|
+
clearState: true
|
|
13
|
+
|
|
14
|
+
# Login first
|
|
15
|
+
- tapOn:
|
|
16
|
+
text: "Email"
|
|
17
|
+
- inputText: "test@example.com"
|
|
18
|
+
- tapOn:
|
|
19
|
+
text: "Password"
|
|
20
|
+
- inputText: "password123"
|
|
21
|
+
- tapOn:
|
|
22
|
+
text: "Sign In"
|
|
23
|
+
index: 1
|
|
24
|
+
- waitForAnimationToEnd:
|
|
25
|
+
timeout: 5000
|
|
26
|
+
|
|
27
|
+
# Navigate to settings
|
|
28
|
+
- tapOn: "Settings"
|
|
29
|
+
- waitForAnimationToEnd
|
|
30
|
+
|
|
31
|
+
# Find and tap on security section
|
|
32
|
+
- scrollUntilVisible:
|
|
33
|
+
element: "Security"
|
|
34
|
+
direction: DOWN
|
|
35
|
+
- tapOn: "Security"
|
|
36
|
+
- waitForAnimationToEnd
|
|
37
|
+
|
|
38
|
+
# Tap on enable MFA
|
|
39
|
+
- tapOn: "Biometric Authentication"
|
|
40
|
+
- waitForAnimationToEnd
|
|
41
|
+
|
|
42
|
+
# OR tap on 2FA if available
|
|
43
|
+
- tapOn:
|
|
44
|
+
text: "Two-Factor Authentication"
|
|
45
|
+
optional: true
|
|
46
|
+
- waitForAnimationToEnd
|
|
47
|
+
|
|
48
|
+
# Verify MFA setup screen appears
|
|
49
|
+
- assertVisible:
|
|
50
|
+
text: "Enable"
|
|
51
|
+
optional: true
|
|
52
|
+
|
|
53
|
+
# If there's an enable button, tap it
|
|
54
|
+
- tapOn:
|
|
55
|
+
text: "Enable 2FA"
|
|
56
|
+
optional: true
|
|
57
|
+
- waitForAnimationToEnd
|
|
58
|
+
|
|
59
|
+
# Verify QR code or setup instructions appear
|
|
60
|
+
- assertVisible:
|
|
61
|
+
text:
|
|
62
|
+
- "Authenticator"
|
|
63
|
+
- "QR"
|
|
64
|
+
- "code"
|
|
65
|
+
optional: true
|
|
66
|
+
|
|
67
|
+
# Enter verification code (mock: 123456)
|
|
68
|
+
- tapOn:
|
|
69
|
+
text: "Verification"
|
|
70
|
+
optional: true
|
|
71
|
+
- inputText: "123456"
|
|
72
|
+
|
|
73
|
+
# Confirm setup
|
|
74
|
+
- tapOn:
|
|
75
|
+
text: "Verify"
|
|
76
|
+
optional: true
|
|
77
|
+
- waitForAnimationToEnd:
|
|
78
|
+
timeout: 3000
|
|
79
|
+
|
|
80
|
+
# Verify success message or enabled state
|
|
81
|
+
- assertVisible:
|
|
82
|
+
text:
|
|
83
|
+
- "enabled"
|
|
84
|
+
- "success"
|
|
85
|
+
- "active"
|
|
86
|
+
optional: true
|