Skip to content

Commit e533aa7

Browse files
authored
Merge pull request #29 from Miki-Session/feat/qa-922/groups-warning-banner
Groups version warning banners
2 parents cc290d1 + b145ed8 commit e533aa7

File tree

7 files changed

+141
-11
lines changed

7 files changed

+141
-11
lines changed

.env.sample

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# this is a sample .env file. Copy it to .env, and edit the .env file to match your needs.
22

33
export ANDROID_APK=/home/yougotthis/Downloads/session-android-universal.apk
4+
export IOS_APP_PATH_PREFIX=/home/yougotthis/Downloads/Session.app
45
export SDK_MANAGER_FULL_PATH=/home/yougotthis/Android/Sdk/cmdline-tools/latest/bin/sdkmanager
56
export AVD_MANAGER_FULL_PATH=/home/yougotthis/Android/Sdk/cmdline-tools/latest/bin/avdmanager
67
export EMULATOR_FULL_PATH=/home/yougotthis/Android/Sdk/emulator/emulator
@@ -14,3 +15,7 @@ export IOS_FIFTH_SIMULATOR=just_not_empty
1415
export IOS_SIXTH_SIMULATOR=just_not_empty
1516
export IOS_SEVENTH_SIMULATOR=just_not_empty
1617
export IOS_EIGHTH_SIMULATOR=just_not_empty
18+
export IOS_NINTH_SIMULATOR=just_not_empty
19+
export IOS_TENTH_SIMULATOR=just_not_empty
20+
export IOS_ELEVENTH_SIMULATOR=just_not_empty
21+
export IOS_TWELFTH_SIMULATOR=just_not_empty
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { bothPlatformsIt } from '../../types/sessionIt';
2+
import { USERNAME } from '../../types/testing';
3+
import { PlusButton } from './locators/home';
4+
import { CreateGroupOption } from './locators/start_conversation';
5+
import { newUser } from './utils/create_account';
6+
import { closeApp, openAppTwoDevices, SupportedPlatformsType } from './utils/open_app';
7+
import { newContact } from './utils/create_contact';
8+
import { LatestReleaseBanner } from './locators/groups';
9+
10+
bothPlatformsIt('Create group banner', 'high', createGroupBanner);
11+
12+
async function createGroupBanner(platform: SupportedPlatformsType) {
13+
const { device1, device2 } = await openAppTwoDevices(platform);
14+
// Create users A and B
15+
const [userA, userB] = await Promise.all([
16+
newUser(device1, USERNAME.ALICE),
17+
newUser(device2, USERNAME.BOB),
18+
]);
19+
await newContact(platform, device1, userA, device2, userB);
20+
await device1.navigateBack();
21+
// Open the Create Group screen from home
22+
await device1.clickOnElementAll(new PlusButton(device1));
23+
await device1.clickOnElementAll(new CreateGroupOption(device1));
24+
const groupsBanner = await device1.doesElementExist(new LatestReleaseBanner(device1));
25+
if (!groupsBanner) {
26+
throw new Error('v2 groups warning banner is not shown or text is incorrect');
27+
}
28+
await closeApp(device1, device2);
29+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { bothPlatformsIt } from '../../types/sessionIt';
2+
import { USERNAME } from '../../types/testing';
3+
import { newUser } from './utils/create_account';
4+
import { closeApp, openAppThreeDevices, SupportedPlatformsType } from './utils/open_app';
5+
import { createGroup } from './utils/create_group';
6+
import { ConversationSettings } from './locators/conversation';
7+
import { EditGroup } from './locators';
8+
import { LatestReleaseBanner } from './locators/groups';
9+
10+
bothPlatformsIt('Edit group banner', 'medium', editGroupBanner);
11+
12+
async function editGroupBanner(platform: SupportedPlatformsType) {
13+
const { device1, device2, device3 } = await openAppThreeDevices(platform);
14+
// Create users A, B and C
15+
const [userA, userB, userC] = await Promise.all([
16+
newUser(device1, USERNAME.ALICE),
17+
newUser(device2, USERNAME.BOB),
18+
newUser(device3, USERNAME.CHARLIE),
19+
]);
20+
// Create group
21+
const testGroupName = 'Test group';
22+
await createGroup(platform, device1, userA, device2, userB, device3, userC, testGroupName);
23+
// Navigate to Edit Group screen
24+
await device1.clickOnElementAll(new ConversationSettings(device1));
25+
await device1.clickOnElementAll(new EditGroup(device1));
26+
const groupsBanner = await device1.doesElementExist(new LatestReleaseBanner(device1));
27+
if (!groupsBanner) {
28+
throw new Error('v2 groups warning banner is not shown or text is incorrect');
29+
}
30+
await closeApp(device1, device2, device3);
31+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { bothPlatformsIt } from '../../types/sessionIt';
2+
import { USERNAME } from '../../types/testing';
3+
import { newUser } from './utils/create_account';
4+
import { closeApp, openAppThreeDevices, SupportedPlatformsType } from './utils/open_app';
5+
import { createGroup } from './utils/create_group';
6+
import { ConversationSettings } from './locators/conversation';
7+
import { EditGroup, InviteContactsButton } from './locators';
8+
import { LatestReleaseBanner } from './locators/groups';
9+
10+
bothPlatformsIt('Invite contacts banner', 'medium', inviteContactGroupBanner);
11+
12+
async function inviteContactGroupBanner(platform: SupportedPlatformsType) {
13+
const { device1, device2, device3 } = await openAppThreeDevices(platform);
14+
// Create users A, B and C
15+
const [userA, userB, userC] = await Promise.all([
16+
newUser(device1, USERNAME.ALICE),
17+
newUser(device2, USERNAME.BOB),
18+
newUser(device3, USERNAME.CHARLIE),
19+
]);
20+
// Create group
21+
const testGroupName = 'Test group';
22+
await createGroup(platform, device1, userA, device2, userB, device3, userC, testGroupName);
23+
// Navigate to Invite Contacts screen
24+
await device1.clickOnElementAll(new ConversationSettings(device1));
25+
await device1.clickOnElementAll(new EditGroup(device1));
26+
await device1.clickOnElementAll(new InviteContactsButton(device1));
27+
const groupsBanner = await device1.doesElementExist(new LatestReleaseBanner(device1));
28+
if (!groupsBanner) {
29+
throw new Error('v2 groups warning banner is not shown or text is incorrect');
30+
}
31+
await closeApp(device1, device2, device3);
32+
}

run/test/specs/locators/groups.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { LocatorsInterface } from '.';
22
import { StrategyExtractionObj } from '../../../types/testing';
3+
import { englishStripped } from '../../../localizer/i18n/localizedString';
34

45
export class GroupNameInput extends LocatorsInterface {
56
public build(): StrategyExtractionObj {
@@ -103,3 +104,23 @@ export class LeaveGroupButton extends LocatorsInterface {
103104
}
104105
}
105106
}
107+
export class LatestReleaseBanner extends LocatorsInterface {
108+
public build() {
109+
switch (this.platform) {
110+
// On Android, the text of the banner is exposed to Appium
111+
// so it's possible to verify that the banner is visible and it has the correct text
112+
case 'android':
113+
return {
114+
strategy: 'id',
115+
selector: 'Version warning banner',
116+
text: englishStripped('groupInviteVersion').toString(),
117+
} as const;
118+
case 'ios':
119+
// On iOS, the text is currently not exposed to Appium
120+
return {
121+
strategy: 'accessibility id',
122+
selector: 'Version warning banner',
123+
} as const;
124+
}
125+
}
126+
}

run/types/DeviceWrapper.ts

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -658,12 +658,16 @@ export class DeviceWrapper {
658658
public async doesElementExist(
659659
args: { text?: string; maxWait?: number } & (StrategyExtractionObj | LocatorsInterface)
660660
) {
661-
const { text, maxWait } = args;
662661
const beforeStart = Date.now();
663-
const maxWaitMSec = maxWait || 30000;
662+
const maxWaitMSec = args.maxWait || 30000;
664663
const waitPerLoop = 100;
665664
let element: AppiumNextElementType | null = null;
665+
666+
// Build the locator if necessary, and extract the expected text.
667+
// Use the text from the locator if available; otherwise fallback to args.text.
668+
// This ensures that the correct text value is used for matching, preventing false positives in tests.
666669
const locator = args instanceof LocatorsInterface ? args.build() : args;
670+
const text: string | undefined = ('text' in locator ? locator.text : undefined) || args.text;
667671

668672
while (element === null) {
669673
try {
@@ -674,26 +678,32 @@ export class DeviceWrapper {
674678
element = await this.findMatchingTextInElementArray(els, text);
675679
if (element) {
676680
console.log(
677-
`${locator.strategy}: ${locator.selector} with matching text ${text} found`
681+
`${locator.strategy}: ${locator.selector} with matching text "${text}" found`
678682
);
679683
} else {
680684
console.log(
681-
`Couldn't find ${text} with matching ${locator.strategy}: ${locator.selector}`
685+
`Couldn't find "${text}" with matching ${locator.strategy}: ${locator.selector}`
682686
);
683687
}
684688
}
685689
} catch (e: any) {
686-
console.info(`doesElementExist failed with`, `${locator.strategy} ${locator.selector}`);
690+
console.info(`doesElementExist failed with ${locator.strategy} ${locator.selector}`);
687691
}
688-
if (!element) {
689-
await sleepFor(waitPerLoop);
692+
// Break immediately if we found the element
693+
if (element) {
694+
break;
690695
}
691-
if (beforeStart + maxWaitMSec <= Date.now()) {
692-
console.log(locator.selector, " doesn't exist, time expired");
696+
697+
// Check for timeout before sleeping
698+
if (Date.now() >= beforeStart + maxWaitMSec) {
699+
console.log(locator.selector, "doesn't exist, time expired");
693700
break;
694701
} else {
695702
console.log(locator.selector, "Doesn't exist but retrying");
696703
}
704+
705+
// Sleep before trying again
706+
await sleepFor(waitPerLoop);
697707
}
698708

699709
return element;

run/types/testing.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,8 @@ export type AccessibilityId =
344344
| '1967-05-06 07:00:00 +0000'
345345
| '1967-05-05 20:00:00 +0000'
346346
| '1967-05-05 21:00:00 +0000'
347-
| 'Pin';
347+
| 'Pin'
348+
| 'Version warning banner';
348349

349350
export type Id =
350351
| 'Modal heading'
@@ -405,7 +406,8 @@ export type Id =
405406
| 'Hide'
406407
| 'com.google.android.apps.photos:id/text'
407408
| 'network.loki.messenger:id/search_cancel'
408-
| 'Download media';
409+
| 'Download media'
410+
| 'Version warning banner';
409411

410412
export type TestRisk = 'high' | 'medium' | 'low' | undefined;
411413

0 commit comments

Comments
 (0)