feat(release): prepare 1.1.0 candidate

This commit is contained in:
Yun Chan 2026-08-29 18:33:45 +09:00
parent 5a34f66981
commit 5205dcdfa9
736 changed files with 115667 additions and 12203 deletions

View file

@ -0,0 +1,37 @@
# Android clean-room E2E contract
이 디렉터리의 플로우는 `com.d3ro.voice`의 번들 포함 `e2e` APK를 Metro 없이 설치해 실행하는 출시 게이트다.
## 필수 게이트
| Flow | 계정 | 외부 쓰기 | 검증 범위 |
|---|---:|---:|---|
| `fresh-install-auth.yaml` | 없음 | 없음 | 기존 사용자 온보딩, 로그인/비밀번호 재설정 진입, 콜드 재실행 상태 유지, 비로그인 광고 차단 |
| `fresh-install-signup.yaml` | 없음 | 없음 | 5단계 튜토리얼, 새 사용자 회원가입 진입, 권한 deny/allow/deny 전환, 콜드 재실행, 비로그인 광고 차단 |
| `invite-deep-link.yaml` | 없음 | 로컬 pending token 저장 후 닫을 때 삭제 | 앱 소유 custom-scheme 라우터, 로그인 필수 경계, 비로그인 광고 차단 |
필수 게이트는 실제 가입, OAuth, 결제, 팀 가입, 서버 데이터 생성을 수행하지 않는다.
CI는 같은 `fresh-install-signup.yaml`을 기본 프로필과 `840x1490` 작은 화면에서 각각 실행하고, 실패 여부와 관계없이 디스플레이 override를 초기화한다. Maestro 실행 전에 debug 앱과 AndroidTest APK를 임시 설치해 `CsprngInstrumentedTest`를 한 번 실행한다. 이 계측 검사는 실제 Android `RNGetRandomValuesModule`에서 16바이트 엔트로피를 두 번 받아 길이, non-zero, 비동일성, UUID v4 version/variant 소비 계약을 확인한 뒤 두 패키지를 제거한다. 이후 검증 대상 E2E APK를 fresh install한다.
## 외부 계정 게이트
`authenticated-parity.yaml`은 CI에 `MOBILE_E2E_EMAIL``MOBILE_E2E_PASSWORD`가 모두 있을 때만 실행한다. 이 플로우는 다음을 실제 앱 UI에서 확인한다.
- Free 계정의 Google 테스트 배너 슬롯
- 마이크 권한 거부 오류와 권한 허용 후 녹음 시작/취소 복구
- sideload 환경의 Google Play 구매 차단
- 보상형 광고 상태 표시
- 계정, 기록, 녹음, Talk, 기기, 회의, 템플릿, 메모, 팀, 알림, 사전, 명령, 지식, 액션, 데이터 이동 화면
- 알림 권한 거부 상태와 허용 후 화면 재진입 복구
`invite-app-link-release.yaml`은 live `assetlinks.json`에 등록된 인증서로 서명한 release APK에서만 실행한다. E2E APK의 debug 인증서를 공개 App Link 신뢰 목록에 추가하지 않는다. 실제 OAuth 공급자 동의/콜백, Google Play 결제/복원, 광고 SSV 크레딧 적립, 외부 공유 대상 앱 확인도 공급자 계정과 배포 채널이 필요한 별도 출시 승인 항목이다. 이 저장소의 자동화는 성공을 위조하지 않으며, 실행하지 않은 항목을 CI 증거에 `NOT_RUN`으로 기록한다.
## 실행 전제
- `e2e` APK는 `debuggable=false`, `E2E_TEST_BUILD=true`, arm64-v8a+x86_64 universal이며 `assets/index.android.bundle`을 포함해야 한다. 같은 APK를 hosted x86_64 emulator와 arm64 실제 기기에 설치한다.
- `e2e` 및 release Gradle task는 strict SemVer `D3RO_VERSION_NAME`과 1 이상 `D3RO_VERSION_CODE`가 없으면 실패해야 한다. GitHub release는 workflow run number에 고정 offset을 더해 Play용 코드를 단조 증가시키고, GitLab E2E는 project pipeline IID를 사용한다.
- Google 공식 테스트 App ID 및 광고 단위만 E2E에 허용한다.
- E2E APK는 custom scheme으로 동일한 앱 내부 초대 라우터를 검증한다. HTTPS `autoVerify`는 release signer SHA-256을 live `/.well-known/assetlinks.json`과 대조한 release 전용 flow에서만 검증한다.
- release APK는 `E2E_TEST_BUILD=false`이고 Google 테스트 publisher ID를 포함하면 실패해야 한다.
- 에뮬레이터 게이트를 실행하는 동안 Metro 서버를 시작하면 안 된다.

View file

@ -0,0 +1,59 @@
appId: com.d3ro.voice
name: Continue local admin role update and cancel destructive subscription deletion
---
- assertVisible:
id: admin-mutation-modal
- tapOn:
id: admin-role-option-manager
- scrollUntilVisible:
element:
id: admin-memo-input
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: admin-memo-input
- inputText: admin-role-user-to-manager
- hideKeyboard
- scrollUntilVisible:
element:
id: admin-mutation-submit
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: admin-mutation-submit
- extendedWaitUntil:
notVisible:
id: admin-mutation-modal
timeout: 30000
- extendedWaitUntil:
visible:
id: admin-user-detail-screen
timeout: 30000
- scrollUntilVisible:
element:
id: admin-delete-subscription
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: admin-delete-subscription
- extendedWaitUntil:
visible:
id: admin-mutation-modal
timeout: 15000
- assertVisible:
id: admin-mutation-submit
- takeScreenshot: admin-local-admin-delete-confirmation
- tapOn:
text: "Cancel"
- extendedWaitUntil:
notVisible:
id: admin-mutation-modal
timeout: 15000
- assertVisible:
id: admin-user-detail-screen
- assertVisible:
id: admin-delete-subscription
- takeScreenshot: admin-local-admin-delete-cancelled

View file

@ -0,0 +1,139 @@
appId: com.d3ro.voice
name: Local paid admin hides ads and opens the role editor with bounded role choices
---
- launchApp:
clearState: true
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: onboarding-screen
timeout: 30000
- tapOn:
id: onboarding-language-en
- tapOn:
id: onboarding-audience-existing
- scrollUntilVisible:
element:
id: onboarding-skip
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: onboarding-skip
- extendedWaitUntil:
visible:
id: login-email
timeout: 30000
- tapOn:
id: login-email
- inputText: ${MAESTRO_ACTOR_EMAIL}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-password
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-password
- inputText: ${MAESTRO_ACTOR_PASSWORD}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-submit
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-submit
- extendedWaitUntil:
visible:
id: dashboard-scroll
timeout: 45000
- extendedWaitUntil:
visible:
id: dashboard-start-recording
timeout: 45000
- scrollUntilVisible:
element:
text: "PRO"
direction: DOWN
timeout: 30000
visibilityPercentage: 50
- assertNotVisible:
id: free-tier-ad-slot
- takeScreenshot: admin-local-paid-admin-ad-hidden
- tapOn:
id: tab-settings
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: settings-screen
timeout: 30000
- scrollUntilVisible:
element:
id: open-admin
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: open-admin
- extendedWaitUntil:
visible:
id: admin-screen
timeout: 30000
- tapOn:
id: admin-user-search
- inputText: ${MAESTRO_TARGET_NAME}
- extendedWaitUntil:
visible:
id: admin-user-${MAESTRO_TARGET_ID}
timeout: 30000
- waitForAnimationToEnd:
timeout: 3000
- tapOn:
id: admin-user-${MAESTRO_TARGET_ID}
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: admin-user-detail-screen
timeout: 30000
- assertVisible:
id: admin-change-role
- scrollUntilVisible:
element:
id: admin-delete-subscription
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- assertVisible:
id: admin-delete-subscription
- scrollUntilVisible:
element:
id: admin-change-role
direction: UP
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: admin-change-role
- extendedWaitUntil:
visible:
id: admin-mutation-modal
timeout: 15000
- assertVisible:
id: admin-role-option-user
enabled: true
- assertVisible:
id: admin-role-option-manager
enabled: true
- assertVisible:
id: admin-role-option-admin
enabled: false
- assertVisible:
id: admin-role-option-super_admin
enabled: false
- takeScreenshot: admin-local-admin-bounded-role-options

View file

@ -0,0 +1,35 @@
appId: com.d3ro.voice
name: Continue the same manager session and read the target user
---
- assertVisible:
id: dashboard-scroll
- tapOn:
id: tab-settings
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: settings-screen
timeout: 30000
- scrollUntilVisible:
element:
id: open-admin
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: open-admin
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: admin-screen
timeout: 30000
- tapOn:
id: admin-user-search
- inputText: ${MAESTRO_TARGET_NAME}
- extendedWaitUntil:
visible:
id: admin-user-${MAESTRO_TARGET_ID}
timeout: 30000
- takeScreenshot: admin-local-manager-read-user

View file

@ -0,0 +1,80 @@
appId: com.d3ro.voice
name: Continue the same manager session into subscription-only mutation
---
- assertVisible:
id: admin-screen
- assertVisible:
id: admin-user-${MAESTRO_TARGET_ID}
- waitForAnimationToEnd:
timeout: 3000
- tapOn:
id: admin-user-${MAESTRO_TARGET_ID}
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: admin-user-detail-screen
timeout: 30000
- assertNotVisible:
id: admin-change-role
- scrollUntilVisible:
element:
id: admin-edit-subscription
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- assertVisible:
id: admin-edit-subscription
- assertNotVisible:
id: admin-delete-subscription
- tapOn:
id: admin-edit-subscription
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: admin-mutation-modal
timeout: 15000
- scrollUntilVisible:
element:
id: admin-credits-input
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: admin-credits-input
- eraseText
- inputText: "17"
- hideKeyboard
- scrollUntilVisible:
element:
id: admin-memo-input
direction: DOWN
timeout: 30000
visibilityPercentage: 20
centerElement: true
- tapOn:
id: admin-memo-input
- inputText: manager-subscription-update
- hideKeyboard
- scrollUntilVisible:
element:
id: admin-mutation-submit
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: admin-mutation-submit
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
notVisible:
id: admin-mutation-modal
timeout: 30000
- assertVisible:
id: admin-user-detail-screen
- assertNotVisible:
id: admin-change-role
- assertNotVisible:
id: admin-delete-subscription
- takeScreenshot: admin-local-manager-subscription-updated

View file

@ -0,0 +1,63 @@
appId: com.d3ro.voice
name: Local manager reads users and updates an existing subscription only
---
- launchApp:
clearState: true
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: onboarding-screen
timeout: 30000
- tapOn:
id: onboarding-language-en
- tapOn:
id: onboarding-audience-existing
- scrollUntilVisible:
element:
id: onboarding-skip
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: onboarding-skip
- extendedWaitUntil:
visible:
id: login-email
timeout: 30000
- tapOn:
id: login-email
- inputText: ${MAESTRO_ACTOR_EMAIL}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-password
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-password
- inputText: ${MAESTRO_ACTOR_PASSWORD}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-submit
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-submit
- extendedWaitUntil:
visible:
id: dashboard-scroll
timeout: 45000
- scrollUntilVisible:
element:
text: "PRO"
direction: DOWN
timeout: 30000
visibilityPercentage: 50
- assertNotVisible:
id: free-tier-ad-slot
- takeScreenshot: admin-local-manager-pro-session

View file

@ -0,0 +1,22 @@
appId: com.d3ro.voice
name: Continue the same ordinary session and prove Admin remains hidden
---
- assertVisible:
id: dashboard-scroll
- tapOn:
id: tab-settings
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: settings-screen
timeout: 30000
- scrollUntilVisible:
element:
id: open-devices
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- assertNotVisible:
id: open-admin
- takeScreenshot: admin-local-ordinary-admin-hidden

View file

@ -0,0 +1,59 @@
appId: com.d3ro.voice
name: Local ordinary free user hides Admin and shows the test ad slot
---
- launchApp:
clearState: true
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: onboarding-screen
timeout: 30000
- tapOn:
id: onboarding-language-en
- tapOn:
id: onboarding-audience-existing
- scrollUntilVisible:
element:
id: onboarding-skip
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: onboarding-skip
- extendedWaitUntil:
visible:
id: login-email
timeout: 30000
- tapOn:
id: login-email
- inputText: ${MAESTRO_ACTOR_EMAIL}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-password
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-password
- inputText: ${MAESTRO_ACTOR_PASSWORD}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-submit
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-submit
- extendedWaitUntil:
visible:
id: dashboard-scroll
timeout: 45000
- extendedWaitUntil:
visible:
id: free-tier-ad-slot
timeout: 45000
- takeScreenshot: admin-local-ordinary-free-ad-visible

View file

@ -0,0 +1,20 @@
appId: com.d3ro.voice
name: Refresh stale manager Admin state after host-side downgrade and fail closed
---
- assertVisible:
id: admin-screen
- assertVisible:
id: admin-user-${MAESTRO_TARGET_ID}
- swipe:
start: 50%, 45%
end: 50%, 90%
duration: 1000
- extendedWaitUntil:
visible:
id: admin-error
timeout: 30000
- assertNotVisible:
id: admin-user-${MAESTRO_TARGET_ID}
- assertNotVisible:
id: admin-mutation-modal
- takeScreenshot: admin-local-stale-manager-forbidden-purged

View file

@ -0,0 +1,90 @@
appId: com.d3ro.voice
name: Open a sensitive Admin list with a manager session before host-side downgrade
---
- launchApp:
clearState: true
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: onboarding-screen
timeout: 30000
- tapOn:
id: onboarding-language-en
- tapOn:
id: onboarding-audience-existing
- scrollUntilVisible:
element:
id: onboarding-skip
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: onboarding-skip
- extendedWaitUntil:
visible:
id: login-email
timeout: 30000
- tapOn:
id: login-email
- inputText: ${MAESTRO_ACTOR_EMAIL}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-password
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-password
- inputText: ${MAESTRO_ACTOR_PASSWORD}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-submit
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-submit
- extendedWaitUntil:
visible:
id: dashboard-scroll
timeout: 45000
- scrollUntilVisible:
element:
text: "PRO"
direction: DOWN
timeout: 30000
visibilityPercentage: 50
- assertNotVisible:
id: free-tier-ad-slot
- tapOn:
id: tab-settings
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: settings-screen
timeout: 30000
- scrollUntilVisible:
element:
id: open-admin
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: open-admin
- extendedWaitUntil:
visible:
id: admin-screen
timeout: 30000
- tapOn:
id: admin-user-search
- inputText: ${MAESTRO_TARGET_NAME}
- extendedWaitUntil:
visible:
id: admin-user-${MAESTRO_TARGET_ID}
timeout: 30000
- takeScreenshot: admin-local-stale-manager-before-downgrade

View file

@ -0,0 +1,135 @@
appId: com.d3ro.voice
name: Local super administrator promotes a manager to administrator
---
- launchApp:
clearState: true
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: onboarding-screen
timeout: 30000
- tapOn:
id: onboarding-language-en
- tapOn:
id: onboarding-audience-existing
- scrollUntilVisible:
element:
id: onboarding-skip
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: onboarding-skip
- extendedWaitUntil:
visible:
id: login-email
timeout: 30000
- tapOn:
id: login-email
- inputText: ${MAESTRO_ACTOR_EMAIL}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-password
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-password
- inputText: ${MAESTRO_ACTOR_PASSWORD}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-submit
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-submit
- extendedWaitUntil:
visible:
id: dashboard-scroll
timeout: 45000
- scrollUntilVisible:
element:
text: "PRO"
direction: DOWN
timeout: 30000
visibilityPercentage: 50
- assertNotVisible:
id: free-tier-ad-slot
- tapOn:
id: tab-settings
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: settings-screen
timeout: 30000
- scrollUntilVisible:
element:
id: open-admin
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: open-admin
- extendedWaitUntil:
visible:
id: admin-screen
timeout: 30000
- tapOn:
id: admin-user-search
- inputText: ${MAESTRO_TARGET_NAME}
- extendedWaitUntil:
visible:
id: admin-user-${MAESTRO_TARGET_ID}
timeout: 30000
- waitForAnimationToEnd:
timeout: 3000
- tapOn:
id: admin-user-${MAESTRO_TARGET_ID}
retryTapIfNoChange: true
waitToSettleTimeoutMs: 2000
- extendedWaitUntil:
visible:
id: admin-user-detail-screen
timeout: 30000
- tapOn:
id: admin-change-role
- extendedWaitUntil:
visible:
id: admin-mutation-modal
timeout: 15000
- assertVisible:
id: admin-role-option-admin
enabled: true
- tapOn:
id: admin-role-option-admin
- scrollUntilVisible:
element:
id: admin-memo-input
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: admin-memo-input
- inputText: super-role-manager-to-admin
- hideKeyboard
- scrollUntilVisible:
element:
id: admin-mutation-submit
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: admin-mutation-submit
- extendedWaitUntil:
notVisible:
id: admin-mutation-modal
timeout: 30000
- assertVisible:
id: admin-user-detail-screen
- takeScreenshot: admin-local-super-role-promoted

View file

@ -0,0 +1,251 @@
appId: com.d3ro.voice
name: Authenticated mobile parity navigation and fail-closed billing
---
- launchApp:
clearState: true
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: onboarding-screen
timeout: 30000
- tapOn:
id: onboarding-language-en
- tapOn:
id: onboarding-audience-existing
- tapOn:
id: onboarding-skip
- extendedWaitUntil:
visible:
id: login-email
timeout: 30000
- tapOn:
id: login-email
- inputText: ${MOBILE_E2E_EMAIL}
- tapOn:
id: login-password
- inputText: ${MOBILE_E2E_PASSWORD}
- tapOn:
id: login-submit
- extendedWaitUntil:
visible:
id: dashboard-scroll
timeout: 45000
- assertVisible:
id: free-tier-ad-slot
- takeScreenshot: authenticated-free-test-ad-slot
- tapOn:
id: tab-works
- assertVisible:
id: works-screen
- tapOn:
id: open-history
- assertVisible:
id: history-search
- pressKey: BACK
- tapOn:
id: tab-record
- assertVisible:
id: record-screen
- assertVisible:
id: record-import-file
- tapOn:
id: record-start
- tapOn:
text: "Don.t allow"
optional: true
- extendedWaitUntil:
visible:
id: record-error
timeout: 10000
- setPermissions:
permissions:
microphone: allow
- tapOn:
id: record-start
- extendedWaitUntil:
visible:
id: record-stop
timeout: 15000
- tapOn:
id: record-cancel
- extendedWaitUntil:
visible:
id: record-start
timeout: 15000
- tapOn:
id: tab-talk
- assertVisible:
id: talk-messages
- assertVisible:
id: talk-ptt
- tapOn:
id: tab-settings
- assertVisible:
id: settings-screen
- scrollUntilVisible:
element:
id: open-account
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-account
- assertVisible:
id: account-logout
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-paywall
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-paywall
- assertVisible:
id: paywall-screen
- assertVisible:
id: rewarded-ad-status
- assertVisible:
id: store-products-unavailable
- tapOn:
id: paywall-close
- scrollUntilVisible:
element:
id: open-devices
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-devices
- assertVisible:
id: devices-screen
- pressKey: BACK
- assertVisible:
id: settings-screen
- tapOn:
id: tab-works
- assertVisible:
id: works-screen
- scrollUntilVisible:
element:
id: open-meetings
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-meetings
- extendedWaitUntil:
visible:
id: meetings-search
timeout: 30000
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-templates
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-templates
- assertVisible:
id: templates-screen
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-memos
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-memos
- assertVisible:
id: memos-screen
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-teams
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-teams
- assertVisible:
id: teams-screen
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-notifications
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-notifications
- assertVisible:
id: notifications-screen
- extendedWaitUntil:
visible:
id: notifications-request-permission
timeout: 10000
- setPermissions:
permissions:
notifications: allow
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-notifications
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-notifications
- assertVisible:
id: notification-status-card
- assertNotVisible:
id: notifications-request-permission
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-data-portability
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-data-portability
- assertVisible:
id: data-portability-screen
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-dictionary
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-dictionary
- assertVisible:
id: dictionary-screen
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-commands
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-commands
- assertVisible:
id: commands-screen
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-knowledge
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-knowledge
- assertVisible:
id: knowledge-screen
- pressKey: BACK
- scrollUntilVisible:
element:
id: open-actions
direction: DOWN
visibilityPercentage: 50
- tapOn:
id: open-actions
- assertVisible:
id: actions-screen
- pressKey: BACK
- assertVisible:
id: works-screen
- takeScreenshot: authenticated-parity-complete

View file

@ -0,0 +1,103 @@
appId: com.d3ro.voice
name: Fresh install onboarding and authentication boundary
---
- launchApp:
clearState: true
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: onboarding-screen
timeout: 30000
- assertVisible:
id: onboarding-step-1
- assertNotVisible:
id: free-tier-ad-slot
- tapOn:
id: onboarding-language-en
- tapOn:
id: onboarding-audience-existing
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: onboarding-next
direction: DOWN
timeout: 10000
visibilityPercentage: 50
- tapOn:
id: onboarding-next
- scrollUntilVisible:
element:
id: onboarding-step-2
direction: UP
timeout: 10000
visibilityPercentage: 50
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: onboarding-back
direction: DOWN
timeout: 10000
visibilityPercentage: 50
- tapOn:
id: onboarding-back
- scrollUntilVisible:
element:
id: onboarding-step-1
direction: UP
timeout: 10000
visibilityPercentage: 50
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: onboarding-skip
direction: DOWN
timeout: 10000
visibilityPercentage: 50
- tapOn:
id: onboarding-skip
- extendedWaitUntil:
visible:
id: login-email
timeout: 30000
- assertVisible:
id: login-password
- assertVisible:
id: login-submit
- assertNotVisible:
id: free-tier-ad-slot
- tapOn:
id: forgot-password
- assertVisible:
id: request-password-reset
- pressKey: BACK
- assertVisible:
id: login-submit
- assertVisible:
id: open-sign-up
- killApp
- launchApp:
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: login-submit
timeout: 30000
- assertVisible:
id: login-email
- assertNotVisible:
id: onboarding-screen
- assertNotVisible:
id: free-tier-ad-slot
- takeScreenshot: fresh-install-existing-login-boundary

View file

@ -0,0 +1,155 @@
appId: com.d3ro.voice
name: Fresh install complete tutorial and new-account boundary
---
- launchApp:
clearState: true
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: onboarding-step-1
timeout: 30000
- assertNotVisible:
id: free-tier-ad-slot
- tapOn:
id: onboarding-language-en
- tapOn:
id: onboarding-audience-new
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: onboarding-next
direction: DOWN
timeout: 10000
visibilityPercentage: 50
- tapOn:
id: onboarding-next
- scrollUntilVisible:
element:
id: onboarding-step-2
direction: UP
timeout: 10000
visibilityPercentage: 50
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: onboarding-next
direction: DOWN
timeout: 10000
visibilityPercentage: 50
- tapOn:
id: onboarding-next
- scrollUntilVisible:
element:
id: onboarding-step-3
direction: UP
timeout: 10000
visibilityPercentage: 50
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: onboarding-next
direction: DOWN
timeout: 10000
visibilityPercentage: 50
- tapOn:
id: onboarding-next
- scrollUntilVisible:
element:
id: onboarding-step-4
direction: UP
timeout: 10000
visibilityPercentage: 50
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: onboarding-next
direction: DOWN
timeout: 10000
visibilityPercentage: 50
- tapOn:
id: onboarding-next
- scrollUntilVisible:
element:
id: onboarding-step-5
direction: UP
timeout: 10000
visibilityPercentage: 50
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: onboarding-theme-dark
direction: DOWN
timeout: 10000
visibilityPercentage: 50
- tapOn:
id: onboarding-theme-dark
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: onboarding-complete
direction: DOWN
timeout: 10000
visibilityPercentage: 50
- tapOn:
id: onboarding-complete
- swipe:
start: 50%, 90%
end: 50%, 10%
duration: 800
- scrollUntilVisible:
element:
id: sign-up-submit
direction: DOWN
timeout: 20000
visibilityPercentage: 50
- assertNotVisible:
id: free-tier-ad-slot
- killApp
- launchApp:
stopApp: true
permissions:
microphone: allow
notifications: allow
- extendedWaitUntil:
visible:
id: login-submit
timeout: 30000
- assertNotVisible:
id: onboarding-screen
- assertNotVisible:
id: free-tier-ad-slot
- setPermissions:
permissions:
microphone: deny
notifications: deny
- killApp
- launchApp:
stopApp: true
permissions:
microphone: deny
notifications: deny
- assertVisible:
id: login-submit
- assertNotVisible:
id: free-tier-ad-slot
- takeScreenshot: fresh-install-new-account-boundary

View file

@ -0,0 +1,25 @@
appId: com.d3ro.voice
name: External Android content provider share routes to durable transcription queue
---
- extendedWaitUntil:
visible:
id: record-screen
timeout: 30000
- extendedWaitUntil:
visible:
id: record-retry-queued
timeout: 60000
- assertVisible:
id: record-error
- assertVisible:
id: record-cancel-queued
- takeScreenshot: incoming-share-local-queued
- tapOn:
id: record-cancel-queued
- extendedWaitUntil:
visible:
id: record-import-file
timeout: 30000
- assertNotVisible:
id: record-retry-queued
- takeScreenshot: incoming-share-local-cleaned

View file

@ -0,0 +1,56 @@
appId: com.d3ro.voice
name: Local authenticated session for external incoming-media E2E
---
- launchApp:
clearState: true
stopApp: true
permissions:
all: deny
- extendedWaitUntil:
visible:
id: onboarding-screen
timeout: 30000
- tapOn:
id: onboarding-language-en
- tapOn:
id: onboarding-audience-existing
- scrollUntilVisible:
element:
id: onboarding-skip
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: onboarding-skip
- extendedWaitUntil:
visible:
id: login-email
timeout: 30000
- tapOn:
id: login-email
- inputText: ${MAESTRO_ACTOR_EMAIL}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-password
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-password
- inputText: ${MAESTRO_ACTOR_PASSWORD}
- hideKeyboard
- scrollUntilVisible:
element:
id: login-submit
direction: DOWN
timeout: 15000
visibilityPercentage: 50
- tapOn:
id: login-submit
- extendedWaitUntil:
visible:
id: dashboard-scroll
timeout: 45000
- assertNotVisible:
id: free-tier-ad-slot

View file

@ -0,0 +1,53 @@
appId: com.d3ro.voice
name: Release-signed warm and cold canonical HTTPS team invite App Link
---
- launchApp:
stopApp: true
- extendedWaitUntil:
visible:
id: login-submit
timeout: 30000
- openLink:
link: "https://d3ro.chanpaca.net/accept-invite/?token=00000000000000000000000000000000"
autoVerify: true
- extendedWaitUntil:
visible:
id: invite-accept-screen
timeout: 30000
- extendedWaitUntil:
visible:
id: invite-login-required
timeout: 10000
- assertNotVisible:
id: free-tier-ad-slot
- assertVisible:
id: invite-close
- tapOn:
id: invite-close
- assertNotVisible:
id: invite-accept-screen
- assertVisible:
id: login-submit
- assertNotVisible:
id: free-tier-ad-slot
- killApp
- openLink:
link: "https://d3ro.chanpaca.net/accept-invite/?token=11111111111111111111111111111111"
autoVerify: true
- extendedWaitUntil:
visible:
id: invite-accept-screen
timeout: 30000
- extendedWaitUntil:
visible:
id: invite-login-required
timeout: 10000
- assertNotVisible:
id: free-tier-ad-slot
- tapOn:
id: invite-close
- assertNotVisible:
id: invite-accept-screen
- assertVisible:
id: login-submit
- takeScreenshot: release-app-link-warm-and-cold-boundary

View file

@ -0,0 +1,49 @@
appId: com.d3ro.voice
name: Warm and cold invite deep-link router boundary
---
- launchApp:
stopApp: true
- extendedWaitUntil:
visible:
id: login-submit
timeout: 30000
- openLink: "d3ro-voice://accept-invite/?token=00000000000000000000000000000000"
- extendedWaitUntil:
visible:
id: invite-accept-screen
timeout: 30000
- extendedWaitUntil:
visible:
id: invite-login-required
timeout: 10000
- assertNotVisible:
id: free-tier-ad-slot
- assertVisible:
id: invite-close
- tapOn:
id: invite-close
- assertNotVisible:
id: invite-accept-screen
- assertVisible:
id: login-submit
- assertNotVisible:
id: free-tier-ad-slot
- killApp
- openLink: "d3ro-voice://accept-invite/?token=11111111111111111111111111111111"
- extendedWaitUntil:
visible:
id: invite-accept-screen
timeout: 30000
- extendedWaitUntil:
visible:
id: invite-login-required
timeout: 10000
- assertNotVisible:
id: free-tier-ad-slot
- tapOn:
id: invite-close
- assertNotVisible:
id: invite-accept-screen
- assertVisible:
id: login-submit
- takeScreenshot: invite-warm-and-cold-login-required-boundary