diff --git a/run/screenshots/ios/app_disguise.png b/run/screenshots/ios/app_disguise.png index ea9203589..61afd67c7 100644 --- a/run/screenshots/ios/app_disguise.png +++ b/run/screenshots/ios/app_disguise.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba9f10f8b7f93eddd3140876abddc280f73ac121799f6444b03748fef6416183 -size 412401 +oid sha256:4f8740bf0dd72564a72f206f58ab83f1753899c6f27c48d7d85d1455b87d081a +size 416258 diff --git a/run/screenshots/ios/conversation_alice.png b/run/screenshots/ios/conversation_alice.png index b878e376e..72e854ce1 100644 --- a/run/screenshots/ios/conversation_alice.png +++ b/run/screenshots/ios/conversation_alice.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e98de34a24ae28e1bd6c98d6bebbeda3181c07d78e6d78c575634d482e916346 -size 271511 +oid sha256:c3fd3871b43cfc39a8c21b1c7c13deab6f6bfbe7ce93b189505b0071c38d2ac6 +size 196524 diff --git a/run/screenshots/ios/conversation_bob.png b/run/screenshots/ios/conversation_bob.png index 8905c6d4c..6fa2354d9 100644 --- a/run/screenshots/ios/conversation_bob.png +++ b/run/screenshots/ios/conversation_bob.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71acdda9e43b3fca337fb84d9e8cfdbc8f55723db490066c2ddaa9765c3665e6 -size 274324 +oid sha256:d3add2eecf4aaac282e426952bb6952ad35c24717346a9e341a78fa587af8013 +size 201385 diff --git a/run/screenshots/ios/landingpage_new_account.png b/run/screenshots/ios/landingpage_new_account.png index 5294449e4..30ff88c28 100644 --- a/run/screenshots/ios/landingpage_new_account.png +++ b/run/screenshots/ios/landingpage_new_account.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cc6a42ba1f85772e01439efc84a6b701e0aed645446f101a5ad04c68f059ceab -size 243367 +oid sha256:cf4373534d224dc42ac982e50e0c4b39e788185e6b1ded3e246107e35222e9cb +size 244717 diff --git a/run/screenshots/ios/landingpage_restore_account.png b/run/screenshots/ios/landingpage_restore_account.png index b0bc64d0f..7afaf6bb5 100644 --- a/run/screenshots/ios/landingpage_restore_account.png +++ b/run/screenshots/ios/landingpage_restore_account.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1ce512b2644c5a19e640c18604497b92a166d332ecd7f8ff93f01853197086a -size 188502 +oid sha256:5cd64fe2eca37efd4017d33b1d049044735d9232e4f34e7b069db12b92df0342 +size 189240 diff --git a/run/screenshots/ios/settings.png b/run/screenshots/ios/settings.png index 6617e2b8a..36407e7fe 100644 --- a/run/screenshots/ios/settings.png +++ b/run/screenshots/ios/settings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6de0b55dd8591b86184b0595db0d0936227201de59e1678a590e9378de24d58b -size 194857 +oid sha256:913069e5273ccb2d2fa66b82a87c93e9785b8d4118fd41b19b02a47105616aed +size 199238 diff --git a/run/screenshots/ios/settings_appearance.png b/run/screenshots/ios/settings_appearance.png index 1fab434de..3b0af2abc 100644 --- a/run/screenshots/ios/settings_appearance.png +++ b/run/screenshots/ios/settings_appearance.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:68f915b0b10251319d5ff411e915bb53bd90a741d211ec83abc1477d22be6b73 -size 172627 +oid sha256:cdcf364e3d7f52ab9070eec879396e4dc3248ed99b0bca1e8e4ca6e85157987e +size 176258 diff --git a/run/screenshots/ios/settings_conversations.png b/run/screenshots/ios/settings_conversations.png index 9b6223e45..e5c9b525d 100644 --- a/run/screenshots/ios/settings_conversations.png +++ b/run/screenshots/ios/settings_conversations.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5353c5341080a96c5403552229922a3ad2231d2caaefd2ad7f0926e6c9dbe40d -size 158985 +oid sha256:7946f0f6883d49937510af10f728a0420eff928af2e43fba20e6f1b4ad875f66 +size 161664 diff --git a/run/screenshots/ios/settings_notifications.png b/run/screenshots/ios/settings_notifications.png index f72b69b2c..6942b9b02 100644 --- a/run/screenshots/ios/settings_notifications.png +++ b/run/screenshots/ios/settings_notifications.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a61c285b9bf5000bad82fe51e99c98e67e8c9e1dafbe6e000901fa32aaa87c8d -size 164226 +oid sha256:3a45d13daf0fcf1be15a715695e4536c10a7ce83fb1a214f15ac8875a700a309 +size 166146 diff --git a/run/screenshots/ios/settings_privacy.png b/run/screenshots/ios/settings_privacy.png index 949ad81fe..67d565974 100644 --- a/run/screenshots/ios/settings_privacy.png +++ b/run/screenshots/ios/settings_privacy.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2af938c505bdfdc4ac2e0ea8f709fb44bf8de3a511ec9f3bdd8283b142297e32 -size 246739 +oid sha256:630706e45ae8a39288dd7e47f641f531a0c34299c5afd9d7155529d5388d598c +size 243706 diff --git a/run/test/locators/global_search.ts b/run/test/locators/global_search.ts index 2ece3811c..3d5ce95a8 100644 --- a/run/test/locators/global_search.ts +++ b/run/test/locators/global_search.ts @@ -13,7 +13,7 @@ export class CancelSearchButton extends LocatorsInterface { case 'ios': return { strategy: 'accessibility id', - selector: 'Cancel', + selector: 'Close', }; } } diff --git a/run/test/locators/settings.ts b/run/test/locators/settings.ts index 6db4471ce..7cf914570 100644 --- a/run/test/locators/settings.ts +++ b/run/test/locators/settings.ts @@ -155,6 +155,34 @@ export class HideRecoveryPasswordButton extends LocatorsInterface { } } +export class LockAppOption extends LocatorsInterface { + public build() { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'preferences-option-lock-app', + } as const; + case 'ios': + throw new Error('Not implemented on iOS'); + } + } +} + +export class LockAppToggle extends LocatorsInterface { + public build() { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'preferences-option-lock-app-toggle', + } as const; + case 'ios': + throw new Error('Not implemented on iOS'); + } + } +} + export class NotificationsMenuItem extends LocatorsInterface { public build() { switch (this.platform) { diff --git a/run/test/specs/community_requests_off.spec.ts b/run/test/specs/community_requests_off.spec.ts index 9a72f2b0d..9fa96ee10 100644 --- a/run/test/specs/community_requests_off.spec.ts +++ b/run/test/specs/community_requests_off.spec.ts @@ -15,7 +15,7 @@ bothPlatformsIt({ risk: 'medium', testCb: blindedMessageRequests, countOfDevicesNeeded: 2, - allureSuites: { parent: 'Settings', suite: 'Community Message Requests' }, + allureSuites: { parent: 'Settings', suite: 'Privacy' }, allureDescription: 'Verifies that a message request cannot be sent when Community Message Requests are off.', }); diff --git a/run/test/specs/community_requests_on.spec.ts b/run/test/specs/community_requests_on.spec.ts index caefd37a8..2a1c4ecbf 100644 --- a/run/test/specs/community_requests_on.spec.ts +++ b/run/test/specs/community_requests_on.spec.ts @@ -25,7 +25,7 @@ bothPlatformsIt({ risk: 'medium', testCb: blindedMessageRequests, countOfDevicesNeeded: 2, - allureSuites: { parent: 'Settings', suite: 'Community Message Requests' }, + allureSuites: { parent: 'Settings', suite: 'Privacy' }, allureDescription: 'Verifies that a message request can be sent when Community Message Requests are on.', allureLinks: { diff --git a/run/test/specs/message_requests_block.spec.ts b/run/test/specs/message_requests_block.spec.ts index 204d28dee..abdb74a6a 100644 --- a/run/test/specs/message_requests_block.spec.ts +++ b/run/test/specs/message_requests_block.spec.ts @@ -54,7 +54,7 @@ async function blockedRequest(platform: SupportedPlatformsType, testInfo: TestIn }), device3.verifyElementNotPresent({ ...new MessageRequestsBanner(device3).build(), - maxWait: 5_000, + maxWait: 10_000, }), ]); const blockedMessage = `"${alice.userName} to ${bob.userName} - shouldn't get through"`; diff --git a/run/test/specs/user_actions_lock_app.spec.ts b/run/test/specs/user_actions_lock_app.spec.ts new file mode 100644 index 000000000..bb0d99a8e --- /dev/null +++ b/run/test/specs/user_actions_lock_app.spec.ts @@ -0,0 +1,63 @@ +import { test, type TestInfo } from '@playwright/test'; + +import { TestSteps } from '../../types/allure'; +import { androidIt } from '../../types/sessionIt'; +import { USERNAME } from '../../types/testing'; +import { PlusButton } from '../locators/home'; +import { LockAppOption, LockAppToggle, PrivacyMenuItem, UserSettings } from '../locators/settings'; +import { newUser } from '../utils/create_account'; +import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from '../utils/open_app'; +import { forceStopAndRestart, runScriptAndLog } from '../utils/utilities'; + +// `xcrun simctl` doesn't support adding a pin like adb does so this is an Android only test +androidIt({ + title: 'Lock app', + risk: 'high', + testCb: lockApp, + countOfDevicesNeeded: 1, + allureSuites: { + parent: 'Settings', + suite: 'Privacy', + }, + allureDescription: + 'Verifies the app can be locked with a PIN and that the system lock screen appears on app launch when enabled.', +}); + +async function lockApp(platform: SupportedPlatformsType, testInfo: TestInfo) { + const pin = '12345678'; + const { device } = await test.step(TestSteps.SETUP.NEW_USER, async () => { + const { device } = await openAppOnPlatformSingleDevice(platform, testInfo); + await newUser(device, USERNAME.ALICE, { saveUserData: false }); + return { device }; + }); + try { + await test.step('Set device PIN', async () => { + await runScriptAndLog(`adb -s ${device.udid} shell locksettings set-pin ${pin}`, true); + }); + await test.step('Enable app lock', async () => { + await device.clickOnElementAll(new UserSettings(device)); + await device.clickOnElementAll(new PrivacyMenuItem(device)); + await device.clickOnElementAll(new LockAppOption(device)); + await device.assertAttribute(new LockAppToggle(device), 'checked', 'true'); + }); + await test.step('Force stop and restart app', async () => { + await forceStopAndRestart(device, false); + // The unlock screen is not visible to appium so there's no real way to tell it appeared + // Other than waiting a long time to make sure the home screen (plus button) never appeared + // This prevents the false positive where we send key events to nowhere and the lock screen never appeared anyway + await device.verifyElementNotPresent({ ...new PlusButton(device).build(), maxWait: 10_000 }); + }); + await test.step('Enter PIN to unlock app', async () => { + await runScriptAndLog(`adb -s ${device.udid} shell input text ${pin}`, true); + await runScriptAndLog(`adb -s ${device.udid} shell input keyevent 66`, true); + }); + await test.step('Verify home screen is visible', async () => { + await device.waitForTextElementToBePresent(new PlusButton(device)); + }); + await test.step(TestSteps.SETUP.CLOSE_APP, async () => { + await closeApp(device); + }); + } finally { + await runScriptAndLog(`adb -s ${device.udid} shell locksettings clear --old ${pin}`, true); + } +} diff --git a/run/test/utils/device_registry.ts b/run/test/utils/device_registry.ts index 4a7c731ce..5d8ba7f49 100644 --- a/run/test/utils/device_registry.ts +++ b/run/test/utils/device_registry.ts @@ -20,8 +20,8 @@ export type DeviceContext = { export const deviceRegistry = new Map(); -export function registryKey(testInfo: TestInfo, retry = testInfo.retry): string { - return `${testInfo.testId}-${testInfo.parallelIndex}-${testInfo.repeatEachIndex}-${retry}`; +export function registryKey(testInfo: TestInfo): string { + return `${testInfo.testId}-${testInfo.parallelIndex}-${testInfo.repeatEachIndex}`; } // Async because Android registration fetches per-device PID for scoped logcat on failure. @@ -59,8 +59,5 @@ export async function registerDevicesForTest( } export function unregisterDevicesForTest(testInfo: TestInfo) { - // Clean up current attempt and any stale entries left by prior retry attempts - for (let r = 0; r <= testInfo.retry; r++) { - deviceRegistry.delete(registryKey(testInfo, r)); - } + deviceRegistry.delete(registryKey(testInfo)); } diff --git a/run/test/utils/utilities.ts b/run/test/utils/utilities.ts index 7971ed384..d8e68538a 100644 --- a/run/test/utils/utilities.ts +++ b/run/test/utils/utilities.ts @@ -133,7 +133,10 @@ export async function clearStatusBarOverrides(device: DeviceWrapper): Promise { +export async function forceStopAndRestart( + device: DeviceWrapper, + waitForRestart: boolean = true +): Promise { if (device.isAndroid()) { await runScriptAndLog(`adb -s ${device.udid} shell am force-stop ${androidAppPackage}`, true); await sleepFor(1_000); @@ -148,8 +151,10 @@ export async function forceStopAndRestart(device: DeviceWrapper): Promise await runScriptAndLog(`xcrun simctl launch ${device.udid} ${iOSBundleId}`, true); await sleepFor(1_000); } - // Ensure we're on the home screen again - await device.waitForTextElementToBePresent(new PlusButton(device)); + // Ensure we're on the home screen again if desired + if (waitForRestart) { + await device.waitForTextElementToBePresent(new PlusButton(device)); + } } /** diff --git a/run/types/allure.ts b/run/types/allure.ts index fd621d9d2..6f416f8d1 100644 --- a/run/types/allure.ts +++ b/run/types/allure.ts @@ -34,7 +34,7 @@ export type AllureSuiteConfig = | { parent: 'Session Pro' } | { parent: 'Settings'; - suite: 'App Disguise' | 'Community Message Requests' | 'Notifications' | 'Recovery Password'; + suite: 'App Disguise' | 'Notifications' | 'Privacy' | 'Recovery Password'; } | { parent: 'User Actions'; diff --git a/run/types/testing.ts b/run/types/testing.ts index 72ad7c5bb..6e5dc38f8 100644 --- a/run/types/testing.ts +++ b/run/types/testing.ts @@ -580,6 +580,8 @@ export type Id = | 'Open URL' | 'preferences-dialog-option-enable' | 'preferences-option-blocked-contacts' + | 'preferences-option-lock-app-toggle' + | 'preferences-option-lock-app' | 'preferences-option-read-receipt' | 'preferences-option-whitelist-toggle' | 'preferred-display-name'