From 1411b93f2d4e845c79592b94fa2b10bc5cd39f1c Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 14 Sep 2022 13:53:44 +1000 Subject: [PATCH 1/7] fix: do not let mentioning members with their unblindedPubkey room blinded --- ts/node/sql.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ts/node/sql.ts b/ts/node/sql.ts index 29c8bd6a6..e71b1da05 100644 --- a/ts/node/sql.ts +++ b/ts/node/sql.ts @@ -9,6 +9,7 @@ import { difference, forEach, fromPairs, + isArray, isEmpty, isNumber, isObject, @@ -646,10 +647,23 @@ function getAllOpenGroupV2ConversationsIds(): Array { } function getPubkeysInPublicConversation(conversationId: string) { + const conversation = getV2OpenGroupRoom(conversationId); + if (!conversation) { + return []; + } + + const hasBlindOn = Boolean( + conversation.capabilities && + isArray(conversation.capabilities) && + conversation.capabilities?.includes('blind') + ); + + const whereClause = hasBlindOn ? 'AND source LIKE "15%"' : ''; + const rows = assertGlobalInstance() .prepare( `SELECT DISTINCT source FROM ${MESSAGES_TABLE} WHERE - conversationId = $conversationId + conversationId = $conversationId ${whereClause} ORDER BY received_at DESC LIMIT ${MAX_PUBKEYS_MEMBERS};` ) .all({ From c6e3116b06be48230efd45912f3cdf0e0e42b86a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 14 Sep 2022 15:46:18 +1000 Subject: [PATCH 2/7] fix integration tests --- ts/components/MemberListItem.tsx | 2 +- .../leftpane/LeftPaneSettingSection.tsx | 2 +- ts/components/settings/BlockedList.tsx | 2 ++ ts/session/types/PubKey.ts | 3 +- ts/test/automation/blocking_user.spec.ts | 30 ++++++++++++------- ts/test/automation/change_avatar.spec.ts | 8 ++--- ts/test/automation/change_username.spec.ts | 4 ++- ts/test/automation/create_user.spec.ts | 4 ++- ts/test/automation/delete_account.spec.ts | 8 +++-- .../automation/disappearing_messages.spec.ts | 4 ++- ts/test/automation/group_creation.spec.ts | 6 ++-- ts/test/automation/group_testing.spec.ts | 4 ++- ts/test/automation/group_upkeep.spec.ts | 4 ++- ts/test/automation/linking_device.spec.ts | 4 ++- ts/test/automation/mentions.spec.ts | 4 ++- ts/test/automation/message_requests.spec.ts | 4 ++- ts/test/automation/new_contact_test.spec.ts | 4 ++- ts/test/automation/password.spec.ts | 4 ++- ts/test/automation/setup/beforeEach.ts | 26 ++++++++++------ ts/test/automation/setup/create_group.ts | 4 +-- ts/test/automation/setup/new_user.ts | 6 +--- ts/test/automation/switching_theme.spec.ts | 4 ++- ts/test/automation/unsend_message.spec.ts | 4 ++- 23 files changed, 94 insertions(+), 51 deletions(-) diff --git a/ts/components/MemberListItem.tsx b/ts/components/MemberListItem.tsx index 3b06be785..693f08251 100644 --- a/ts/components/MemberListItem.tsx +++ b/ts/components/MemberListItem.tsx @@ -32,7 +32,7 @@ const StyledSessionMemberItem = styled.button<{ font-family: var(--font-default); padding: 0px var(--margins-sm); height: ${props => (props.inMentions ? '40px' : '50px')}; - + width: 100%; transition: var(--default-duration); opacity: ${props => (props.zombie ? 0.5 : 1)}; background-color: ${props => diff --git a/ts/components/leftpane/LeftPaneSettingSection.tsx b/ts/components/leftpane/LeftPaneSettingSection.tsx index 4eaa33e17..25f24e9ec 100644 --- a/ts/components/leftpane/LeftPaneSettingSection.tsx +++ b/ts/components/leftpane/LeftPaneSettingSection.tsx @@ -64,7 +64,7 @@ const LeftPaneSettingsCategoryRow = (props: { const dispatch = useDispatch(); const focusedSettingsSection = useSelector(getFocusedSettingsSection); - const dataTestId = `${title.toLowerCase()}-settings-menu-item`; + const dataTestId = `${title.toLowerCase().replace(' ', '-')}-settings-menu-item`; const isClearData = id === SessionSettingCategory.ClearData; diff --git a/ts/components/settings/BlockedList.tsx b/ts/components/settings/BlockedList.tsx index e32c80ace..8812cc985 100644 --- a/ts/components/settings/BlockedList.tsx +++ b/ts/components/settings/BlockedList.tsx @@ -133,6 +133,7 @@ export const BlockedContactsList = () => { buttonType={SessionButtonType.BrandOutline} text={window.i18n('unblockUser')} onClick={unBlockThoseUsers} + dataTestId="unblock-button-settings-screen" /> ) : null} @@ -141,6 +142,7 @@ export const BlockedContactsList = () => { iconType={'chevron'} onClick={toggleUnblockList} iconRotation={expanded ? 0 : 180} + dataTestId="reveal-blocked-user-settings" /> diff --git a/ts/session/types/PubKey.ts b/ts/session/types/PubKey.ts index bea9edbda..b4b1641aa 100644 --- a/ts/session/types/PubKey.ts +++ b/ts/session/types/PubKey.ts @@ -1,7 +1,6 @@ import { fromHexToArray } from '../utils/String'; -export const getStoragePubKey = (key: string) => - window.sessionFeatureFlags.useTestNet ? key.substring(2) : key; +export const getStoragePubKey = (key: string) => key; export enum KeyPrefixType { /** diff --git a/ts/test/automation/blocking_user.spec.ts b/ts/test/automation/blocking_user.spec.ts index d70c46b1c..211db723b 100644 --- a/ts/test/automation/blocking_user.spec.ts +++ b/ts/test/automation/blocking_user.spec.ts @@ -1,10 +1,17 @@ -import { _electron, expect, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { _electron, Page, test } from '@playwright/test'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { openAppsAndNewUsers } from './setup/new_user'; import { sendNewMessage } from './send_message'; -import { clickOnMatchingText, clickOnTestIdWithText, waitForTestIdWithText } from './utils'; +import { + clickOnMatchingText, + clickOnTestIdWithText, + waitForMatchingText, + waitForTestIdWithText, +} from './utils'; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); test('Block User', async () => { @@ -19,7 +26,6 @@ test('Block User', async () => { await sendNewMessage(windowA, userB.sessionid, `A -> B: ${Date.now()}`); await sendNewMessage(windowB, userA.sessionid, `B -> A: ${Date.now()}`); // Check to see if User B is a contact - await clickOnTestIdWithText(windowA, 'new-conversation-button'); await waitForTestIdWithText(windowA, 'module-conversation__user__profile-name', userB.userName); @@ -34,14 +40,18 @@ test('Block User', async () => { // Verify the user was moved to the blocked contact list // Click on settings tab await clickOnTestIdWithText(windowA, 'settings-section'); + + // click on settings section 'conversation' + await clickOnTestIdWithText(windowA, 'conversations-settings-menu-item'); + // Navigate to blocked users tab' - await clickOnMatchingText(windowA, 'Blocked contacts'); - // Check for user B's name - const blockedContact = windowA.locator('.session-settings-item__title'); + await clickOnTestIdWithText(windowA, 'reveal-blocked-user-settings'); + // select the contact to unblock by clicking on it by name + await clickOnMatchingText(windowA, userB.userName); - await expect(blockedContact).toContainText(userB.userName); - // Unblock user - await clickOnMatchingText(windowA, 'Unblock'); + // Unblock user by clicking on unblock + await clickOnTestIdWithText(windowA, 'unblock-button-settings-screen'); // Verify toast notification says unblocked await waitForTestIdWithText(windowA, 'session-toast', 'Unblocked'); + await waitForMatchingText(windowA, 'No blocked contacts'); }); diff --git a/ts/test/automation/change_avatar.spec.ts b/ts/test/automation/change_avatar.spec.ts index fdc09aed1..5dceda607 100644 --- a/ts/test/automation/change_avatar.spec.ts +++ b/ts/test/automation/change_avatar.spec.ts @@ -1,10 +1,11 @@ import { _electron, expect, Page, test } from '@playwright/test'; import { openAppAndWait } from './setup/open'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { newUser } from './setup/new_user'; import { clickOnTestIdWithText, waitForTestIdWithText } from './utils'; let window: Page | undefined; +test.beforeEach(beforeAllClean); test.afterEach(async () => { if (window) { @@ -29,10 +30,7 @@ test('Change profile picture/avatar', async () => { await waitForTestIdWithText(window, 'copy-button-profile-update', 'Copy'); await clickOnTestIdWithText(window, 'modal-close-button'); - const leftpaneAvatarContainer = await waitForTestIdWithText( - window, - 'img-leftpane-primary-avatar' - ); + const leftpaneAvatarContainer = await waitForTestIdWithText(window, 'leftpane-primary-avatar'); const screenshot = await leftpaneAvatarContainer.screenshot({ type: 'jpeg', // path: 'avatar-updated-blue', diff --git a/ts/test/automation/change_username.spec.ts b/ts/test/automation/change_username.spec.ts index 3a2d7d6a0..679aadcd2 100644 --- a/ts/test/automation/change_username.spec.ts +++ b/ts/test/automation/change_username.spec.ts @@ -1,10 +1,12 @@ import { _electron, expect, Page, test } from '@playwright/test'; import { newUser } from './setup/new_user'; import { openAppAndWait } from './setup/open'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { clickOnTestIdWithText, typeIntoInput } from './utils'; let window: Page | undefined; +test.beforeEach(beforeAllClean); + test.afterEach(async () => { if (window) { await forceCloseAllWindows([window]); diff --git a/ts/test/automation/create_user.spec.ts b/ts/test/automation/create_user.spec.ts index 130223348..6f3b749d9 100644 --- a/ts/test/automation/create_user.spec.ts +++ b/ts/test/automation/create_user.spec.ts @@ -2,10 +2,12 @@ import { _electron, Page, test } from '@playwright/test'; import { newUser } from './setup/new_user'; import { openAppAndWait } from './setup/open'; import { sleepFor } from '../../session/utils/Promise'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { clickOnMatchingText, clickOnTestIdWithText, waitForTestIdWithText } from './utils'; let window: Page | undefined; +test.beforeEach(beforeAllClean); + test.afterEach(async () => { if (window) { await forceCloseAllWindows([window]); diff --git a/ts/test/automation/delete_account.spec.ts b/ts/test/automation/delete_account.spec.ts index bbf9c8957..815c32f56 100644 --- a/ts/test/automation/delete_account.spec.ts +++ b/ts/test/automation/delete_account.spec.ts @@ -1,5 +1,5 @@ import { _electron, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { openAppsAndNewUsers, openAppsNoNewUsers } from './setup/new_user'; import { sendNewMessage } from './send_message'; import { clickOnMatchingText, clickOnTestIdWithText, typeIntoInput } from './utils'; @@ -7,6 +7,8 @@ import { sleepFor } from '../../session/utils/Promise'; // tslint:disable: no-console let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); test('Delete account from swarm', async () => { @@ -25,7 +27,7 @@ test('Delete account from swarm', async () => { // Click on settings tab await clickOnTestIdWithText(windowA, 'settings-section'); // Click on clear all data - await clickOnMatchingText(windowA, 'Clear All Data'); + await clickOnTestIdWithText(windowA, 'clear-data-settings-menu-item', 'Clear Data'); // Select entire account await clickOnMatchingText(windowA, 'Entire Account'); // Confirm deletion by clicking i am sure @@ -44,6 +46,8 @@ test('Delete account from swarm', async () => { await typeIntoInput(restoringWindow, 'display-name-input', userA.userName); // Click continue await clickOnTestIdWithText(restoringWindow, 'continue-session-button'); + console.log('sleeping for 20000ms'); + await sleepFor(20000); // just to allow any messages from our swarm to show up // Check if message from user B is restored (we don't want it to be) const errorDesc = 'Test Message should not be found'; try { diff --git a/ts/test/automation/disappearing_messages.spec.ts b/ts/test/automation/disappearing_messages.spec.ts index 58e1cf00f..5a2b554ec 100644 --- a/ts/test/automation/disappearing_messages.spec.ts +++ b/ts/test/automation/disappearing_messages.spec.ts @@ -1,5 +1,5 @@ import { _electron, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { messageSent } from './message'; import { openAppsAndNewUsers } from './setup/new_user'; import { sendNewMessage } from './send_message'; @@ -12,6 +12,8 @@ import { } from './utils'; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); // tslint:disable: no-console diff --git a/ts/test/automation/group_creation.spec.ts b/ts/test/automation/group_creation.spec.ts index 49a4bab58..a582dd7e0 100644 --- a/ts/test/automation/group_creation.spec.ts +++ b/ts/test/automation/group_creation.spec.ts @@ -1,5 +1,5 @@ import { _electron, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { messageSent } from './message'; import { openAppsAndNewUsers } from './setup/new_user'; import { sendNewMessage } from './send_message'; @@ -14,6 +14,8 @@ import { const testGroupName = 'Test Group Name'; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); test('Create group', async () => { @@ -39,7 +41,7 @@ test('Create group', async () => { // Select user C await clickOnMatchingText(windowA, userC.userName); // Click Done - await clickOnMatchingText(windowA, 'Done'); + await clickOnTestIdWithText(windowA, 'next-button'); // Check group was successfully created await clickOnMatchingText(windowB, testGroupName); await waitForTestIdWithText(windowB, 'header-conversation-name', testGroupName); diff --git a/ts/test/automation/group_testing.spec.ts b/ts/test/automation/group_testing.spec.ts index b6aa5a7a5..046d6c3ff 100644 --- a/ts/test/automation/group_testing.spec.ts +++ b/ts/test/automation/group_testing.spec.ts @@ -1,5 +1,5 @@ import { _electron, expect, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; // import { recoverFromSeed } from './setup/recovery_using_seed'; import { clickOnMatchingText, @@ -14,6 +14,8 @@ import { leaveGroup } from './leave_group'; import { createGroup } from './setup/create_group'; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); test('Group testing', async () => { diff --git a/ts/test/automation/group_upkeep.spec.ts b/ts/test/automation/group_upkeep.spec.ts index 69e91873b..a439b9a11 100644 --- a/ts/test/automation/group_upkeep.spec.ts +++ b/ts/test/automation/group_upkeep.spec.ts @@ -1,5 +1,5 @@ import { _electron, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { openAppsNoNewUsers } from './setup/new_user'; import { sendNewMessage } from './send_message'; import { logIn } from './setup/log_in'; @@ -12,6 +12,8 @@ import { } from './setup/test_user'; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); test.skip('Group upkeep', async () => { diff --git a/ts/test/automation/linking_device.spec.ts b/ts/test/automation/linking_device.spec.ts index a46f371d0..b72993a07 100644 --- a/ts/test/automation/linking_device.spec.ts +++ b/ts/test/automation/linking_device.spec.ts @@ -1,9 +1,11 @@ import { _electron, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { linkedDevice } from './setup/linked_device'; import { clickOnTestIdWithText, typeIntoInput, waitForTestIdWithText } from './utils'; const windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); // tslint:disable: no-console diff --git a/ts/test/automation/mentions.spec.ts b/ts/test/automation/mentions.spec.ts index e89131796..36cd58be3 100644 --- a/ts/test/automation/mentions.spec.ts +++ b/ts/test/automation/mentions.spec.ts @@ -1,9 +1,11 @@ import { _electron, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { clickOnTestIdWithText, typeIntoInput, waitForTestIdWithText } from './utils'; import { createGroup } from './setup/create_group'; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); test('Mentions', async () => { diff --git a/ts/test/automation/message_requests.spec.ts b/ts/test/automation/message_requests.spec.ts index 385020320..b1ba016d1 100644 --- a/ts/test/automation/message_requests.spec.ts +++ b/ts/test/automation/message_requests.spec.ts @@ -1,12 +1,14 @@ import { _electron, Page, test } from '@playwright/test'; import { sendNewMessage } from './send_message'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { openAppsAndNewUsers } from './setup/new_user'; import { clickOnTestIdWithText, waitForMatchingText, waitForTestIdWithText } from './utils'; const testMessage = 'A -> B'; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); // Open two windows and log into 2 separate accounts test.describe('Message requests', () => { diff --git a/ts/test/automation/new_contact_test.spec.ts b/ts/test/automation/new_contact_test.spec.ts index 52be8e8c9..9644510cf 100644 --- a/ts/test/automation/new_contact_test.spec.ts +++ b/ts/test/automation/new_contact_test.spec.ts @@ -1,5 +1,5 @@ import { _electron, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { sendNewMessage } from './send_message'; import { openAppsAndNewUsers } from './setup/new_user'; @@ -9,6 +9,8 @@ const testMessage = 'A -> B'; const testReply = 'B -> A'; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); // Send message in one to one conversation with new contact diff --git a/ts/test/automation/password.spec.ts b/ts/test/automation/password.spec.ts index 308d29690..f4506ec7c 100644 --- a/ts/test/automation/password.spec.ts +++ b/ts/test/automation/password.spec.ts @@ -1,5 +1,5 @@ import { _electron, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { newUser } from './setup/new_user'; import { openAppAndWait } from './setup/open'; import { @@ -11,6 +11,8 @@ import { } from './utils'; let window: Page | undefined; +test.beforeEach(beforeAllClean); + test.afterEach(async () => { if (window) { await forceCloseAllWindows([window]); diff --git a/ts/test/automation/setup/beforeEach.ts b/ts/test/automation/setup/beforeEach.ts index 725efab7f..6cada0449 100644 --- a/ts/test/automation/setup/beforeEach.ts +++ b/ts/test/automation/setup/beforeEach.ts @@ -7,16 +7,20 @@ import { MULTI_PREFIX, NODE_ENV, openElectronAppOnly } from './open'; const getDirectoriesOfSessionDataPath = (source: string) => readdirSync(source, { withFileTypes: true }) .filter(dirent => dirent.isDirectory()) - .map(dirent => dirent.name) - .filter(n => n.startsWith(`Session-${NODE_ENV}-${MULTI_PREFIX}`)); + .map(dirent => { + return dirent.name; + }) + .filter(n => n.includes(`${NODE_ENV}-${MULTI_PREFIX}`)); let alreadyCleaned = false; +let alreadyCleanedWaiting = false; -export const cleanUpOtherTest = async () => { - if (alreadyCleaned) { +const cleanUpOtherTest = async () => { + if (alreadyCleaned || alreadyCleanedWaiting) { return; } alreadyCleaned = true; + const electronApp = await openElectronAppOnly('start'); const appPath = await electronApp.evaluate(async ({ app }) => { @@ -24,23 +28,25 @@ export const cleanUpOtherTest = async () => { }); const window = await electronApp.firstWindow(); await window.close(); - if (alreadyCleaned) { + if (alreadyCleaned && alreadyCleanedWaiting) { return; } + alreadyCleanedWaiting = true; + if (!appPath.length) { throw new Error('appDataPath unset'); } + const parentFolderOfAllDataPath = dirname(appPath); if (!parentFolderOfAllDataPath || parentFolderOfAllDataPath.length < 20) { throw new Error('parentFolderOfAllDataPath not found or invalid'); } - console.info('cleaning other tests leftovers...'); + console.info('cleaning other tests leftovers...', parentFolderOfAllDataPath); - if (alreadyCleaned) { - return; - } const allAppDataPath = getDirectoriesOfSessionDataPath(parentFolderOfAllDataPath); + console.info('allAppDataPath', allAppDataPath); + allAppDataPath.map(folder => { if (!appPath) { throw new Error('parentFolderOfAllDataPath unset'); @@ -51,6 +57,8 @@ export const cleanUpOtherTest = async () => { console.info('...done'); }; +export const beforeAllClean = cleanUpOtherTest; + export const forceCloseAllWindows = async (windows: Array) => { return Promise.all(windows.map(w => w.close())); }; diff --git a/ts/test/automation/setup/create_group.ts b/ts/test/automation/setup/create_group.ts index 60d0ac221..3c4676535 100644 --- a/ts/test/automation/setup/create_group.ts +++ b/ts/test/automation/setup/create_group.ts @@ -38,8 +38,8 @@ export const createGroup = async (groupName: string) => { await clickOnMatchingText(windowA, userB.userName); // Select user C await clickOnMatchingText(windowA, userC.userName); - // Click Done - await clickOnMatchingText(windowA, 'Done'); + // Click Next + await clickOnTestIdWithText(windowA, 'next-button'); // Check group was successfully created await clickOnMatchingText(windowB, groupName); await waitForTestIdWithText(windowB, 'header-conversation-name', groupName); diff --git a/ts/test/automation/setup/new_user.ts b/ts/test/automation/setup/new_user.ts index 3aca163f1..5502da0ca 100644 --- a/ts/test/automation/setup/new_user.ts +++ b/ts/test/automation/setup/new_user.ts @@ -1,7 +1,6 @@ -import { _electron, Page, test } from '@playwright/test'; +import { _electron, Page } from '@playwright/test'; import _ from 'lodash'; import { clickOnMatchingText, typeIntoInput } from '../utils'; -import { cleanUpOtherTest } from './beforeEach'; import { openAppAndWait } from './open'; const multisAvailable = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; @@ -11,9 +10,6 @@ export type UserLoggedInType = { recoveryPhrase: string; }; -test.beforeAll(cleanUpOtherTest); -test.afterAll(cleanUpOtherTest); - export const newUser = async (window: Page, userName: string): Promise => { // Create User await clickOnMatchingText(window, 'Create Session ID'); diff --git a/ts/test/automation/switching_theme.spec.ts b/ts/test/automation/switching_theme.spec.ts index 4a510e8d6..26f0a7025 100644 --- a/ts/test/automation/switching_theme.spec.ts +++ b/ts/test/automation/switching_theme.spec.ts @@ -1,9 +1,11 @@ import { _electron, expect, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { openAppsAndNewUsers } from './setup/new_user'; import { clickOnTestIdWithText } from './utils'; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); test('Switch themes', async () => { diff --git a/ts/test/automation/unsend_message.spec.ts b/ts/test/automation/unsend_message.spec.ts index 60b2b74d2..085ff6d87 100644 --- a/ts/test/automation/unsend_message.spec.ts +++ b/ts/test/automation/unsend_message.spec.ts @@ -1,5 +1,5 @@ import { _electron, Page, test } from '@playwright/test'; -import { forceCloseAllWindows } from './setup/beforeEach'; +import { beforeAllClean, forceCloseAllWindows } from './setup/beforeEach'; import { openAppsAndNewUsers } from './setup/new_user'; import { sendNewMessage } from './send_message'; import { @@ -13,6 +13,8 @@ const testMessage = 'A -> B: '; const testReply = 'B -> A: '; let windows: Array = []; +test.beforeEach(beforeAllClean); + test.afterEach(() => forceCloseAllWindows(windows)); test('Unsend message', async () => { From 772fe27b2bf209a0ba4c9b56e9c3054fd8bb4ffa Mon Sep 17 00:00:00 2001 From: William Grant Date: Thu, 15 Sep 2022 11:00:47 +1000 Subject: [PATCH 3/7] fix: compressed reactions shouldn't wrap, when expanded we show at most 10 reactions on a time --- .../message/message-content/MessageReactions.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ts/components/conversation/message/message-content/MessageReactions.tsx b/ts/components/conversation/message/message-content/MessageReactions.tsx index 8a1d512b4..d42f79cef 100644 --- a/ts/components/conversation/message/message-content/MessageReactions.tsx +++ b/ts/components/conversation/message/message-content/MessageReactions.tsx @@ -21,8 +21,8 @@ const StyledMessageReactionsContainer = styled(Flex)<{ x: number; y: number }>` } `; -export const StyledMessageReactions = styled(Flex)<{ inModal: boolean }>` - ${props => (props.inModal ? '' : 'max-width: 320px;')} +export const StyledMessageReactions = styled(Flex)<{ fullWidth: boolean }>` + ${props => (props.fullWidth ? '' : 'max-width: 640px;')} `; const StyledReactionOverflow = styled.button` @@ -63,7 +63,7 @@ const Reactions = (props: ReactionsProps): ReactElement => { container={true} flexWrap={inModal ? 'nowrap' : 'wrap'} alignItems={'center'} - inModal={inModal} + fullWidth={inModal} > {reactions.map(([emoji, _]) => ( @@ -83,7 +83,7 @@ const CompressedReactions = (props: ExpandReactionsProps): ReactElement => { container={true} flexWrap={inModal ? 'nowrap' : 'wrap'} alignItems={'center'} - inModal={inModal} + fullWidth={true} > {reactions.slice(0, 4).map(([emoji, _]) => ( From 17742539afc5a3b2bfda49e1c699e2de7ad0e43d Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 15 Sep 2022 09:58:41 +1000 Subject: [PATCH 4/7] fix: disable typing and message request on sogs without `write` --- stylesheets/_session.scss | 2 +- ts/components/conversation/TypingAnimation.tsx | 2 +- .../message/message-content/MessageAvatar.tsx | 8 ++++++++ ts/models/conversation.ts | 17 +++++++++++++++++ ts/state/ducks/conversations.ts | 7 +++++-- ts/state/selectors/conversations.ts | 4 ++-- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index db47ef1b1..10c394763 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -79,7 +79,7 @@ textarea { overflow: hidden; outline: none; color: $textAndBorderColor; - border: 2px solid $textAndBorderColor; + border: 1px solid $textAndBorderColor; } width: auto; diff --git a/ts/components/conversation/TypingAnimation.tsx b/ts/components/conversation/TypingAnimation.tsx index 79c1384bc..e414f14b1 100644 --- a/ts/components/conversation/TypingAnimation.tsx +++ b/ts/components/conversation/TypingAnimation.tsx @@ -14,7 +14,7 @@ const StyledTypingContainer = styled.div` const StyledTypingDot = styled.div<{ index: number }>` border-radius: 50%; - background-color: var(--color-text-subtle); // TODO Theming update + background-color: var(--color-text-subtle); // TODO Theming update height: 6px; width: 6px; diff --git a/ts/components/conversation/message/message-content/MessageAvatar.tsx b/ts/components/conversation/message/message-content/MessageAvatar.tsx index 37784e645..a2b1a878d 100644 --- a/ts/components/conversation/message/message-content/MessageAvatar.tsx +++ b/ts/components/conversation/message/message-content/MessageAvatar.tsx @@ -9,6 +9,7 @@ import { PubKey } from '../../../../session/types'; import { openConversationWithMessages } from '../../../../state/ducks/conversations'; import { updateUserDetailsModal } from '../../../../state/ducks/modalDialog'; import { + getIsTypingEnabled, getMessageAvatarProps, getSelectedConversationKey, } from '../../../../state/selectors/conversations'; @@ -37,6 +38,8 @@ export const MessageAvatar = (props: Props) => { const avatarProps = useSelector(state => getMessageAvatarProps(state as any, messageId)); const selectedConvoKey = useSelector(getSelectedConversationKey); + const isTypingEnabled = useSelector(getIsTypingEnabled); + if (!avatarProps) { return null; } @@ -75,6 +78,11 @@ export const MessageAvatar = (props: Props) => { } } + if (isPublic && !isTypingEnabled) { + window.log.info('onMessageAvatarClick: no typing enabled. Dropping...'); + return; + } + if (isPublic && selectedConvoKey) { const convoOpen = getConversationController().get(selectedConvoKey); const room = OpenGroupData.getV2OpenGroupRoom(convoOpen.id); diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index fd2fe7f21..c3ceacf16 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -416,6 +416,23 @@ export class ConversationModel extends Backbone.Model { toRet.currentNotificationSetting = currentNotificationSetting; } + if (this.isOpenGroupV2()) { + const room = OpenGroupData.getV2OpenGroupRoom(this.id); + if (room && isArray(room.capabilities) && room.capabilities.length) { + toRet.capabilities = room.capabilities; + } + + if (this.get('writeCapability')) { + toRet.writeCapability = this.get('writeCapability'); + } + if (this.get('readCapability')) { + toRet.readCapability = this.get('readCapability'); + } + if (this.get('uploadCapability')) { + toRet.uploadCapability = this.get('uploadCapability'); + } + } + const lastMessageText = this.get('lastMessage'); if (lastMessageText && lastMessageText.length) { const lastMessageStatus = this.get('lastMessageStatus'); diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 0ff54b94d..3d4614d4b 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -268,8 +268,11 @@ export interface ReduxConversationType { isApproved?: boolean; didApproveMe?: boolean; - /** Should only be present on open groups - the key (stored as hex) that should be used when sending messages to an open group */ - blindedPublicKey?: string; + // Should only be present on opengroups - the capabilities we have on this room. + capabilities?: Array; + readCapability?: boolean; + writeCapability?: boolean; + uploadCapability?: boolean; } export interface NotificationForConvoOption { diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 7cd8101ce..01c78b002 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -85,9 +85,9 @@ export const getIsTypingEnabled = createSelector( if (!selectedConvo) { return false; } - const { isBlocked, isKickedFromGroup, left } = selectedConvo; + const { isBlocked, isKickedFromGroup, left, isPublic, writeCapability } = selectedConvo; - return !(isBlocked || isKickedFromGroup || left); + return !(isBlocked || isKickedFromGroup || left || (isPublic && !writeCapability)); } ); /** From c076c5b819dff5bb23fff2c73fb84cfcf6b65aaa Mon Sep 17 00:00:00 2001 From: William Grant Date: Thu, 15 Sep 2022 11:20:29 +1000 Subject: [PATCH 5/7] fix: improve alignment in list modal when rendering complex emojis --- ts/components/dialog/ReactListModal.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/ts/components/dialog/ReactListModal.tsx b/ts/components/dialog/ReactListModal.tsx index 4c5ac2375..b14e42ad6 100644 --- a/ts/components/dialog/ReactListModal.tsx +++ b/ts/components/dialog/ReactListModal.tsx @@ -55,6 +55,7 @@ const StyledReactionBar = styled(Flex)` span:nth-child(1) { margin: 0 8px; color: var(--color-text); + white-space: nowrap; } span:nth-child(2) { From 179f8726791723d9eb4394a32286ecc7bcafde2f Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 15 Sep 2022 09:58:41 +1000 Subject: [PATCH 6/7] fix: disable typing and message request on sogs without `write` --- stylesheets/_session.scss | 2 +- ts/components/conversation/TypingAnimation.tsx | 2 +- .../message/message-content/MessageAvatar.tsx | 8 ++++++++ ts/models/conversation.ts | 17 +++++++++++++++++ ts/state/ducks/conversations.ts | 7 +++++-- ts/state/selectors/conversations.ts | 4 ++-- 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index db47ef1b1..10c394763 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -79,7 +79,7 @@ textarea { overflow: hidden; outline: none; color: $textAndBorderColor; - border: 2px solid $textAndBorderColor; + border: 1px solid $textAndBorderColor; } width: auto; diff --git a/ts/components/conversation/TypingAnimation.tsx b/ts/components/conversation/TypingAnimation.tsx index 79c1384bc..e414f14b1 100644 --- a/ts/components/conversation/TypingAnimation.tsx +++ b/ts/components/conversation/TypingAnimation.tsx @@ -14,7 +14,7 @@ const StyledTypingContainer = styled.div` const StyledTypingDot = styled.div<{ index: number }>` border-radius: 50%; - background-color: var(--color-text-subtle); // TODO Theming update + background-color: var(--color-text-subtle); // TODO Theming update height: 6px; width: 6px; diff --git a/ts/components/conversation/message/message-content/MessageAvatar.tsx b/ts/components/conversation/message/message-content/MessageAvatar.tsx index 37784e645..a2b1a878d 100644 --- a/ts/components/conversation/message/message-content/MessageAvatar.tsx +++ b/ts/components/conversation/message/message-content/MessageAvatar.tsx @@ -9,6 +9,7 @@ import { PubKey } from '../../../../session/types'; import { openConversationWithMessages } from '../../../../state/ducks/conversations'; import { updateUserDetailsModal } from '../../../../state/ducks/modalDialog'; import { + getIsTypingEnabled, getMessageAvatarProps, getSelectedConversationKey, } from '../../../../state/selectors/conversations'; @@ -37,6 +38,8 @@ export const MessageAvatar = (props: Props) => { const avatarProps = useSelector(state => getMessageAvatarProps(state as any, messageId)); const selectedConvoKey = useSelector(getSelectedConversationKey); + const isTypingEnabled = useSelector(getIsTypingEnabled); + if (!avatarProps) { return null; } @@ -75,6 +78,11 @@ export const MessageAvatar = (props: Props) => { } } + if (isPublic && !isTypingEnabled) { + window.log.info('onMessageAvatarClick: no typing enabled. Dropping...'); + return; + } + if (isPublic && selectedConvoKey) { const convoOpen = getConversationController().get(selectedConvoKey); const room = OpenGroupData.getV2OpenGroupRoom(convoOpen.id); diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index fd2fe7f21..c3ceacf16 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -416,6 +416,23 @@ export class ConversationModel extends Backbone.Model { toRet.currentNotificationSetting = currentNotificationSetting; } + if (this.isOpenGroupV2()) { + const room = OpenGroupData.getV2OpenGroupRoom(this.id); + if (room && isArray(room.capabilities) && room.capabilities.length) { + toRet.capabilities = room.capabilities; + } + + if (this.get('writeCapability')) { + toRet.writeCapability = this.get('writeCapability'); + } + if (this.get('readCapability')) { + toRet.readCapability = this.get('readCapability'); + } + if (this.get('uploadCapability')) { + toRet.uploadCapability = this.get('uploadCapability'); + } + } + const lastMessageText = this.get('lastMessage'); if (lastMessageText && lastMessageText.length) { const lastMessageStatus = this.get('lastMessageStatus'); diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 0ff54b94d..3d4614d4b 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -268,8 +268,11 @@ export interface ReduxConversationType { isApproved?: boolean; didApproveMe?: boolean; - /** Should only be present on open groups - the key (stored as hex) that should be used when sending messages to an open group */ - blindedPublicKey?: string; + // Should only be present on opengroups - the capabilities we have on this room. + capabilities?: Array; + readCapability?: boolean; + writeCapability?: boolean; + uploadCapability?: boolean; } export interface NotificationForConvoOption { diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 7cd8101ce..01c78b002 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -85,9 +85,9 @@ export const getIsTypingEnabled = createSelector( if (!selectedConvo) { return false; } - const { isBlocked, isKickedFromGroup, left } = selectedConvo; + const { isBlocked, isKickedFromGroup, left, isPublic, writeCapability } = selectedConvo; - return !(isBlocked || isKickedFromGroup || left); + return !(isBlocked || isKickedFromGroup || left || (isPublic && !writeCapability)); } ); /** From 203e4992c358ad45e9ab5bb9c66ddb1bed7aae64 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 15 Sep 2022 12:02:39 +1000 Subject: [PATCH 7/7] bump to Session v1.10.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d61780aff..8c930fa74 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "session-desktop", "productName": "Session", "description": "Private messaging from your desktop", - "version": "1.10.0", + "version": "1.10.1", "license": "GPL-3.0", "author": { "name": "Oxen Labs",