diff --git a/run/test/specs/community_tests_join.spec.ts b/run/test/specs/community_tests_join.spec.ts index 230ad2f..35472b1 100644 --- a/run/test/specs/community_tests_join.spec.ts +++ b/run/test/specs/community_tests_join.spec.ts @@ -1,5 +1,6 @@ import { testCommunityLink, testCommunityName } from '../../constants/community'; import { bothPlatformsIt } from '../../types/sessionIt'; +import { ConversationItem } from './locators/home'; import { open_Alice2 } from './state_builder'; import { joinCommunity } from './utils/join_community'; import { SupportedPlatformsType, closeApp } from './utils/open_app'; @@ -21,10 +22,6 @@ async function joinCommunityTest(platform: SupportedPlatformsType) { await alice1.onIOS().scrollToBottom(); await alice1.sendMessage(testMessage); // Has community synced to device 2? - await alice2.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: testCommunityName, - }); + await alice2.waitForTextElementToBePresent(new ConversationItem(alice2, testCommunityName)); await closeApp(alice1, alice2); } diff --git a/run/test/specs/disappear_after_send_note_to_self.spec.ts b/run/test/specs/disappear_after_send_note_to_self.spec.ts index 9ce095e..6610873 100644 --- a/run/test/specs/disappear_after_send_note_to_self.spec.ts +++ b/run/test/specs/disappear_after_send_note_to_self.spec.ts @@ -1,7 +1,7 @@ import { bothPlatformsIt } from '../../types/sessionIt'; import { DisappearActions, DISAPPEARING_TIMES, USERNAME } from '../../types/testing'; -import { MessageInput } from './locators/conversation'; -import { EnterAccountID } from './locators/start_conversation'; +import { PlusButton } from './locators/home'; +import { EnterAccountID, NewMessageOption, NextButton } from './locators/start_conversation'; import { sleepFor } from './utils'; import { newUser } from './utils/create_account'; import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from './utils/open_app'; @@ -21,12 +21,15 @@ async function disappearAfterSendNoteToSelf(platform: SupportedPlatformsType) { const controlMode: DisappearActions = 'sent'; const time = DISAPPEARING_TIMES.THIRTY_SECONDS; // Send message to self to bring up Note to Self conversation - await device.clickOnByAccessibilityID('New conversation button'); - await device.clickOnByAccessibilityID('New direct message'); + await device.clickOnElementAll(new PlusButton(device)); + await device.clickOnElementAll(new NewMessageOption(device)); await device.inputText(alice.accountID, new EnterAccountID(device)); await device.scrollDown(); - await device.clickOnByAccessibilityID('Next'); - await device.inputText('Creating note to self', new MessageInput(device)); + await device.clickOnElementAll(new NextButton(device)); + await device.inputText('Creating note to self', { + strategy: 'accessibility id', + selector: 'Message input box', + }); await device.clickOnByAccessibilityID('Send message button'); // Enable disappearing messages await setDisappearingMessage(platform, device, [ diff --git a/run/test/specs/disappearing_call.spec.ts b/run/test/specs/disappearing_call.spec.ts index 6fd4886..86620fc 100644 --- a/run/test/specs/disappearing_call.spec.ts +++ b/run/test/specs/disappearing_call.spec.ts @@ -1,5 +1,7 @@ import { bothPlatformsItSeparate } from '../../types/sessionIt'; import { DISAPPEARING_TIMES } from '../../types/testing'; +import { CallButton } from './locators/conversation'; +import { ContinueButton } from './locators/global'; import { open_Alice1_Bob1_friends } from './state_builder'; import { sleepFor } from './utils'; import { SupportedPlatformsType, closeApp } from './utils/open_app'; @@ -31,8 +33,7 @@ async function disappearingCallMessage1o1Ios(platform: SupportedPlatformsType) { focusFriendsConvo: true, }); await setDisappearingMessage(platform, alice1, ['1:1', timerType, time], bob1); - // await alice1.navigateBack(); - await alice1.clickOnByAccessibilityID('Call'); + await alice1.clickOnElementAll(new CallButton(alice1)); // Enabled voice calls in privacy settings await alice1.waitForTextElementToBePresent({ strategy: 'accessibility id', @@ -46,7 +47,7 @@ async function disappearingCallMessage1o1Ios(platform: SupportedPlatformsType) { strategy: 'accessibility id', selector: 'Allow voice and video calls', }); - await alice1.clickOnByAccessibilityID('Continue'); + await alice1.clickOnElementAll(new ContinueButton(alice1)); // Navigate back to conversation await sleepFor(500); await alice1.clickOnByAccessibilityID('Close button'); @@ -62,7 +63,7 @@ async function disappearingCallMessage1o1Ios(platform: SupportedPlatformsType) { await sleepFor(500, true); await bob1.clickOnByAccessibilityID('Close button'); // Make call on device 1 (alice) - await alice1.clickOnByAccessibilityID('Call'); + await alice1.clickOnElementAll(new CallButton(alice1)); // Answer call on device 2 await bob1.clickOnByAccessibilityID('Answer call'); // Wait 30 seconds @@ -98,15 +99,12 @@ async function disappearingCallMessage1o1Android(platform: SupportedPlatformsTyp focusFriendsConvo: true, }); await setDisappearingMessage(platform, alice1, ['1:1', timerType, time], bob1); - - // await alice1.navigateBack(); - await alice1.clickOnByAccessibilityID('Call'); + await alice1.clickOnElementAll(new CallButton(alice1)); // Enabled voice calls in privacy settings await alice1.waitForTextElementToBePresent({ strategy: 'accessibility id', selector: 'Settings', }); - // Scroll to bottom of page to voice and video calls await sleepFor(1000); await alice1.scrollDown(); @@ -115,7 +113,6 @@ async function disappearingCallMessage1o1Android(platform: SupportedPlatformsTyp selector: 'android:id/summary', text: 'Enables voice and video calls to and from other users.', }); - await alice1.click(voicePermissions.ELEMENT); // Toggle voice settings on // Click enable on exposure IP address warning @@ -128,7 +125,6 @@ async function disappearingCallMessage1o1Android(platform: SupportedPlatformsTyp await alice1.clickOnElementById( 'com.android.permissioncontroller:id/permission_allow_foreground_only_button' ); - await alice1.navigateBack(); // Enable voice calls on device 2 for User B await bob1.clickOnByAccessibilityID('Call'); @@ -138,7 +134,6 @@ async function disappearingCallMessage1o1Android(platform: SupportedPlatformsTyp selector: 'Settings', text: 'Settings', }); - await bob1.clickOnElementAll({ strategy: 'accessibility id', selector: 'Settings', @@ -151,7 +146,6 @@ async function disappearingCallMessage1o1Android(platform: SupportedPlatformsTyp selector: 'android:id/summary', text: 'Enables voice and video calls to and from other users.', }); - await bob1.click(voicePermissions2.ELEMENT); // Toggle voice settings on // Click enable on exposure IP address warning @@ -166,7 +160,7 @@ async function disappearingCallMessage1o1Android(platform: SupportedPlatformsTyp ); await bob1.navigateBack(); // Make call on device 1 (alice) - await alice1.clickOnByAccessibilityID('Call'); + await alice1.clickOnElementAll(new CallButton(alice1)); // Answer call on device 2 await bob1.clickOnByAccessibilityID('Answer call'); // Wait 5 seconds diff --git a/run/test/specs/group_message_long_text.spec.ts b/run/test/specs/group_message_long_text.spec.ts index 567032d..3cce2d2 100644 --- a/run/test/specs/group_message_long_text.spec.ts +++ b/run/test/specs/group_message_long_text.spec.ts @@ -3,6 +3,7 @@ import { bothPlatformsItSeparate } from '../../types/sessionIt'; import { open_Alice1_Bob1_Charlie1_friends_group } from './state_builder'; import { SupportedPlatformsType, closeApp } from './utils/open_app'; import { OutgoingMessageStatusSent } from './locators/conversation'; +import { ConversationItem } from './locators/home'; bothPlatformsItSeparate({ title: 'Send long message to group', @@ -95,11 +96,7 @@ async function sendLongMessageGroupAndroid(platform: SupportedPlatformsType) { const replyMessage = await bob1.sendMessage(`${alice.userName} message reply`); // Go out and back into the group to see the last message await alice1.navigateBack(); - await alice1.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: testGroupName, - }); + await alice1.clickOnElementAll(new ConversationItem(alice1, testGroupName)); await alice1.waitForTextElementToBePresent({ strategy: 'accessibility id', selector: 'Message body', @@ -107,11 +104,7 @@ async function sendLongMessageGroupAndroid(platform: SupportedPlatformsType) { }); // Go out and back into the group to see the last message await charlie1.navigateBack(); - await charlie1.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: testGroupName, - }); + await charlie1.clickOnElementAll(new ConversationItem(charlie1, testGroupName)); await charlie1.waitForTextElementToBePresent({ strategy: 'accessibility id', selector: 'Message body', diff --git a/run/test/specs/group_tests_add_contact.spec.ts b/run/test/specs/group_tests_add_contact.spec.ts index feba3a0..c26879d 100644 --- a/run/test/specs/group_tests_add_contact.spec.ts +++ b/run/test/specs/group_tests_add_contact.spec.ts @@ -5,6 +5,7 @@ import { EditGroup, InviteContactsButton, InviteContactsMenuItem } from './locat import { ConversationSettings } from './locators/conversation'; import { Contact } from './locators/global'; import { InviteContactConfirm } from './locators/groups'; +import { ConversationItem } from './locators/home'; import { open_Alice1_Bob1_Charlie1_Unknown1 } from './state_builder'; import { sleepFor } from './utils'; import { newUser } from './utils/create_account'; @@ -33,11 +34,7 @@ async function addContactToGroup(platform: SupportedPlatformsType) { // Exit to conversation list await alice1.navigateBack(); // Select group conversation in list - await alice1.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: group.groupName, - }); + await alice1.clickOnElementAll(new ConversationItem(alice1, testGroupName)); // Click more options await alice1.clickOnElementAll(new ConversationSettings(alice1)); // Select edit group diff --git a/run/test/specs/group_tests_leave_group.spec.ts b/run/test/specs/group_tests_leave_group.spec.ts index 11979bd..225538e 100644 --- a/run/test/specs/group_tests_leave_group.spec.ts +++ b/run/test/specs/group_tests_leave_group.spec.ts @@ -1,7 +1,8 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../types/sessionIt'; import { ConversationSettings } from './locators/conversation'; -import { LeaveGroupButton } from './locators/groups'; +import { LeaveGroupButton, LeaveGroupConfirm } from './locators/groups'; +import { ConversationItem } from './locators/home'; import { open_Alice1_Bob1_Charlie1_friends_group } from './state_builder'; import { sleepFor } from './utils/index'; import { SupportedPlatformsType, closeApp } from './utils/open_app'; @@ -28,7 +29,7 @@ async function leaveGroup(platform: SupportedPlatformsType) { await sleepFor(1000); await charlie1.clickOnElementAll(new LeaveGroupButton(charlie1)); // Modal with Leave/Cancel - await charlie1.clickOnByAccessibilityID('Leave'); + await charlie1.clickOnElementAll(new LeaveGroupConfirm(charlie1)); // Check for control message const groupMemberLeft = englishStrippedStr('groupMemberLeft') .withArgs({ name: charlie.userName }) @@ -37,9 +38,7 @@ async function leaveGroup(platform: SupportedPlatformsType) { await bob1.waitForControlMessageToBePresent(groupMemberLeft); // Check device 3 that group has disappeared await charlie1.hasElementBeenDeleted({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: testGroupName, + ...new ConversationItem(charlie1, testGroupName).build(), maxWait: 5000, }); await closeApp(alice1, bob1, charlie1); diff --git a/run/test/specs/input_validations/onboarding_incorrect_seed.spec.ts b/run/test/specs/input_validations/onboarding_incorrect_seed.spec.ts index 68be409..bc2269b 100644 --- a/run/test/specs/input_validations/onboarding_incorrect_seed.spec.ts +++ b/run/test/specs/input_validations/onboarding_incorrect_seed.spec.ts @@ -1,12 +1,8 @@ import { englishStrippedStr } from '../../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../../types/sessionIt'; -import { - AccountRestoreButton, - ContinueButton, - ErrorMessage, - SeedPhraseInput, -} from '../locators/onboarding'; +import { AccountRestoreButton, ErrorMessage, SeedPhraseInput } from '../locators/onboarding'; import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from '../utils/open_app'; +import { ContinueButton } from '../locators/global'; bothPlatformsIt({ title: 'Onboarding incorrect seed', diff --git a/run/test/specs/input_validations/onboarding_long_name.spec.ts b/run/test/specs/input_validations/onboarding_long_name.spec.ts index c6b3d98..2976e35 100644 --- a/run/test/specs/input_validations/onboarding_long_name.spec.ts +++ b/run/test/specs/input_validations/onboarding_long_name.spec.ts @@ -1,12 +1,8 @@ import { englishStrippedStr } from '../../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../../types/sessionIt'; -import { - ContinueButton, - CreateAccountButton, - DisplayNameInput, - ErrorMessage, -} from '../locators/onboarding'; +import { CreateAccountButton, DisplayNameInput, ErrorMessage } from '../locators/onboarding'; import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from '../utils/open_app'; +import { ContinueButton } from '../locators/global'; bothPlatformsIt({ title: 'Onboarding long name', diff --git a/run/test/specs/input_validations/onboarding_no_name.spec.ts b/run/test/specs/input_validations/onboarding_no_name.spec.ts index 8b5acd6..9982931 100644 --- a/run/test/specs/input_validations/onboarding_no_name.spec.ts +++ b/run/test/specs/input_validations/onboarding_no_name.spec.ts @@ -1,12 +1,8 @@ import { englishStrippedStr } from '../../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../../types/sessionIt'; -import { - ContinueButton, - CreateAccountButton, - DisplayNameInput, - ErrorMessage, -} from '../locators/onboarding'; +import { CreateAccountButton, DisplayNameInput, ErrorMessage } from '../locators/onboarding'; import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from '../utils/open_app'; +import { ContinueButton } from '../locators/global'; bothPlatformsIt({ title: 'Onboarding no name', diff --git a/run/test/specs/input_validations/onboarding_no_seed.spec.ts b/run/test/specs/input_validations/onboarding_no_seed.spec.ts index 7028c84..f2a6c14 100644 --- a/run/test/specs/input_validations/onboarding_no_seed.spec.ts +++ b/run/test/specs/input_validations/onboarding_no_seed.spec.ts @@ -1,12 +1,8 @@ import { englishStrippedStr } from '../../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../../types/sessionIt'; -import { - AccountRestoreButton, - ContinueButton, - ErrorMessage, - SeedPhraseInput, -} from '../locators/onboarding'; +import { AccountRestoreButton, ErrorMessage, SeedPhraseInput } from '../locators/onboarding'; import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from '../utils/open_app'; +import { ContinueButton } from '../locators/global'; bothPlatformsIt({ title: 'Onboarding no seed', diff --git a/run/test/specs/input_validations/onboarding_wrong_seed.spec.ts b/run/test/specs/input_validations/onboarding_wrong_seed.spec.ts index eaad9f2..d883634 100644 --- a/run/test/specs/input_validations/onboarding_wrong_seed.spec.ts +++ b/run/test/specs/input_validations/onboarding_wrong_seed.spec.ts @@ -1,12 +1,8 @@ import { englishStrippedStr } from '../../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../../types/sessionIt'; -import { - AccountRestoreButton, - ContinueButton, - ErrorMessage, - SeedPhraseInput, -} from '../locators/onboarding'; +import { AccountRestoreButton, ErrorMessage, SeedPhraseInput } from '../locators/onboarding'; import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from '../utils/open_app'; +import { ContinueButton } from '../locators/global'; bothPlatformsIt({ title: 'Onboarding wrong seed', diff --git a/run/test/specs/linked_device_block_user.spec.ts b/run/test/specs/linked_device_block_user.spec.ts index 2f29217..493c7fb 100644 --- a/run/test/specs/linked_device_block_user.spec.ts +++ b/run/test/specs/linked_device_block_user.spec.ts @@ -2,7 +2,8 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../types/sessionIt'; import { BlockedContactsSettings, BlockUser, BlockUserConfirmationModal } from './locators'; import { ConversationSettings } from './locators/conversation'; -import { UserSettings } from './locators/settings'; +import { ConversationItem } from './locators/home'; +import { ConversationsMenuItem, UserSettings } from './locators/settings'; import { open_Alice2_Bob1_friends } from './state_builder'; import { sleepFor } from './utils'; import { closeApp, SupportedPlatformsType } from './utils/open_app'; @@ -44,11 +45,7 @@ async function blockUserInConversationOptions(platform: SupportedPlatformsType) }); if (blockedStatus) { // Check linked device for blocked status (if shown on alice1) - await alice2.onAndroid().clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: `${bob.userName}`, - }); + await alice2.onAndroid().clickOnElementAll(new ConversationItem(alice2, bob.userName)); await alice2.onAndroid().waitForTextElementToBePresent({ strategy: 'accessibility id', selector: 'Blocked banner', @@ -66,8 +63,8 @@ async function blockUserInConversationOptions(platform: SupportedPlatformsType) // 'Conversations' might be hidden beyond the Settings view, gotta scroll down to find it await Promise.all([alice1.scrollDown(), alice2.scrollDown()]); await Promise.all([ - alice1.clickOnElementAll({ strategy: 'accessibility id', selector: 'Conversations' }), - alice2.clickOnElementAll({ strategy: 'accessibility id', selector: 'Conversations' }), + alice1.clickOnElementAll(new ConversationsMenuItem(alice1)), + alice2.clickOnElementAll(new ConversationsMenuItem(alice2)), ]); await Promise.all([ alice1.clickOnElementAll(new BlockedContactsSettings(alice1)), diff --git a/run/test/specs/linked_device_create_group.spec.ts b/run/test/specs/linked_device_create_group.spec.ts index 93d624c..6fc851e 100644 --- a/run/test/specs/linked_device_create_group.spec.ts +++ b/run/test/specs/linked_device_create_group.spec.ts @@ -2,8 +2,9 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsItSeparate } from '../../types/sessionIt'; import { USERNAME } from '../../types/testing'; import { EditGroup, EditGroupName } from './locators'; -import { ConversationSettings } from './locators/conversation'; +import { ConversationHeaderName, ConversationSettings } from './locators/conversation'; import { EditGroupNameInput } from './locators/groups'; +import { ConversationItem } from './locators/home'; import { SaveNameChangeButton } from './locators/settings'; import { sleepFor } from './utils'; import { newUser } from './utils/create_account'; @@ -35,11 +36,7 @@ async function linkedGroupiOS(platform: SupportedPlatformsType) { // Note we keep this createGroup here as we want it to **indeed** use the UI to create the group await createGroup(platform, device1, alice, device3, bob, device4, charlie, testGroupName); // Test that group has loaded on linked device - await device2.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: testGroupName, - }); + await device2.clickOnElementAll(new ConversationItem(device2, testGroupName)); // Change group name in device 1 // Click on settings/more info await device1.clickOnElementAll(new ConversationSettings(device1)); @@ -69,11 +66,9 @@ async function linkedGroupiOS(platform: SupportedPlatformsType) { // Wait 5 seconds for name to update await sleepFor(5000); // Check linked device for name change (conversation header name) - await device2.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Conversation header name', - text: newGroupName, - }); + await device2.waitForTextElementToBePresent( + new ConversationHeaderName(device2).build(newGroupName) + ); await Promise.all([ device2.waitForControlMessageToBePresent(groupNameNew), device3.waitForControlMessageToBePresent(groupNameNew), @@ -96,11 +91,7 @@ async function linkedGroupAndroid(platform: SupportedPlatformsType) { // Note we keep this createGroup here as we want it to **indeed** use the UI to create the group await createGroup(platform, device1, alice, device3, bob, device4, charlie, testGroupName); // Test that group has loaded on linked device - await device2.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: testGroupName, - }); + await device2.clickOnElementAll(new ConversationItem(device2, testGroupName)); // Click on settings or three dots await device1.clickOnElementAll(new ConversationSettings(device1)); // Click on Edit group option diff --git a/run/test/specs/linked_device_delete_message.spec.ts b/run/test/specs/linked_device_delete_message.spec.ts index 94c50dd..557f63d 100644 --- a/run/test/specs/linked_device_delete_message.spec.ts +++ b/run/test/specs/linked_device_delete_message.spec.ts @@ -2,6 +2,7 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../types/sessionIt'; import { DeleteMessageConfirmationModal } from './locators'; import { DeletedMessage } from './locators/conversation'; +import { ConversationItem } from './locators/home'; import { open_Alice2_Bob1_friends } from './state_builder'; import { SupportedPlatformsType, closeApp } from './utils/open_app'; @@ -22,10 +23,7 @@ async function deletedMessageLinkedDevice(platform: SupportedPlatformsType) { const sentMessage = await alice1.sendMessage(testMessage); // Check message came through on linked device(3) // Enter conversation with user B on device 3 - await alice2.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Conversation list item', - }); + await alice2.waitForTextElementToBePresent(new ConversationItem(alice2, bob.userName)); await alice2.selectByText('Conversation list item', bob.userName); // Find message await alice2.findMessageWithBody(sentMessage); diff --git a/run/test/specs/linked_device_hide_note_to_self.spec.ts b/run/test/specs/linked_device_hide_note_to_self.spec.ts index b8035bd..6da2cc1 100644 --- a/run/test/specs/linked_device_hide_note_to_self.spec.ts +++ b/run/test/specs/linked_device_hide_note_to_self.spec.ts @@ -2,7 +2,7 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsItSeparate } from '../../types/sessionIt'; import { EmptyConversation, Hide } from './locators/conversation'; import { CancelSearchButton, NoteToSelfOption } from './locators/global_search'; -import { SearchButton } from './locators/home'; +import { ConversationItem, SearchButton } from './locators/home'; import { open_Alice2 } from './state_builder'; import { SupportedPlatformsType } from './utils/open_app'; @@ -34,11 +34,7 @@ async function hideNoteToSelf(platform: SupportedPlatformsType) { await alice1.sendMessage('Creating note to self'); await alice1.navigateBack(); // Does note to self appear on linked device - await alice2.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: noteToSelf, - }); + await alice2.waitForTextElementToBePresent(new ConversationItem(alice2, noteToSelf)); await alice1.clickOnElementAll(new CancelSearchButton(alice1)); await alice1.onIOS().swipeLeft('Conversation list item', noteToSelf); await alice1.onAndroid().longPressConversation(noteToSelf); @@ -51,9 +47,7 @@ async function hideNoteToSelf(platform: SupportedPlatformsType) { await Promise.all( [alice1, alice2].map(device => device.doesElementExist({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: noteToSelf, + ...new ConversationItem(alice2, noteToSelf).build(), maxWait: 5000, }) ) diff --git a/run/test/specs/linked_device_restore_group.spec.ts b/run/test/specs/linked_device_restore_group.spec.ts index 9848296..1e43d04 100644 --- a/run/test/specs/linked_device_restore_group.spec.ts +++ b/run/test/specs/linked_device_restore_group.spec.ts @@ -1,5 +1,6 @@ import { bothPlatformsIt } from '../../types/sessionIt'; import { USERNAME } from '../../types/testing'; +import { ConversationItem } from './locators/home'; import { newUser } from './utils/create_account'; import { createGroup } from './utils/create_group'; import { closeApp, openAppFourDevices, SupportedPlatformsType } from './utils/open_app'; @@ -26,11 +27,7 @@ async function restoreGroup(platform: SupportedPlatformsType) { const charlieMessage = `${USERNAME.CHARLIE} to ${testGroupName}`; await restoreAccount(device4, alice); // Check that group has loaded on linked device - await device4.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: testGroupName, - }); + await device4.clickOnElementAll(new ConversationItem(device4, testGroupName)); // Check the group name has loaded await device4.waitForTextElementToBePresent({ strategy: 'accessibility id', @@ -57,22 +54,14 @@ async function restoreGroup(platform: SupportedPlatformsType) { ]); const testMessage2 = 'Checking that message input is working'; await device4.sendMessage(testMessage2); - await Promise.all([ - device1.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Message body', - text: testMessage2, - }), - device2.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Message body', - text: testMessage2, - }), - device3.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Message body', - text: testMessage2, - }), - ]); + await Promise.all( + [device1, device2, device3].map(device => + device.waitForTextElementToBePresent({ + strategy: 'accessibility id', + selector: 'Message body', + text: testMessage2, + }) + ) + ); await closeApp(device1, device2, device3, device4); } diff --git a/run/test/specs/linked_device_unsend_message.spec.ts b/run/test/specs/linked_device_unsend_message.spec.ts index 037bd22..9e6d281 100644 --- a/run/test/specs/linked_device_unsend_message.spec.ts +++ b/run/test/specs/linked_device_unsend_message.spec.ts @@ -2,6 +2,7 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../types/sessionIt'; import { DeleteMessageConfirmationModal, DeleteMessageForEveryone } from './locators'; import { DeletedMessage } from './locators/conversation'; +import { ConversationItem } from './locators/home'; import { open_Alice2_Bob1_friends } from './state_builder'; import { SupportedPlatformsType, closeApp } from './utils/open_app'; @@ -22,15 +23,8 @@ async function unSendMessageLinkedDevice(platform: SupportedPlatformsType) { const sentMessage = await alice1.sendMessage('Howdy'); // Check message came through on linked device(3) // Enter conversation with user B on device 3 - await alice2.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Conversation list item', - }); - await alice2.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: bob.userName, - }); + await alice2.waitForTextElementToBePresent(new ConversationItem(alice2)); + await alice2.clickOnElementAll(new ConversationItem(alice2, bob.userName)); // Find message await alice2.findMessageWithBody(sentMessage); // Select message on device 1, long press diff --git a/run/test/specs/locators/conversation.ts b/run/test/specs/locators/conversation.ts index 0ef8516..28eba00 100644 --- a/run/test/specs/locators/conversation.ts +++ b/run/test/specs/locators/conversation.ts @@ -11,10 +11,18 @@ export class MessageInput extends LocatorsInterface { export class ConversationSettings extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'More options', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'conversation-options-avatar', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'More options', + } as const; + } } } @@ -93,3 +101,63 @@ export class OutgoingMessageStatusSent extends LocatorsInterface { } as const; } } + +export class CallButton extends LocatorsInterface { + public build() { + switch (this.platform) { + case 'android': + return { + strategy: 'accessibility id', + selector: 'Call button', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Call', + } as const; + } + } +} + +export class ConversationHeaderName extends LocatorsInterface { + public build(text?: string) { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Conversation header name', + text, + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Conversation header name', + text, + } as const; + } + } +} + +export class NotificationSettings extends LocatorsInterface { + public build() { + return { + strategy: 'accessibility id', + selector: 'Notifications', + } as const; + } +} + +export class NotificationSwitch extends LocatorsInterface { + public build() { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'com.android.settings:id/switch_text', + text: 'All Session notifications', + } as const; + case 'ios': + throw new Error('Platform not supported'); + } + } +} diff --git a/run/test/specs/locators/disappearing_messages.ts b/run/test/specs/locators/disappearing_messages.ts index 9c27504..48d0377 100644 --- a/run/test/specs/locators/disappearing_messages.ts +++ b/run/test/specs/locators/disappearing_messages.ts @@ -1,7 +1,10 @@ import { LocatorsInterface } from '.'; -import { StrategyExtractionObj } from '../../../types/testing'; -import { DISAPPEARING_TIMES } from '../../../types/testing'; import { DeviceWrapper } from '../../../types/DeviceWrapper'; +import { + DISAPPEARING_TIMES, + DisappearingOptions, + StrategyExtractionObj, +} from '../../../types/testing'; export class DisappearingMessagesMenuOption extends LocatorsInterface { public build(): StrategyExtractionObj { @@ -9,8 +12,7 @@ export class DisappearingMessagesMenuOption extends LocatorsInterface { case 'android': return { strategy: 'id', - selector: `network.loki.messenger:id/title`, - text: 'Disappearing messages', + selector: 'disappearing-messages-menu-option', }; case 'ios': return { @@ -25,6 +27,10 @@ export class DisappearingMessagesSubtitle extends LocatorsInterface { public build(): StrategyExtractionObj { switch (this.platform) { case 'android': + return { + strategy: 'id', + selector: 'Disappearing messages type and time', + }; case 'ios': return { strategy: 'accessibility id', @@ -39,7 +45,7 @@ export class DisableDisappearingMessages extends LocatorsInterface { switch (this.platform) { case 'android': return { - strategy: 'accessibility id', + strategy: 'id', selector: `Disable disappearing messages`, }; case 'ios': @@ -52,10 +58,18 @@ export class DisableDisappearingMessages extends LocatorsInterface { } export class SetDisappearMessagesButton extends LocatorsInterface { public build(): StrategyExtractionObj { - return { - strategy: 'accessibility id', - selector: 'Set button', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Set button', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Set button', + } as const; + } } } @@ -93,9 +107,41 @@ export class DisappearingMessageRadial extends LocatorsInterface { this.timer = timer; } public build(): StrategyExtractionObj { - return { - strategy: 'accessibility id', - selector: `${this.timer} - Radio`, - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: this.timer, + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: `${this.timer} - Radio`, + } as const; + } + } +} + +export class DisappearingMessagesTimerType extends LocatorsInterface { + private timerType: DisappearingOptions; + + constructor(device: DeviceWrapper, timerType: DisappearingOptions) { + super(device); + this.timerType = timerType; + } + + public build(): StrategyExtractionObj { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: this.timerType, + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: this.timerType, + } as const; + } } } diff --git a/run/test/specs/locators/index.ts b/run/test/specs/locators/index.ts index a2f7aef..8ba958d 100644 --- a/run/test/specs/locators/index.ts +++ b/run/test/specs/locators/index.ts @@ -96,21 +96,6 @@ export class EditGroupName extends LocatorsInterface { } } -export class PrivacyButton extends LocatorsInterface { - public build() { - switch (this.platform) { - case 'android': - return { - strategy: 'class name', - selector: 'android.widget.TextView', - text: 'Privacy', - } as const; - case 'ios': - return { strategy: 'id', selector: 'Privacy' } as const; - } - } -} - export class ReadReceiptsButton extends LocatorsInterface { public build() { switch (this.platform) { @@ -224,8 +209,7 @@ export class BlockUser extends LocatorsInterface { case 'android': return { strategy: 'id', - selector: 'network.loki.messenger:id/title', - text: 'Block', + selector: 'block-user-confirm-button', }; } } @@ -470,23 +454,6 @@ export class DeleteMesssageRequestConfirmation extends LocatorsInterface { } } -export class RevealRecoveryPhraseButton extends LocatorsInterface { - public build(): StrategyExtractionObj { - switch (this.platform) { - case 'android': - return { - strategy: 'accessibility id', - selector: 'Reveal recovery phrase button', - }; - case 'ios': - return { - strategy: 'accessibility id', - selector: 'Continue', - }; - } - } -} - export class DownloadMediaButton extends LocatorsInterface { public build(): StrategyExtractionObj { switch (this.platform) { diff --git a/run/test/specs/locators/onboarding.ts b/run/test/specs/locators/onboarding.ts index 95acfad..a9ad3e2 100644 --- a/run/test/specs/locators/onboarding.ts +++ b/run/test/specs/locators/onboarding.ts @@ -3,21 +3,20 @@ import { LocatorsInterface } from './index'; // SHARED LOCATORS -export class ContinueButton extends LocatorsInterface { - public build() { - return { - strategy: 'accessibility id', - selector: 'Continue', - } as const; - } -} - export class ErrorMessage extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'Error message', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'error-message', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Error message', + } as const; + } } } @@ -50,31 +49,54 @@ export class WarningModalQuitButton extends LocatorsInterface { // SPLASH SCREEN export class CreateAccountButton extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'Create account button', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Create account button', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Create account button', + } as const; + } } } export class AccountRestoreButton extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'Restore your session button', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Restore your session button', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Restore your session button', + } as const; + } } } export class SplashScreenLinks extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'Open URL', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Open URL', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Open URL', + } as const; + } } } - export class TermsOfServiceButton extends LocatorsInterface { public build() { switch (this.platform) { @@ -151,9 +173,34 @@ export class SeedPhraseInput extends LocatorsInterface { export class SlowModeRadio extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'Slow mode notifications button', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Slow mode notifications button', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Slow mode notifications button', + } as const; + } + } +} + +export class LoadingAnimation extends LocatorsInterface { + public build() { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Loading animation', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Loading animation', + } as const; + } } } diff --git a/run/test/specs/locators/settings.ts b/run/test/specs/locators/settings.ts index 09e520d..3cd7829 100644 --- a/run/test/specs/locators/settings.ts +++ b/run/test/specs/locators/settings.ts @@ -3,10 +3,18 @@ import { LocatorsInterface } from './index'; export class HideRecoveryPasswordButton extends LocatorsInterface { public build(): StrategyExtractionObj { - return { - strategy: 'accessibility id', - selector: 'Hide recovery password button', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Hide recovery password button', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Hide recovery password button', + } as const; + } } } @@ -53,6 +61,40 @@ export class RecoveryPasswordMenuItem extends LocatorsInterface { } } +export class RevealRecoveryPhraseButton extends LocatorsInterface { + public build(): StrategyExtractionObj { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Reveal recovery phrase button', + }; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Continue', + }; + } + } +} + +export class RecoveryPhraseContainer extends LocatorsInterface { + public build(): StrategyExtractionObj { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Recovery password container', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Recovery password container', + } as const; + } + } +} + export class SaveProfilePictureButton extends LocatorsInterface { public build(): StrategyExtractionObj { switch (this.platform) { @@ -104,6 +146,36 @@ export class BlockedContacts extends LocatorsInterface { } } } +export class PrivacyMenuItem extends LocatorsInterface { + public build() { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Privacy', + } as const; + case 'ios': + return { strategy: 'id', selector: 'Privacy' } as const; + } + } +} + +export class ConversationsMenuItem extends LocatorsInterface { + public build() { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Conversations', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Conversations', + } as const; + } + } +} export class AppearanceMenuItem extends LocatorsInterface { public build() { diff --git a/run/test/specs/locators/start_conversation.ts b/run/test/specs/locators/start_conversation.ts index c9a5feb..2c7b911 100644 --- a/run/test/specs/locators/start_conversation.ts +++ b/run/test/specs/locators/start_conversation.ts @@ -3,19 +3,35 @@ import { LocatorsInterface } from './index'; export class NewMessageOption extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'New direct message', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'New direct message', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'New direct message', + } as const; + } } } export class CreateGroupOption extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'Create group', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Create group', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Create group', + } as const; + } } } @@ -24,7 +40,7 @@ export class JoinCommunityOption extends LocatorsInterface { switch (this.platform) { case 'android': return { - strategy: 'accessibility id', + strategy: 'id', selector: 'Join community button', }; case 'ios': @@ -38,10 +54,18 @@ export class JoinCommunityOption extends LocatorsInterface { export class InviteAFriendOption extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'Invite friend button', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Invite friend button', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Invite friend button', + } as const; + } } } @@ -61,6 +85,40 @@ export class CloseButton extends LocatorsInterface { } } } + +export class CopyButton extends LocatorsInterface { + public build() { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Copy button', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Copy button', + } as const; + } + } +} + +export class NextButton extends LocatorsInterface { + public build(): StrategyExtractionObj { + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Next', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Next', + } as const; + } + } +} // NEW MESSAGE SECTION export class EnterAccountID extends LocatorsInterface { public build(): StrategyExtractionObj { @@ -82,27 +140,34 @@ export class EnterAccountID extends LocatorsInterface { // INVITE A FRIEND SECTION export class AccountIDField extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'Account ID', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Account ID', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Account ID', + } as const; + } } } export class ShareButton extends LocatorsInterface { public build() { - return { - strategy: 'accessibility id', - selector: 'Share button', - } as const; - } -} - -export class CopyButton extends LocatorsInterface { - public build() { - return { - strategy: 'accessibility id', - selector: 'Copy button', - } as const; + switch (this.platform) { + case 'android': + return { + strategy: 'id', + selector: 'Share button', + } as const; + case 'ios': + return { + strategy: 'accessibility id', + selector: 'Share button', + } as const; + } } } diff --git a/run/test/specs/message_community_invitation.spec.ts b/run/test/specs/message_community_invitation.spec.ts index fd86b9f..b0c18e1 100644 --- a/run/test/specs/message_community_invitation.spec.ts +++ b/run/test/specs/message_community_invitation.spec.ts @@ -7,6 +7,7 @@ import { testCommunityLink, testCommunityName } from './../../constants/communit import { ConversationSettings } from './locators/conversation'; import { open_Alice1_Bob1_friends } from './state_builder'; import { englishStrippedStr } from '../../localizer/englishStrippedStr'; +import { ConversationItem } from './locators/home'; bothPlatformsItSeparate({ title: 'Send community invitation', @@ -62,11 +63,7 @@ async function sendCommunityInvitationIos(platform: SupportedPlatformsType) { ); await bob1.clickOnElementAll({ strategy: 'accessibility id', selector: 'Join' }); await bob1.navigateBack(); - await bob1.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: testCommunityName, - }); + await bob1.waitForTextElementToBePresent(new ConversationItem(bob1, testCommunityName)); await closeApp(alice1, bob1); } @@ -117,10 +114,6 @@ async function sendCommunityInviteMessageAndroid(platform: SupportedPlatformsTyp ); await bob1.clickOnElementAll({ strategy: 'accessibility id', selector: 'Join' }); await bob1.navigateBack(); - await bob1.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: testCommunityName, - }); + await bob1.waitForTextElementToBePresent(new ConversationItem(bob1, testCommunityName)); await closeApp(alice1, bob1); } diff --git a/run/test/specs/message_requests_accept_text_reply.spec.ts b/run/test/specs/message_requests_accept_text_reply.spec.ts index 8d5ea2f..da4a0c6 100644 --- a/run/test/specs/message_requests_accept_text_reply.spec.ts +++ b/run/test/specs/message_requests_accept_text_reply.spec.ts @@ -2,7 +2,8 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../types/sessionIt'; import { USERNAME } from '../../types/testing'; import { MessageInput } from './locators/conversation'; -import { EnterAccountID } from './locators/start_conversation'; +import { PlusButton } from './locators/home'; +import { EnterAccountID, NewMessageOption, NextButton } from './locators/start_conversation'; import { newUser } from './utils/create_account'; import { SupportedPlatformsType, closeApp, openAppTwoDevices } from './utils/open_app'; @@ -23,14 +24,14 @@ async function acceptRequestWithText(platform: SupportedPlatformsType) { ]); const testMessage = `${alice.userName} to ${bob.userName}`; // Send message from Alice to Bob - await device1.clickOnByAccessibilityID('New conversation button'); + await device1.clickOnElementAll(new PlusButton(device1)); // Select direct message option - await device1.clickOnByAccessibilityID('New direct message'); + await device1.clickOnElementAll(new NewMessageOption(device1)); // Enter User B's session ID into input box await device1.inputText(bob.accountID, new EnterAccountID(device1)); // Click next await device1.scrollDown(); - await device1.clickOnByAccessibilityID('Next'); + await device1.clickOnElementAll(new NextButton(device1)); //messageRequestPendingDescription: "You will be able to send voice messages and attachments once the recipient has approved this message request." const messageRequestPendingDescription = englishStrippedStr( 'messageRequestPendingDescription' diff --git a/run/test/specs/message_requests_block.spec.ts b/run/test/specs/message_requests_block.spec.ts index fab57d8..322f11a 100644 --- a/run/test/specs/message_requests_block.spec.ts +++ b/run/test/specs/message_requests_block.spec.ts @@ -2,7 +2,8 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../types/sessionIt'; import { USERNAME, type AccessibilityId } from '../../types/testing'; import { BlockedContactsSettings, BlockUserConfirmationModal } from './locators'; -import { UserSettings } from './locators/settings'; +import { PlusButton } from './locators/home'; +import { ConversationsMenuItem, UserSettings } from './locators/settings'; import { sleepFor } from './utils'; import { newUser } from './utils/create_account'; import { linkedDevice } from './utils/link_device'; @@ -63,10 +64,7 @@ async function blockedRequest(platform: SupportedPlatformsType) { const blockedMessage = `"${alice.userName} to ${bob.userName} - shouldn't get through"`; await device1.sendMessage(blockedMessage); await device2.navigateBack(); - await device2.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'New conversation button', - }); + await device2.waitForTextElementToBePresent(new PlusButton(device2)); // Need to wait to see if message gets through await sleepFor(5000); await device2.hasTextElementBeenDeleted('Message body', blockedMessage); @@ -79,8 +77,8 @@ async function blockedRequest(platform: SupportedPlatformsType) { // 'Conversations' might be hidden beyond the Settings view, gotta scroll down to find it await Promise.all([device2.scrollDown(), device3.scrollDown()]); await Promise.all([ - device2.clickOnElementAll({ strategy: 'accessibility id', selector: 'Conversations' }), - device3.clickOnElementAll({ strategy: 'accessibility id', selector: 'Conversations' }), + device2.clickOnElementAll(new ConversationsMenuItem(device2)), + device3.clickOnElementAll(new ConversationsMenuItem(device3)), ]); await Promise.all([ device2.clickOnElementAll(new BlockedContactsSettings(device2)), diff --git a/run/test/specs/message_requests_decline.spec.ts b/run/test/specs/message_requests_decline.spec.ts index de4cf1e..1e1eabc 100644 --- a/run/test/specs/message_requests_decline.spec.ts +++ b/run/test/specs/message_requests_decline.spec.ts @@ -2,6 +2,7 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsIt } from '../../types/sessionIt'; import { USERNAME, type AccessibilityId } from '../../types/testing'; import { DeclineMessageRequestButton, DeleteMesssageRequestConfirmation } from './locators'; +import { PlusButton } from './locators/home'; import { sleepFor } from './utils'; import { newUser } from './utils/create_account'; import { linkedDevice } from './utils/link_device'; @@ -59,10 +60,7 @@ async function declineRequest(platform: SupportedPlatformsType) { await sleepFor(100); await device2.navigateBack(); // Look for new conversation button to make sure it all worked - await device2.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'New conversation button', - }); + await device2.waitForTextElementToBePresent(new PlusButton(device2)); // Close app await closeApp(device1, device2, device3); } diff --git a/run/test/specs/user_actions_block_conversation_list.spec.ts b/run/test/specs/user_actions_block_conversation_list.spec.ts index fde86a5..5d77fb3 100644 --- a/run/test/specs/user_actions_block_conversation_list.spec.ts +++ b/run/test/specs/user_actions_block_conversation_list.spec.ts @@ -3,7 +3,7 @@ import { androidIt } from '../../types/sessionIt'; import { USERNAME } from '../../types/testing'; import { BlockedContactsSettings, BlockUserConfirmationModal } from './locators'; import { LongPressBlockOption } from './locators/home'; -import { UserSettings } from './locators/settings'; +import { ConversationsMenuItem, UserSettings } from './locators/settings'; import { open_Alice1_Bob1_friends } from './state_builder'; import { SupportedPlatformsType, closeApp } from './utils/open_app'; @@ -46,7 +46,7 @@ async function blockUserInConversationList(platform: SupportedPlatformsType) { await alice1.clickOnElementAll(new UserSettings(alice1)); // 'Conversations' might be hidden beyond the Settings view, gotta scroll down to find it await alice1.scrollDown(); - await alice1.clickOnElementAll({ strategy: 'accessibility id', selector: 'Conversations' }); + await alice1.clickOnElementAll(new ConversationsMenuItem(alice1)); await alice1.clickOnElementAll(new BlockedContactsSettings(alice1)); await alice1.waitForTextElementToBePresent({ strategy: 'accessibility id', diff --git a/run/test/specs/user_actions_block_conversation_options.spec.ts b/run/test/specs/user_actions_block_conversation_options.spec.ts index 2e61101..688e792 100644 --- a/run/test/specs/user_actions_block_conversation_options.spec.ts +++ b/run/test/specs/user_actions_block_conversation_options.spec.ts @@ -7,7 +7,7 @@ import { ExitUserProfile, } from './locators'; import { ConversationSettings } from './locators/conversation'; -import { UserSettings } from './locators/settings'; +import { ConversationsMenuItem, UserSettings } from './locators/settings'; import { open_Alice1_Bob1_friends } from './state_builder'; import { sleepFor } from './utils'; import { closeApp, SupportedPlatformsType } from './utils/open_app'; @@ -60,7 +60,7 @@ async function blockUserInConversationOptions(platform: SupportedPlatformsType) await alice1.clickOnElementAll(new UserSettings(alice1)); // 'Conversations' might be hidden beyond the Settings view, gotta scroll down to find it await alice1.scrollDown(); - await alice1.clickOnElementAll({ strategy: 'accessibility id', selector: 'Conversations' }); + await alice1.clickOnElementAll(new ConversationsMenuItem(alice1)); await alice1.clickOnElementAll(new BlockedContactsSettings(alice1)); // Accessibility ID for Blocked Contact not present on iOS await alice1.waitForTextElementToBePresent({ diff --git a/run/test/specs/user_actions_hide_recovery_password.spec.ts b/run/test/specs/user_actions_hide_recovery_password.spec.ts index 389ff86..fc5731c 100644 --- a/run/test/specs/user_actions_hide_recovery_password.spec.ts +++ b/run/test/specs/user_actions_hide_recovery_password.spec.ts @@ -23,10 +23,7 @@ async function hideRecoveryPassword(platform: SupportedPlatformsType) { await linkedDevice(device1, device2, USERNAME.ALICE); await device1.clickOnElementAll(new UserSettings(device1)); await device1.scrollDown(); - await device1.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Recovery password menu item', - }); + await device1.clickOnElementAll(new RecoveryPasswordMenuItem(device1)); await device1.clickOnElementAll(new HideRecoveryPasswordButton(device1)); // Wait for modal to appear // Check modal is correct diff --git a/run/test/specs/user_actions_set_nickname.spec.ts b/run/test/specs/user_actions_set_nickname.spec.ts index ef6e293..a0d899a 100644 --- a/run/test/specs/user_actions_set_nickname.spec.ts +++ b/run/test/specs/user_actions_set_nickname.spec.ts @@ -2,7 +2,7 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsItSeparate } from '../../types/sessionIt'; import { USERNAME } from '../../types/testing'; import { UsernameInput } from './locators'; -import { ConversationSettings } from './locators/conversation'; +import { ConversationHeaderName, ConversationSettings } from './locators/conversation'; import { SaveNameChangeButton } from './locators/settings'; import { open_Alice1_Bob1_friends } from './state_builder'; import { sleepFor } from './utils'; @@ -71,7 +71,7 @@ async function setNicknameAndroid(platform: SupportedPlatformsType) { }); const nickName = 'New nickname'; // Go back to conversation list - await alice1.navigateBack(); + await alice1.navigateBack(true); // Select conversation in list with Bob await alice1.longPressConversation(bob.userName); // Select 'Details' option @@ -85,13 +85,13 @@ async function setNicknameAndroid(platform: SupportedPlatformsType) { // CLick out of pop up await alice1.clickOnByAccessibilityID('Message user'); // Check name at top of conversation is nickname - await alice1.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Conversation header name', - }); + await alice1.waitForTextElementToBePresent(new ConversationHeaderName(alice1)); // Send a message so nickname is updated in conversation list await alice1.sendMessage('Message to test nickname change'); - const actualNickname = await alice1.grabTextFromAccessibilityId('Conversation header name'); + const conversationHeader = await alice1.waitForTextElementToBePresent( + new ConversationHeaderName(alice1) + ); + const actualNickname = await alice1.getTextFromElement(conversationHeader); if (actualNickname !== nickName) { throw new Error('Nickname has not been changed in header'); } diff --git a/run/test/specs/utils/create_account.ts b/run/test/specs/utils/create_account.ts index 1681cc1..8af0f09 100644 --- a/run/test/specs/utils/create_account.ts +++ b/run/test/specs/utils/create_account.ts @@ -2,26 +2,24 @@ import type { UserNameType } from '@session-foundation/qa-seeder'; import { sleepFor } from '.'; import { DeviceWrapper } from '../../../types/DeviceWrapper'; import { User } from '../../../types/testing'; -import { RevealRecoveryPhraseButton } from '../locators'; -import { DisplayNameInput } from '../locators/onboarding'; +import { RecoveryPhraseContainer, RevealRecoveryPhraseButton } from '../locators/settings'; +import { CreateAccountButton, DisplayNameInput, SlowModeRadio } from '../locators/onboarding'; import { UserSettings } from '../locators/settings'; +import { ContinueButton } from '../locators/global'; +import { CopyButton } from '../locators/start_conversation'; export const newUser = async (device: DeviceWrapper, userName: UserNameType): Promise => { // Click create session ID - - await device.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Create account button', - }); + await device.clickOnElementAll(new CreateAccountButton(device)); // Input username await device.inputText(userName, new DisplayNameInput(device)); // Click continue - await device.clickOnByAccessibilityID('Continue'); + await device.clickOnElementAll(new ContinueButton(device)); // Choose message notification options // Want to choose 'Slow Mode' so notifications don't interrupt test - await device.clickOnByAccessibilityID('Slow mode notifications button'); + await device.clickOnElementAll(new SlowModeRadio(device)); // Select Continue to save notification settings - await device.clickOnByAccessibilityID('Continue'); + await device.clickOnElementAll(new ContinueButton(device)); // TODO need to retry check every 1s for 5s console.warn('about to look for Allow permission in 5s'); await sleepFor(5000); @@ -30,16 +28,15 @@ export const newUser = async (device: DeviceWrapper, userName: UserNameType): Pr console.warn('looked for Allow permission'); await sleepFor(1000); // Click on 'continue' button to open recovery phrase modal - await device.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Reveal recovery phrase button', - }); + await device.waitForTextElementToBePresent(new RevealRecoveryPhraseButton(device)); await device.clickOnElementAll(new RevealRecoveryPhraseButton(device)); //Save recovery password - await device.clickOnByAccessibilityID('Recovery password container'); - await device.onAndroid().clickOnByAccessibilityID('Copy button'); + const recoveryPhraseContainer = await device.clickOnElementAll( + new RecoveryPhraseContainer(device) + ); + await device.onAndroid().clickOnElementAll(new CopyButton(device)); // Save recovery phrase as variable - const recoveryPhrase = await device.grabTextFromAccessibilityId('Recovery password container'); + const recoveryPhrase = await device.getTextFromElement(recoveryPhraseContainer); console.log(`${userName}s recovery phrase is "${recoveryPhrase}"`); // Exit Modal await device.navigateBack(); diff --git a/run/test/specs/utils/create_group.ts b/run/test/specs/utils/create_group.ts index b32bbbd..9a2c134 100644 --- a/run/test/specs/utils/create_group.ts +++ b/run/test/specs/utils/create_group.ts @@ -3,6 +3,8 @@ import { DeviceWrapper } from '../../../types/DeviceWrapper'; import { Group, GROUPNAME, User } from '../../../types/testing'; import { Contact } from '../locators/global'; import { CreateGroupButton, GroupNameInput } from '../locators/groups'; +import { ConversationItem, PlusButton } from '../locators/home'; +import { CreateGroupOption } from '../locators/start_conversation'; import { newContact } from './create_contact'; import { sortByPubkey } from './get_account_id'; import { SupportedPlatformsType } from './open_app'; @@ -25,18 +27,18 @@ export const createGroup = async ( const charlieMessage = `${userThree.userName} to ${userName}`; // Create contact between User A and User B await newContact(platform, device1, userOne, device2, userTwo); - await device1.navigateBack(); + await device1.navigateBack(true); await newContact(platform, device1, userOne, device3, userThree); - await device2.navigateBack(); + await device2.navigateBack(true); // Create contact between User A and User C // Exit conversation back to list - await device1.navigateBack(); + await device1.navigateBack(true); // Exit conversation back to list - await device3.navigateBack(); + await device3.navigateBack(true); // Click plus button - await device1.clickOnByAccessibilityID('New conversation button'); + await device1.clickOnElementAll(new PlusButton(device1)); // Select Closed Group option - await device1.clickOnByAccessibilityID('Create group'); + await device1.clickOnElementAll(new CreateGroupOption(device1)); // Type in group name await device1.inputText(userName, new GroupNameInput(device1)); // Select User B and User C @@ -45,17 +47,10 @@ export const createGroup = async ( // Select tick await device1.clickOnElementAll(new CreateGroupButton(device1)); // Enter group chat on device 2 and 3 + await Promise.all([device2.onAndroid().navigateBack(), device3.onAndroid().navigateBack()]); await Promise.all([ - device2.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: group.userName, - }), - device3.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Conversation list item', - text: group.userName, - }), + device2.clickOnElementAll(new ConversationItem(device2, group.userName)), + device3.clickOnElementAll(new ConversationItem(device3, group.userName)), ]); if (checkControlMessage) { // Sort by account ID diff --git a/run/test/specs/utils/join_community.ts b/run/test/specs/utils/join_community.ts index c2f124f..55b861a 100644 --- a/run/test/specs/utils/join_community.ts +++ b/run/test/specs/utils/join_community.ts @@ -1,5 +1,6 @@ import { DeviceWrapper } from '../../../types/DeviceWrapper'; import { CommunityInput, JoinCommunityButton } from '../locators'; +import { PlusButton } from '../locators/home'; import { JoinCommunityOption } from '../locators/start_conversation'; export const joinCommunity = async ( @@ -7,7 +8,7 @@ export const joinCommunity = async ( communityLink: string, communityName: string ) => { - await device.clickOnByAccessibilityID('New conversation button'); + await device.clickOnElementAll(new PlusButton(device)); await device.clickOnElementAll(new JoinCommunityOption(device)); await device.inputText(communityLink, new CommunityInput(device)); await device.clickOnElementAll(new JoinCommunityButton(device)); diff --git a/run/test/specs/utils/link_device.ts b/run/test/specs/utils/link_device.ts index d8761da..f3dbf23 100644 --- a/run/test/specs/utils/link_device.ts +++ b/run/test/specs/utils/link_device.ts @@ -1,8 +1,15 @@ import { sleepFor } from '.'; import { newUser } from './create_account'; -import { DisplayNameInput, SeedPhraseInput } from '../locators/onboarding'; +import { + AccountRestoreButton, + DisplayNameInput, + SeedPhraseInput, + SlowModeRadio, +} from '../locators/onboarding'; import { DeviceWrapper } from '../../../types/DeviceWrapper'; import type { UserNameType } from '@session-foundation/qa-seeder'; +import { ContinueButton } from '../locators/global'; +import { PlusButton } from '../locators/home'; export const linkedDevice = async ( device1: DeviceWrapper, @@ -12,18 +19,17 @@ export const linkedDevice = async ( const user = await newUser(device1, userName); // Log in with recovery seed on device 2 - await device2.clickOnByAccessibilityID('Restore your session button'); + await device2.clickOnElementAll(new AccountRestoreButton(device2)); // Enter recovery phrase into input box await device2.inputText(user.recoveryPhrase, new SeedPhraseInput(device2)); - // Wait for continue button to become active await sleepFor(500); // Continue with recovery phrase - await device2.clickOnByAccessibilityID('Continue'); + await device2.clickOnElementAll(new ContinueButton(device2)); // Wait for any notifications to disappear - await device2.clickOnByAccessibilityID('Slow mode notifications button'); + await device2.clickOnElementAll(new SlowModeRadio(device2)); // Click continue on message notification settings - await device2.clickOnByAccessibilityID('Continue'); + await device2.clickOnElementAll(new ContinueButton(device2)); // Wait for loading animation to look for display name await device2.waitForLoadingOnboarding(); const displayName = await device2.doesElementExist({ @@ -32,7 +38,7 @@ export const linkedDevice = async ( }); if (displayName) { await device2.inputText(userName, new DisplayNameInput(device2)); - await device2.clickOnByAccessibilityID('Continue'); + await device2.clickOnElementAll(new ContinueButton(device2)); } else { console.info('Display name found: Loading account'); } @@ -40,10 +46,7 @@ export const linkedDevice = async ( await sleepFor(500); await device2.checkPermissions('Allow'); // Check that button was clicked - await device2.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'New conversation button', - }); + await device2.waitForTextElementToBePresent(new PlusButton(device2)); console.info('Device 2 linked'); diff --git a/run/test/specs/utils/restore_account.ts b/run/test/specs/utils/restore_account.ts index f7f3596..f43b2d3 100644 --- a/run/test/specs/utils/restore_account.ts +++ b/run/test/specs/utils/restore_account.ts @@ -1,7 +1,9 @@ import { sleepFor } from '.'; import { DeviceWrapper } from '../../../types/DeviceWrapper'; import { User } from '../../../types/testing'; -import { SeedPhraseInput } from '../locators/onboarding'; +import { AccountRestoreButton, SeedPhraseInput, SlowModeRadio } from '../locators/onboarding'; +import { ContinueButton } from '../../specs/locators/global'; +import { PlusButton } from '../locators/home'; export const restoreAccount = async (device: DeviceWrapper, user: User) => { await device.clickOnElementAll({ @@ -12,11 +14,11 @@ export const restoreAccount = async (device: DeviceWrapper, user: User) => { // Wait for continue button to become active await sleepFor(500); // Continue with recovery phrase - await device.clickOnByAccessibilityID('Continue'); + await device.clickOnElementAll(new ContinueButton(device)); // Wait for any notifications to disappear - await device.clickOnByAccessibilityID('Slow mode notifications button'); + await device.clickOnElementAll(new SlowModeRadio(device)); // Click continue on message notification settings - await device.clickOnByAccessibilityID('Continue'); + await device.clickOnElementAll(new ContinueButton(device)); // Wait for loading animation to look for display name await device.waitForLoadingOnboarding(); const displayName = await device.doesElementExist({ @@ -29,7 +31,7 @@ export const restoreAccount = async (device: DeviceWrapper, user: User) => { strategy: 'accessibility id', selector: 'Enter display name', }); - await device.clickOnByAccessibilityID('Continue'); + await device.clickOnElementAll(new ContinueButton(device)); } else { console.info('Display name found: Loading account'); } @@ -38,15 +40,11 @@ export const restoreAccount = async (device: DeviceWrapper, user: User) => { await device.checkPermissions('Allow'); await sleepFor(1000); await device.hasElementBeenDeleted({ - strategy: 'accessibility id', - selector: 'Continue', + ...new ContinueButton(device).build(), maxWait: 1000, }); // Check that button was clicked - await device.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'New conversation button', - }); + await device.waitForTextElementToBePresent(new PlusButton(device)); }; /** @@ -54,19 +52,16 @@ export const restoreAccount = async (device: DeviceWrapper, user: User) => { * If the account isn't found on the network, fail the test. */ export const restoreAccountNoFallback = async (device: DeviceWrapper, recoveryPhrase: string) => { - await device.clickOnElementAll({ - strategy: 'accessibility id', - selector: 'Restore your session button', - }); + await device.clickOnElementAll(new AccountRestoreButton(device)); await device.inputText(recoveryPhrase, new SeedPhraseInput(device)); // Wait for continue button to become active await sleepFor(500); // Continue with recovery phrase - await device.clickOnByAccessibilityID('Continue'); + await device.clickOnElementAll(new ContinueButton(device)); // Wait for any notifications to disappear - await device.clickOnByAccessibilityID('Slow mode notifications button'); + await device.clickOnElementAll(new SlowModeRadio(device)); // Click continue on message notification settings - await device.clickOnByAccessibilityID('Continue'); + await device.clickOnElementAll(new ContinueButton(device)); // Wait for loading animation to look for display name await device.waitForLoadingOnboarding(); const displayName = await device.doesElementExist({ @@ -84,13 +79,9 @@ export const restoreAccountNoFallback = async (device: DeviceWrapper, recoveryPh await device.checkPermissions('Allow'); await sleepFor(1000); await device.hasElementBeenDeleted({ - strategy: 'accessibility id', - selector: 'Continue', + ...new ContinueButton(device).build(), maxWait: 1000, }); // Check that button was clicked - await device.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'New conversation button', - }); + await device.waitForTextElementToBePresent(new PlusButton(device)); }; diff --git a/run/test/specs/utils/set_disappearing_messages.ts b/run/test/specs/utils/set_disappearing_messages.ts index 6cd2e83..89f3cb9 100644 --- a/run/test/specs/utils/set_disappearing_messages.ts +++ b/run/test/specs/utils/set_disappearing_messages.ts @@ -2,7 +2,10 @@ import { DeviceWrapper } from '../../../types/DeviceWrapper'; import { ConversationType, DISAPPEARING_TIMES, MergedOptions } from '../../../types/testing'; import { ConversationSettings } from '../locators/conversation'; import { + DisappearingMessageRadial, DisappearingMessagesMenuOption, + DisappearingMessagesSubtitle, + DisappearingMessagesTimerType, FollowSettingsButton, SetDisappearMessagesButton, SetModalButton, @@ -22,7 +25,7 @@ export const setDisappearingMessage = async ( await sleepFor(500); await device.clickOnElementAll(new DisappearingMessagesMenuOption(device)); if (enforcedType === '1:1') { - await device.clickOnByAccessibilityID(timerType); + await device.clickOnElementAll(new DisappearingMessagesTimerType(device, timerType)); } if (timerType === 'Disappear after read option') { if (enforcedType === '1:1') { @@ -40,12 +43,9 @@ export const setDisappearingMessage = async ( await device.disappearRadioButtonSelected(platform, DISAPPEARING_TIMES.ONE_DAY); } - await device.clickOnElementAll({ - strategy: 'accessibility id', - selector: timerDuration, - }); + await device.clickOnElementAll(new DisappearingMessageRadial(device, timerDuration)); await device.clickOnElementAll(new SetDisappearMessagesButton(device)); - await device.onIOS().navigateBack(); + await device.navigateBack(true); // Extended the wait for the Follow settings button to settle in the UI, it was moving and confusing appium await sleepFor(2000); if (device2) { @@ -53,5 +53,5 @@ export const setDisappearingMessage = async ( await sleepFor(500); await device2.clickOnElementAll(new SetModalButton(device2)); } - // await device.waitForTextElementToBePresent(new DisappearingMessagesSubtitle(device)); + await device.waitForTextElementToBePresent(new DisappearingMessagesSubtitle(device)); }; diff --git a/run/test/specs/voice_calls.spec.ts b/run/test/specs/voice_calls.spec.ts index 8e8bd9d..99bb2a9 100644 --- a/run/test/specs/voice_calls.spec.ts +++ b/run/test/specs/voice_calls.spec.ts @@ -1,6 +1,7 @@ import { englishStrippedStr } from '../../localizer/englishStrippedStr'; import { bothPlatformsItSeparate } from '../../types/sessionIt'; import { ExitUserProfile } from './locators'; +import { CallButton, NotificationSettings, NotificationSwitch } from './locators/conversation'; import { open_Alice1_bob1_notfriends } from './state_builder'; import { sleepFor } from './utils/index'; import { SupportedPlatformsType, closeApp } from './utils/open_app'; @@ -28,11 +29,7 @@ async function voiceCallIos(platform: SupportedPlatformsType) { await alice1.sendNewMessage({ accountID: bob.sessionId }, 'Testing calls'); // Look for phone icon (shouldnt be there) - await alice1.hasElementBeenDeleted({ - strategy: 'accessibility id', - selector: 'Call', - maxWait: 1000, - }); + await alice1.hasElementBeenDeleted({ ...new CallButton(alice1).build(), maxWait: 5000 }); // Create contact await bob1.clickOnByAccessibilityID('Message requests banner'); // Select message from User A @@ -47,7 +44,7 @@ async function voiceCallIos(platform: SupportedPlatformsType) { const messageRequestsAccepted = englishStrippedStr('messageRequestsAccepted').toString(); await alice1.waitForControlMessageToBePresent(messageRequestsAccepted); // Phone icon should appear now that conversation has been approved - await alice1.clickOnByAccessibilityID('Call'); + await alice1.clickOnElementAll(new CallButton(alice1)); // Enabled voice calls in privacy settings await alice1.waitForTextElementToBePresent({ strategy: 'accessibility id', @@ -72,16 +69,17 @@ async function voiceCallIos(platform: SupportedPlatformsType) { await alice1.clickOnByAccessibilityID('Continue'); // Navigate back to conversation await alice1.closeScreen(); - await alice1.clickOnByAccessibilityID('Call'); + await alice1.clickOnElementAll(new CallButton(alice1)); // Need to allow microphone access await alice1.modalPopup({ strategy: 'accessibility id', selector: 'Allow' }); // Call hasn't connected until microphone access is granted - await alice1.clickOnByAccessibilityID('Call'); - // No test tags on modal as of yet - // await bob1.checkModalStrings( - // englishStrippedStr('callsMissedCallFrom').withArgs({ name: alice.userName }).toString(), - // englishStrippedStr('callsYouMissedCallPermissions').withArgs({ name: alice.userName }).toString() - // ); + await alice1.clickOnElementAll(new CallButton(alice1)); + await bob1.checkModalStrings( + englishStrippedStr('callsMissedCallFrom').withArgs({ name: alice.userName }).toString(), + englishStrippedStr('callsYouMissedCallPermissions') + .withArgs({ name: alice.userName }) + .toString() + ); await bob1.clickOnElementAll({ strategy: 'accessibility id', selector: 'Okay' }); // Hang up on device 1 await alice1.clickOnByAccessibilityID('End call button'); @@ -91,7 +89,7 @@ async function voiceCallIos(platform: SupportedPlatformsType) { selector: 'Conversation list item', text: alice.userName, }); - await bob1.clickOnByAccessibilityID('Call'); + await bob1.clickOnElementAll(new CallButton(bob1)); await bob1.clickOnByAccessibilityID('Settings'); await bob1.scrollDown(); await bob1.modalPopup({ @@ -107,13 +105,19 @@ async function voiceCallIos(platform: SupportedPlatformsType) { englishStrippedStr('callsVoiceAndVideoModalDescription').toString() ); await bob1.clickOnByAccessibilityID('Continue'); - await bob1.clickOnElementAll(new ExitUserProfile(bob1)); + await bob1.checkModalStrings( + englishStrippedStr('sessionNotifications').toString(), + englishStrippedStr('callsNotificationsRequired').toString() + ); + await sleepFor(100); + await bob1.clickOnElementAll(new NotificationSettings(bob1)); + await bob1.clickOnElementAll({ ...new ExitUserProfile(bob1).build(), maxWait: 1000 }); // Wait for change to take effect await sleepFor(1000); // Make call on device 1 (alice) - await bob1.clickOnByAccessibilityID('Call'); + await bob1.clickOnElementAll(new CallButton(bob1)); await bob1.modalPopup({ strategy: 'accessibility id', selector: 'Allow' }); - await alice1.clickOnByAccessibilityID('Call'); + await alice1.clickOnElementAll(new CallButton(alice1)); // Wait for call to come through await sleepFor(1000); // Answer call on device 2 @@ -163,7 +167,7 @@ async function voiceCallAndroid(platform: SupportedPlatformsType) { // Verify config message states message request was accepted await alice1.waitForControlMessageToBePresent('Your message request has been accepted.'); // Phone icon should appear now that conversation has been approved - await alice1.clickOnByAccessibilityID('Call'); + await alice1.clickOnElementAll(new CallButton(alice1)); // Enabled voice calls in privacy settings await alice1.clickOnElementAll({ strategy: 'accessibility id', @@ -190,10 +194,17 @@ async function voiceCallAndroid(platform: SupportedPlatformsType) { await alice1.clickOnElementById( 'com.android.permissioncontroller:id/permission_allow_foreground_only_button' ); - + await alice1.checkModalStrings( + englishStrippedStr('sessionNotifications').toString(), + englishStrippedStr('callsNotificationsRequired').toString(), + true + ); + await sleepFor(100); + await alice1.clickOnElementAll(new NotificationSettings(alice1)); + await alice1.clickOnElementAll(new NotificationSwitch(alice1)); await alice1.navigateBack(); // Enable voice calls on device 2 for User B - await bob1.clickOnByAccessibilityID('Call'); + await bob1.clickOnElementAll(new CallButton(bob1)); // Enabled voice calls in privacy settings await bob1.clickOnElementAll({ strategy: 'accessibility id', @@ -221,9 +232,18 @@ async function voiceCallAndroid(platform: SupportedPlatformsType) { await bob1.clickOnElementById( 'com.android.permissioncontroller:id/permission_allow_foreground_only_button' ); + await bob1.checkModalStrings( + englishStrippedStr('sessionNotifications').toString(), + englishStrippedStr('callsNotificationsRequired').toString(), + true + ); + await sleepFor(100); + await bob1.clickOnElementAll(new NotificationSettings(bob1)); + await bob1.clickOnElementAll(new NotificationSwitch(bob1)); + await bob1.navigateBack(); await bob1.navigateBack(); // Make call on device 1 (alice) - await alice1.clickOnByAccessibilityID('Call'); + await bob1.clickOnElementAll(new CallButton(bob1)); // Answer call on device 2 await bob1.clickOnElementById('network.loki.messenger:id/acceptCallButton'); // Wait 5 seconds diff --git a/run/test/specs/warning_modal_new_account.spec.ts b/run/test/specs/warning_modal_new_account.spec.ts index 57a4089..966b3ab 100644 --- a/run/test/specs/warning_modal_new_account.spec.ts +++ b/run/test/specs/warning_modal_new_account.spec.ts @@ -3,13 +3,13 @@ import { androidIt } from '../../types/sessionIt'; import { USERNAME } from '../../types/testing'; import { BackButton, - ContinueButton, CreateAccountButton, DisplayNameInput, SlowModeRadio, WarningModalQuitButton, } from './locators/onboarding'; import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from './utils/open_app'; +import { ContinueButton } from '../specs/locators/global'; // These modals no longer exist in groups rebuild for iOS androidIt({ diff --git a/run/test/specs/warning_modal_restore_account.spec.ts b/run/test/specs/warning_modal_restore_account.spec.ts index 9b19597..fa46a96 100644 --- a/run/test/specs/warning_modal_restore_account.spec.ts +++ b/run/test/specs/warning_modal_restore_account.spec.ts @@ -3,12 +3,12 @@ import { androidIt } from '../../types/sessionIt'; import { AccountRestoreButton, BackButton, - ContinueButton, SeedPhraseInput, SlowModeRadio, WarningModalQuitButton, } from './locators/onboarding'; import { closeApp, openAppOnPlatformSingleDevice, SupportedPlatformsType } from './utils/open_app'; +import { ContinueButton } from '../specs/locators/global'; // These modals no longer exist in groups rebuild for iOS androidIt({ title: 'Warning modal on restore account', diff --git a/run/types/DeviceWrapper.ts b/run/types/DeviceWrapper.ts index f946646..69a84f1 100644 --- a/run/types/DeviceWrapper.ts +++ b/run/types/DeviceWrapper.ts @@ -10,13 +10,27 @@ import { ImageName, ImagePermissionsModalAllow, LocatorsInterface, - PrivacyButton, ReadReceiptsButton, SendMediaButton, } from '../../run/test/specs/locators'; +import { englishStrippedStr } from '../localizer/englishStrippedStr'; +import { + AttachmentsButton, + MessageInput, + OutgoingMessageStatusSent, +} from '../test/specs/locators/conversation'; import { ModalDescription, ModalHeading } from '../test/specs/locators/global'; -import { SaveProfilePictureButton, UserSettings } from '../test/specs/locators/settings'; -import { EnterAccountID } from '../test/specs/locators/start_conversation'; +import { LoadingAnimation } from '../test/specs/locators/onboarding'; +import { + PrivacyMenuItem, + SaveProfilePictureButton, + UserSettings, +} from '../test/specs/locators/settings'; +import { + EnterAccountID, + NewMessageOption, + NextButton, +} from '../test/specs/locators/start_conversation'; import { clickOnCoordinates, sleepFor } from '../test/specs/utils'; import { getAdbFullPath } from '../test/specs/utils/binaries'; import { parseDataImage } from '../test/specs/utils/check_colour'; @@ -33,6 +47,7 @@ import { User, XPath, } from './testing'; +import { PlusButton } from '../test/specs/locators/home'; import { testFile, testImage, @@ -40,8 +55,6 @@ import { profilePicture, testVideoThumbnail, } from '../constants/testfiles'; -import { AttachmentsButton, OutgoingMessageStatusSent } from '../test/specs/locators/conversation'; -import { englishStrippedStr } from '../localizer/englishStrippedStr'; import * as path from 'path'; import fs from 'fs/promises'; import { getImageOccurrence } from '@appium/opencv'; @@ -1050,8 +1063,7 @@ export class DeviceWrapper { do { try { loadingAnimation = await this.waitForTextElementToBePresent({ - strategy: 'accessibility id', - selector: 'Loading animation', + ...new LoadingAnimation(this).build(), maxWait: 1000, }); @@ -1112,17 +1124,17 @@ export class DeviceWrapper { public async sendNewMessage(user: Pick, message: string) { // Sender workflow // Click on plus button - await this.clickOnByAccessibilityID('New conversation button'); + await this.clickOnElementAll(new PlusButton(this)); // Select direct message option - await this.clickOnByAccessibilityID('New direct message'); + await this.clickOnElementAll(new NewMessageOption(this)); // Enter User B's session ID into input box await this.inputText(user.accountID, new EnterAccountID(this)); // Click next await this.scrollDown(); - await this.clickOnByAccessibilityID('Next'); + await this.clickOnElementAll(new NextButton(this)); // Type message into message input box - await this.inputText(message, { strategy: 'accessibility id', selector: 'Message input box' }); + await this.inputText(message, new MessageInput(this)); // Click send const sendButton = await this.clickOnElementAll({ strategy: 'accessibility id', @@ -1231,7 +1243,7 @@ export class DeviceWrapper { } } else { const radioButton = await this.waitForTextElementToBePresent({ - strategy: 'accessibility id', + strategy: 'id', selector: timeOption, }); const attr = await this.getAttribute('selected', radioButton.ELEMENT); @@ -1763,7 +1775,7 @@ export class DeviceWrapper { await sleepFor(100); await this.clickOnElementAll(new UserSettings(this)); await sleepFor(500); - await this.clickOnElementAll(new PrivacyButton(this)); + await this.clickOnElementAll(new PrivacyMenuItem(this)); await sleepFor(2000); await this.clickOnElementAll(new ReadReceiptsButton(this)); await this.navigateBack(); diff --git a/run/types/testing.ts b/run/types/testing.ts index 1b939f1..843d27f 100644 --- a/run/types/testing.ts +++ b/run/types/testing.ts @@ -80,6 +80,8 @@ export enum DISAPPEARING_TIMES { OFF_ANDROID = 'Disable disappearing messages', } +export type DisappearingOptions = `Disappear after ${DisappearModes} option`; + export type DisappearOpts1o1 = [ '1:1', `Disappear after ${DisappearModes} option`, @@ -344,12 +346,14 @@ export type AccessibilityId = | 'Legacy group banner' | 'Legacy Groups Recreate Button' | 'Confirm leave' + | 'Albums' + | `Disappear after ${DisappearActions} option` + | 'Call button' | 'Session Network' | 'Learn more link' | 'Open' | 'Learn about staking link' | 'Last updated timestamp' - | 'Albums' | 'Save to Files' | 'Replace' | 'ShareButton' @@ -395,7 +399,6 @@ export type Id = | 'Delete' | 'android:id/content_preview_text' | 'network.loki.messenger:id/search_result_title' - | 'Error message' | 'Enter display name' | 'Session id input box' | 'com.android.chrome:id/url_bar' @@ -433,7 +436,38 @@ export type Id = | 'Image button' | 'network.loki.messenger:id/system_settings_app_icon' | 'MeetingSE option' - | 'donate-menu-item'; + | 'donate-menu-item' + | 'android.widget.TextView' + | 'Create account button' + | 'Restore your session button' + | 'Open URL' + | 'Loading animation' + | 'Slow mode notifications button' + | 'Reveal recovery phrase button' + | 'Recovery password container' + | 'Copy button' + | 'New direct message' + | 'Join community button' + | 'Invite friend button' + | 'Conversations' + | 'Hide recovery password button' + | 'error-message' + | 'Next' + | 'Set button' + | 'disappearing-messages-menu-option' + | 'Disable disappearing messages' + | DISAPPEARING_TIMES + | 'conversation-options-avatar' + | `Disappear after ${DisappearModes} option` + | 'Disappearing messages type and time' + | 'Account ID' + | 'Share button' + | 'Call' + | 'Conversation header name' + | 'block-user-confirm-button' + | 'Notifications' + | 'All Session notifications' + | 'com.android.settings:id/switch_text'; export type TestRisk = 'high' | 'medium' | 'low';