diff --git a/apps/meteor/app/authentication/server/lib/restrictLoginAttempts.ts b/apps/meteor/app/authentication/server/lib/restrictLoginAttempts.ts index 3b6cd6c894090..6f260c8a129c0 100644 --- a/apps/meteor/app/authentication/server/lib/restrictLoginAttempts.ts +++ b/apps/meteor/app/authentication/server/lib/restrictLoginAttempts.ts @@ -22,7 +22,7 @@ const notifyFailedLogin = async (ipOrUsername: string, blockedUntil: Date, faile // to avoid issues when "fname" is presented in the UI, check if the name matches it as well const room = await Rooms.findOneByNameOrFname(channelToNotify); if (!room) { - logger.error("Cannot notify failed logins: channel provided doesn't exists"); + logger.error({ msg: 'Cannot notify failed logins: channel provided does not exist', channelToNotify }); return; } diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 12825cde0f678..13f757b37bc38 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -381,7 +381,7 @@ Accounts.insertUserDoc = async function (options, user) { if (!options.skipAppsEngineEvent) { // `post` triggered events don't need to wait for the promise to resolve Apps.self?.triggerEvent(AppEvents.IPostUserCreated, { user, performedBy: await safeGetMeteorUser() }).catch((e) => { - Apps.self?.getRocketChatLogger().error('Error while executing post user created event:', e); + Apps.self?.getRocketChatLogger().error({ msg: 'Error while executing post user created event', err: e }); }); } diff --git a/apps/meteor/app/custom-oauth/server/custom_oauth_server.js b/apps/meteor/app/custom-oauth/server/custom_oauth_server.js index f25405c8b14a0..b9071709f2cce 100644 --- a/apps/meteor/app/custom-oauth/server/custom_oauth_server.js +++ b/apps/meteor/app/custom-oauth/server/custom_oauth_server.js @@ -25,7 +25,7 @@ const BeforeUpdateOrCreateUserFromExternalService = []; export class CustomOAuth { constructor(name, options) { - logger.debug('Init CustomOAuth', name, options); + logger.debug({ msg: 'Init CustomOAuth', name, options }); this.name = name; if (!Match.test(this.name, String)) { @@ -307,7 +307,7 @@ export class CustomOAuth { const value = fromTemplate(this.avatarField, data); if (!value) { - logger.debug(`Avatar field "${this.avatarField}" not found in data`, data); + logger.debug({ msg: 'Avatar field not found in data', avatarField: this.avatarField, data }); } return value; } catch (error) { diff --git a/apps/meteor/app/irc/server/irc-bridge/index.js b/apps/meteor/app/irc/server/irc-bridge/index.js index b86dff943e45f..25f6b5b9f0a29 100644 --- a/apps/meteor/app/irc/server/irc-bridge/index.js +++ b/apps/meteor/app/irc/server/irc-bridge/index.js @@ -135,7 +135,7 @@ class Bridge { // Get the command const item = this.queue.dequeue(); - this.logQueue(`Processing "${item.command}" command from "${item.from}"`); + this.logQueue({ msg: 'Processing command from source', command: item.command, from: item.from }); // Handle the command accordingly try { diff --git a/apps/meteor/app/irc/server/servers/RFC2813/index.js b/apps/meteor/app/irc/server/servers/RFC2813/index.js index 8c5b8abf19c84..531338d939827 100644 --- a/apps/meteor/app/irc/server/servers/RFC2813/index.js +++ b/apps/meteor/app/irc/server/servers/RFC2813/index.js @@ -39,9 +39,9 @@ class RFC2813 { this.socket.on('data', this.onReceiveFromPeer.bind(this)); this.socket.on('connect', this.onConnect.bind(this)); - this.socket.on('error', (err) => logger.error(err)); - this.socket.on('timeout', () => this.log('Timeout')); - this.socket.on('close', () => this.log('Connection Closed')); + this.socket.on('error', (err) => logger.error({ msg: 'Socket error', err })); + this.socket.on('timeout', () => this.log({ msg: 'Timeout' })); + this.socket.on('close', () => this.log({ msg: 'Connection Closed' })); // Setup local this.on('onReceiveFromLocal', this.onReceiveFromLocal.bind(this)); } @@ -51,6 +51,11 @@ class RFC2813 { */ log(message) { // TODO logger: debug? + if (typeof message === 'string') { + logger.info({ msg: message }); + return; + } + logger.info(message); } @@ -58,7 +63,11 @@ class RFC2813 { * Connect */ register() { - this.log(`Connecting to @${this.config.server.host}:${this.config.server.port}`); + this.log({ + msg: 'Connecting to IRC server', + host: this.config.server.host, + port: this.config.server.port, + }); if (!this.socket) { this.setupSocket(); @@ -114,7 +123,7 @@ class RFC2813 { buffer += ` :${command.trailer}`; } - this.log(`Sending Command: ${buffer}`); + this.log({ msg: 'Sending Command', buffer }); return this.socket.write(`${buffer}\r\n`); } @@ -148,7 +157,7 @@ class RFC2813 { const parsedMessage = parseMessage(line); if (peerCommandHandlers[parsedMessage.command]) { - this.log(`Handling peer message: ${line}`); + this.log({ msg: 'Handling peer message', line }); const command = peerCommandHandlers[parsedMessage.command].call(this, parsedMessage); @@ -172,7 +181,7 @@ class RFC2813 { */ onReceiveFromLocal(command, parameters) { if (localCommandHandlers[command]) { - this.log(`Handling local command: ${command}`); + this.log({ msg: 'Handling local command', command }); localCommandHandlers[command].call(this, parameters, this); } else { diff --git a/apps/meteor/app/slackbridge/server/RocketAdapter.js b/apps/meteor/app/slackbridge/server/RocketAdapter.js index 17fce65133090..624d4a72de068 100644 --- a/apps/meteor/app/slackbridge/server/RocketAdapter.js +++ b/apps/meteor/app/slackbridge/server/RocketAdapter.js @@ -65,7 +65,7 @@ export default class RocketAdapter { continue; } - rocketLogger.debug('onRocketMessageDelete', rocketMessageDeleted); + rocketLogger.debug({ msg: 'onRocketMessageDelete', rocketMessageDeleted }); await slack.postDeleteMessage(rocketMessageDeleted); } catch (err) { rocketLogger.error({ msg: 'Unhandled error onMessageDelete', err }); @@ -137,7 +137,7 @@ export default class RocketAdapter { // This is on a channel that the rocket bot is not subscribed continue; } - rocketLogger.debug('onRocketMessage', rocketMessage); + rocketLogger.debug({ msg: 'onRocketMessage', rocketMessage }); if (rocketMessage.editedAt) { // This is an Edit Event @@ -260,7 +260,7 @@ export default class RocketAdapter { } async addChannel(slackChannelID, hasRetried = false) { - rocketLogger.debug('Adding Rocket.Chat channel from Slack', slackChannelID); + rocketLogger.debug({ msg: 'Adding Rocket.Chat channel from Slack', slackChannelID }); let addedRoom; for await (const slack of this.slackAdapters) { @@ -296,12 +296,12 @@ export default class RocketAdapter { slackChannel.rocketId = rocketChannel.rid; } catch (e) { if (!hasRetried) { - rocketLogger.debug('Error adding channel from Slack. Will retry in 1s.', e.message); + rocketLogger.debug({ msg: 'Error adding channel from Slack. Will retry in 1s.', err: e }); // If first time trying to create channel fails, could be because of multiple messages received at the same time. Try again once after 1s. await sleep(1000); return (await this.findChannel(slackChannelID)) || this.addChannel(slackChannelID, true); } - rocketLogger.error(e); + rocketLogger.error({ msg: 'Error adding channel from Slack', err: e }); } const roomUpdate = { diff --git a/apps/meteor/client/views/room/body/RoomBody.tsx b/apps/meteor/client/views/room/body/RoomBody.tsx index 8e5bd8da996ef..6a9a325f1711f 100644 --- a/apps/meteor/client/views/room/body/RoomBody.tsx +++ b/apps/meteor/client/views/room/body/RoomBody.tsx @@ -274,7 +274,7 @@ const RoomBody = (): ReactElement => { - + { - + = targetVersion) { upgradeToV7Date = new Date(stat.installedAt); - this._rocketchatLogger.info(`Found upgrade to v${targetVersion} date: ${upgradeToV7Date.toISOString()}`); + this._rocketchatLogger.info({ + msg: 'Found upgrade to target version date', + targetVersion, + upgradeToDate: upgradeToV7Date.toISOString(), + }); break; } } - } catch (error) { - this._rocketchatLogger.error('Error checking statistics for version history:', error.message); + } catch (err) { + this._rocketchatLogger.error({ + msg: 'Error checking statistics for version history', + err, + }); } return upgradeToV7Date; @@ -300,11 +314,17 @@ export class AppServerOrchestrator { try { await Promise.all(disablePromises); - this._rocketchatLogger.info( - `${installationSource} apps processing complete - kept ${grandfathered.length + toKeep.length}, disabled ${toDisable.length}`, - ); + this._rocketchatLogger.info({ + msg: 'Apps processing complete', + installationSource, + keptCount: grandfathered.length + toKeep.length, + disabledCount: toDisable.length, + }); } catch (error) { - this._rocketchatLogger.error('Error disabling apps:', error.message); + this._rocketchatLogger.error({ + msg: 'Error disabling apps', + err: error, + }); } } @@ -318,7 +338,12 @@ export class AppServerOrchestrator { return this._manager .unload() .then(() => this._rocketchatLogger.info('Unloaded the Apps Framework.')) - .catch((err) => this._rocketchatLogger.error({ msg: 'Failed to unload the Apps Framework!', err })); + .catch((err) => + this._rocketchatLogger.error({ + msg: 'Failed to unload the Apps Framework!', + err, + }), + ); } async updateAppsMarketplaceInfo(apps = []) { diff --git a/apps/meteor/server/services/apps-engine/service.ts b/apps/meteor/server/services/apps-engine/service.ts index 3f441fbea2f1f..0be60a579908d 100644 --- a/apps/meteor/server/services/apps-engine/service.ts +++ b/apps/meteor/server/services/apps-engine/service.ts @@ -31,12 +31,18 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi }); this.onEvent('apps.added', async (appId: string): Promise => { - Apps.self?.getRocketChatLogger().debug(`"apps.added" event received for app "${appId}"`); + Apps.self?.getRocketChatLogger().debug({ + msg: '"apps.added" event received for app', + appId, + }); // if the app already exists in this instance, don't load it again const app = Apps.self?.getManager()?.getOneById(appId); if (app) { - Apps.self?.getRocketChatLogger().info(`"apps.added" event received for app "${appId}", but it already exists in this instance`); + Apps.self?.getRocketChatLogger().info({ + msg: '"apps.added" event received for app, but it already exists in this instance', + appId, + }); return; } @@ -44,12 +50,16 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi }); this.onEvent('apps.removed', async (appId: string): Promise => { - Apps.self?.getRocketChatLogger().debug(`"apps.removed" event received for app "${appId}"`); + Apps.self?.getRocketChatLogger().debug({ + msg: '"apps.removed" event received for app', + appId, + }); const app = Apps.self?.getManager()?.getOneById(appId); if (!app) { - Apps.self - ?.getRocketChatLogger() - .info(`"apps.removed" event received for app "${appId}", but it couldn't be found in this instance`); + Apps.self?.getRocketChatLogger().info({ + msg: '"apps.removed" event received for app, but it could not be found in this instance', + appId, + }); return; } @@ -57,10 +67,16 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi }); this.onEvent('apps.updated', async (appId: string): Promise => { - Apps.self?.getRocketChatLogger().debug(`"apps.updated" event received for app "${appId}"`); + Apps.self?.getRocketChatLogger().debug({ + msg: '"apps.updated" event received for app', + appId, + }); const storageItem = await Apps.self?.getStorage()?.retrieveOne(appId); if (!storageItem) { - Apps.self?.getRocketChatLogger().info(`"apps.updated" event received for app "${appId}", but it couldn't be found in the storage`); + Apps.self?.getRocketChatLogger().info({ + msg: '"apps.updated" event received for app, but it could not be found in the storage', + appId, + }); return; } @@ -78,17 +94,27 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi }); this.onEvent('apps.statusUpdate', async (appId: string, status: AppStatus): Promise => { - Apps.self?.getRocketChatLogger().debug(`"apps.statusUpdate" event received for app "${appId}" with status "${status}"`); + Apps.self?.getRocketChatLogger().debug({ + msg: '"apps.statusUpdate" event received for app with status', + appId, + status, + }); const app = Apps.self?.getManager()?.getOneById(appId); if (!app) { - Apps.self - ?.getRocketChatLogger() - .info(`"apps.statusUpdate" event received for app "${appId}", but it couldn't be found in this instance`); + Apps.self?.getRocketChatLogger().info({ + msg: '"apps.statusUpdate" event received for app, but it could not be found in this instance', + appId, + status, + }); return; } if ((await app.getStatus()) === status) { - Apps.self?.getRocketChatLogger().info(`"apps.statusUpdate" event received for app "${appId}", but the status is the same`); + Apps.self?.getRocketChatLogger().info({ + msg: '"apps.statusUpdate" event received for app, but the status is the same', + appId, + status, + }); return; } @@ -100,7 +126,11 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi }); this.onEvent('apps.settingUpdated', async (appId: string, setting): Promise => { - Apps.self?.getRocketChatLogger().debug(`"apps.settingUpdated" event received for app "${appId}"`, { setting }); + Apps.self?.getRocketChatLogger().debug({ + msg: '"apps.settingUpdated" event received for app', + appId, + setting, + }); const app = Apps.self?.getManager()?.getOneById(appId); const oldSetting = app?.getStorageItem().settings[setting.id].value; @@ -110,9 +140,11 @@ export class AppsEngineService extends ServiceClassInternal implements IAppsEngi // so we need to convert it to JSON stringified to compare it if (JSON.stringify(oldSetting) === JSON.stringify(setting.value)) { - Apps.self - ?.getRocketChatLogger() - .info(`"apps.settingUpdated" event received for setting ${setting.id} of app "${appId}", but the setting value is the same`); + Apps.self?.getRocketChatLogger().info({ + msg: '"apps.settingUpdated" event received for app, but the setting value is the same', + appId, + settingId: setting.id, + }); return; } diff --git a/apps/meteor/tests/e2e/channel-management.spec.ts b/apps/meteor/tests/e2e/channel-management.spec.ts index be61f83e2e649..bd76bafb4ec16 100644 --- a/apps/meteor/tests/e2e/channel-management.spec.ts +++ b/apps/meteor/tests/e2e/channel-management.spec.ts @@ -145,7 +145,7 @@ test.describe.serial('channel-management', () => { test('should create a discussion using the message composer', async ({ page }) => { discussionName = faker.string.uuid(); await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.content.btnMenuMoreActions.click(); + await poHomeChannel.composer.btnMenuMoreActions.click(); await page.getByRole('menuitem', { name: 'Discussion' }).click(); await poHomeChannel.content.inputDiscussionName.fill(discussionName); await poHomeChannel.content.btnCreateDiscussionModal.click(); @@ -196,7 +196,7 @@ test.describe.serial('channel-management', () => { const user1Channel = new HomeChannel(user1Page); await user1Page.goto(`/channel/${targetChannel}`); await user1Channel.content.waitForChannel(); - await expect(user1Channel.readOnlyFooter).toBeVisible(); + await expect(user1Channel.composer.readOnlyFooter).toBeVisible(); }); test('should unmuteUser user1', async () => { @@ -210,7 +210,7 @@ test.describe.serial('channel-management', () => { const user1Channel = new HomeChannel(user1Page); await user1Page.goto(`/channel/${targetChannel}`); await user1Channel.content.waitForChannel(); - await expect(user1Channel.composer).toBeVisible(); + await expect(user1Channel.composer.inputMessage).toBeVisible(); }); test('should set user1 as moderator', async () => { diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts index 1ebcd2e7068a1..4e5708d56aa5d 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-encrypted-channels.spec.ts @@ -345,7 +345,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.openLastMessageMenu(); await poHomeChannel.content.btnOptionEditMessage.click(); - await poHomeChannel.content.inputMessage.fill(editedMessage); + await poHomeChannel.composer.inputMessage.fill(editedMessage); await page.keyboard.press('Enter'); @@ -369,7 +369,7 @@ test.describe('E2EE Encrypted Channels', () => { await poHomeChannel.content.openLastMessageMenu(); await poHomeChannel.content.btnOptionEditMessage.click(); - await poHomeChannel.content.inputMessage.fill(editedMessage); + await poHomeChannel.composer.inputMessage.fill(editedMessage); await page.keyboard.press('Enter'); diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts index 4f6b77b883b39..f32a7bd028e18 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-file-encryption.spec.ts @@ -64,9 +64,9 @@ test.describe('E2EE File Encryption', () => { await poHomeChannel.content.openLastMessageMenu(); await poHomeChannel.content.btnOptionEditMessage.click(); - expect(await poHomeChannel.composer.inputValue()).toBe('any_description'); + expect(await poHomeChannel.composer.inputMessage.inputValue()).toBe('any_description'); - await poHomeChannel.content.inputMessage.fill('edited any_description'); + await poHomeChannel.composer.inputMessage.fill('edited any_description'); await page.keyboard.press('Enter'); await expect(poHomeChannel.content.getFileDescription).toHaveText('edited any_description'); diff --git a/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts b/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts index dd5f1e8f00e71..1e6ae7b9a957c 100644 --- a/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts +++ b/apps/meteor/tests/e2e/e2e-encryption/e2ee-passphrase-management.spec.ts @@ -228,7 +228,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await expect(poHomeChannel.roomToolbar.btnMembers).toBeVisible(); await expect(poHomeChannel.roomToolbar.btnRoomInfo).toBeVisible(); - await expect(poHomeChannel.content.inputMessage).not.toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).not.toBeVisible(); await poHomeChannel.btnRoomSaveE2EEPassword.click(); @@ -239,7 +239,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await poHomeChannel.btnSavedMyPassword.click(); - await poHomeChannel.content.inputMessage.waitFor(); + await poHomeChannel.composer.inputMessage.waitFor(); await poHomeChannel.content.sendMessage('hello world'); @@ -273,7 +273,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await expect(poHomeChannel.roomToolbar.btnMembers).toBeVisible(); await expect(poHomeChannel.roomToolbar.btnRoomInfo).toBeVisible(); - await expect(poHomeChannel.content.inputMessage).not.toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).not.toBeVisible(); await poHomeChannel.btnRoomEnterE2EEPassword.click(); @@ -283,7 +283,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await expect(poHomeChannel.bannerEnterE2EEPassword).not.toBeVisible(); - await poHomeChannel.content.inputMessage.waitFor(); + await poHomeChannel.composer.inputMessage.waitFor(); // For E2EE to complete init setup await page.waitForTimeout(300); @@ -334,7 +334,7 @@ test.describe.serial('E2EE Passphrase Management - Room Setup States', () => { await poHomeChannel.btnRoomSaveE2EEPassword.click(); await poHomeChannel.btnSavedMyPassword.click(); - await expect(poHomeChannel.content.inputMessage).not.toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).not.toBeVisible(); await expect(page.locator('.rcx-states__title')).toContainText('Check back later'); await poHomeChannel.roomToolbar.btnDisableE2EEncryption.waitFor(); diff --git a/apps/meteor/tests/e2e/embedded-layout.spec.ts b/apps/meteor/tests/e2e/embedded-layout.spec.ts index 648eefa4d4ec9..c834d96c17da8 100644 --- a/apps/meteor/tests/e2e/embedded-layout.spec.ts +++ b/apps/meteor/tests/e2e/embedded-layout.spec.ts @@ -65,9 +65,9 @@ test.describe('embedded-layout', () => { await poHomeChannel.navbar.openChat(targetChannelId); await page.goto(embeddedLayoutURL(page.url())); - await expect(poHomeChannel.composer).toBeVisible(); - await expect(poHomeChannel.composer).toBeEnabled(); - await expect(poHomeChannel.btnJoinRoom).not.toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).toBeEnabled(); + await expect(poHomeChannel.composer.btnJoinRoom).not.toBeVisible(); }); test('should allow sending and receiving messages', async ({ page }) => { @@ -85,14 +85,14 @@ test.describe('embedded-layout', () => { await poHomeChannel.navbar.openChat(targetChannelId); await page.goto(embeddedLayoutURL(page.url())); - await expect(poHomeChannel.composer).toBeVisible(); - await expect(poHomeChannel.composerToolbar).toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).toBeVisible(); + await expect(poHomeChannel.composer.toolbarPrimaryActions).toBeVisible(); - await poHomeChannel.composer.fill('Test message'); - await expect(poHomeChannel.composer).toHaveValue('Test message'); + await poHomeChannel.composer.inputMessage.fill('Test message'); + await expect(poHomeChannel.composer.inputMessage).toHaveValue('Test message'); - await poHomeChannel.composer.fill(''); - await expect(poHomeChannel.composer).toHaveValue(''); + await poHomeChannel.composer.inputMessage.fill(''); + await expect(poHomeChannel.composer.inputMessage).toHaveValue(''); }); }); @@ -102,8 +102,8 @@ test.describe('embedded-layout', () => { await poHomeChannel.navbar.openChat(notMemberChannelId); await page.goto(embeddedLayoutURL(page.url())); - await expect(poHomeChannel.composer).toBeDisabled(); - await expect(poHomeChannel.btnJoinRoom).toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).toBeDisabled(); + await expect(poHomeChannel.composer.btnJoinRoom).toBeVisible(); }); test('should allow joining channel and enable messaging', async ({ page }) => { @@ -111,11 +111,11 @@ test.describe('embedded-layout', () => { await poHomeChannel.navbar.openChat(joinChannelId); await page.goto(embeddedLayoutURL(page.url())); - await poHomeChannel.btnJoinRoom.click(); + await poHomeChannel.composer.btnJoinRoom.click(); - await expect(poHomeChannel.btnJoinRoom).not.toBeVisible(); - await expect(poHomeChannel.composer).toBeVisible(); - await expect(poHomeChannel.composer).toBeEnabled(); + await expect(poHomeChannel.composer.btnJoinRoom).not.toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).toBeEnabled(); const joinMessage = `Joined and sent message ${Date.now()}`; await poHomeChannel.content.sendMessage(joinMessage); @@ -130,9 +130,9 @@ test.describe('embedded-layout', () => { await poHomeChannel.navbar.openChat(Users.user2.data.username); await page.goto(embeddedLayoutURL(page.url())); - await expect(poHomeChannel.composer).toBeVisible(); - await expect(poHomeChannel.composer).toBeEnabled(); - await expect(poHomeChannel.btnJoinRoom).not.toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).toBeEnabled(); + await expect(poHomeChannel.composer.btnJoinRoom).not.toBeVisible(); const dmMessage = `Embedded DM test ${Date.now()}`; await poHomeChannel.content.sendMessage(dmMessage); diff --git a/apps/meteor/tests/e2e/emojis.spec.ts b/apps/meteor/tests/e2e/emojis.spec.ts index 34ad63a1f6120..6f0c99284c525 100644 --- a/apps/meteor/tests/e2e/emojis.spec.ts +++ b/apps/meteor/tests/e2e/emojis.spec.ts @@ -22,22 +22,23 @@ test.describe.serial('emoji', () => { test('should display emoji picker properly', async ({ page }) => { await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.content.btnComposerEmoji.click(); + await poHomeChannel.composer.btnEmoji.click(); await test.step('should display scroller', async () => { - await expect(poHomeChannel.content.scrollerEmojiPicker).toBeVisible(); + await expect(poHomeChannel.scrollerEmojiPicker).toBeVisible(); }); await test.step('should focus the active emoji tab category', async () => { - const activityEmojiTab = poHomeChannel.content.getEmojiPickerTabByName('Activity'); + const activityEmojiTab = poHomeChannel.getEmojiPickerTabByName('Activity'); await activityEmojiTab.click(); await expect(activityEmojiTab).toBeFocused(); + await poHomeChannel.composer.inputMessage.click(); // To close the emoji picker }); await test.step('should pick and send grinning emoji', async () => { await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.content.pickEmoji('grinning'); + await poHomeChannel.pickEmoji('grinning'); await page.keyboard.press('Enter'); await expect(poHomeChannel.content.lastUserMessage).toContainText('😀'); diff --git a/apps/meteor/tests/e2e/feature-preview.spec.ts b/apps/meteor/tests/e2e/feature-preview.spec.ts index 840575c5df67b..b0481e8cfdd18 100644 --- a/apps/meteor/tests/e2e/feature-preview.spec.ts +++ b/apps/meteor/tests/e2e/feature-preview.spec.ts @@ -259,7 +259,7 @@ test.describe.serial('feature preview', () => { const discussionName = faker.string.uuid(); - await poHomeChannel.content.btnMenuMoreActions.click(); + await poHomeChannel.composer.btnMenuMoreActions.click(); await page.getByRole('menuitem', { name: 'Discussion' }).click(); await poHomeChannel.content.inputDiscussionName.fill(discussionName); await poHomeChannel.content.btnCreateDiscussionModal.click(); @@ -585,7 +585,7 @@ test.describe.serial('feature preview', () => { }); await test.step('create discussion in DM', async () => { - await poHomeChannel.content.btnMenuMoreActions.click(); + await poHomeChannel.composer.btnMenuMoreActions.click(); await page.getByRole('menuitem', { name: 'Discussion' }).click(); await poHomeChannel.content.inputDiscussionName.fill(discussionName); await poHomeChannel.content.btnCreateDiscussionModal.click(); diff --git a/apps/meteor/tests/e2e/image-gallery.spec.ts b/apps/meteor/tests/e2e/image-gallery.spec.ts index e7e0171880e59..34a84cab458e1 100644 --- a/apps/meteor/tests/e2e/image-gallery.spec.ts +++ b/apps/meteor/tests/e2e/image-gallery.spec.ts @@ -24,10 +24,10 @@ test.describe.serial('Image Gallery', async () => { poHomeChannel = new HomeChannel(page); await poHomeChannel.navbar.openChat(targetChannelLargeImage); - await poHomeChannel.content.btnJoinRoom.click(); + await poHomeChannel.composer.btnJoinRoom.click(); await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.content.btnJoinRoom.click(); + await poHomeChannel.composer.btnJoinRoom.click(); }); test.afterAll(async ({ api }) => { diff --git a/apps/meteor/tests/e2e/message-composer.spec.ts b/apps/meteor/tests/e2e/message-composer.spec.ts index 9819bc5646088..14d700e5f21d0 100644 --- a/apps/meteor/tests/e2e/message-composer.spec.ts +++ b/apps/meteor/tests/e2e/message-composer.spec.ts @@ -25,14 +25,14 @@ test.describe.serial('message-composer', () => { await poHomeChannel.navbar.openChat(targetChannel); await poHomeChannel.content.sendMessage('hello composer'); - await expect(poHomeChannel.composerToolbarActions).toHaveCount(12); + await expect(poHomeChannel.composer.allPrimaryActions).toHaveCount(12); }); test('should have only the main formatter and the main action', async ({ page }) => { await page.setViewportSize({ width: 768, height: 600 }); await poHomeChannel.navbar.openChat(targetChannel); - await expect(poHomeChannel.composerToolbarActions).toHaveCount(6); + await expect(poHomeChannel.composer.allPrimaryActions).toHaveCount(6); }); test('should navigate on toolbar using arrow keys', async ({ page }) => { @@ -41,10 +41,10 @@ test.describe.serial('message-composer', () => { await page.keyboard.press('Tab'); await page.keyboard.press('ArrowRight'); await page.keyboard.press('ArrowRight'); - await expect(poHomeChannel.composerToolbar.getByRole('button', { name: 'Italic' })).toBeFocused(); + await expect(poHomeChannel.composer.btnItalicFormatter).toBeFocused(); await page.keyboard.press('ArrowLeft'); - await expect(poHomeChannel.composerToolbar.getByRole('button', { name: 'Bold' })).toBeFocused(); + await expect(poHomeChannel.composer.btnBoldFormatter).toBeFocused(); }); test('should move the focus away from toolbar using tab key', async ({ page }) => { @@ -53,7 +53,7 @@ test.describe.serial('message-composer', () => { await page.keyboard.press('Tab'); await page.keyboard.press('Tab'); - await expect(poHomeChannel.composerToolbar.getByRole('button', { name: 'Emoji' })).not.toBeFocused(); + await expect(poHomeChannel.composer.btnEmoji).not.toBeFocused(); }); test('should add a link to the selected text', async ({ page }) => { @@ -63,11 +63,11 @@ test.describe.serial('message-composer', () => { await page.keyboard.type('hello composer'); await page.keyboard.press('Control+A'); // on Windows and Linux await page.keyboard.press('Meta+A'); // on macOS - await poHomeChannel.composerToolbar.getByRole('button', { name: 'Link' }).click(); + await poHomeChannel.composer.btnLinkFormatter.click(); await page.keyboard.type(url); await page.keyboard.press('Enter'); - await expect(poHomeChannel.composer).toHaveValue(`[hello composer](${url})`); + await expect(poHomeChannel.composer.inputMessage).toHaveValue(`[hello composer](${url})`); }); test('should select popup item and not send the message when pressing enter', async ({ page }) => { @@ -79,9 +79,9 @@ test.describe.serial('message-composer', () => { await page.keyboard.press('Enter'); - await expect(poHomeChannel.composer).toHaveValue('hello composer @all '); + await expect(poHomeChannel.composer.inputMessage).toHaveValue('hello composer @all '); - await poHomeChannel.composer.fill(''); + await poHomeChannel.composer.inputMessage.fill(''); }); await test.step('emoji popup', async () => { @@ -89,9 +89,9 @@ test.describe.serial('message-composer', () => { await page.keyboard.press('Enter'); - await expect(poHomeChannel.composer).toHaveValue('hello composer :flag_br: '); + await expect(poHomeChannel.composer.inputMessage).toHaveValue('hello composer :flag_br: '); - await poHomeChannel.composer.fill(''); + await poHomeChannel.composer.inputMessage.fill(''); }); await test.step('slash command', async () => { @@ -99,9 +99,9 @@ test.describe.serial('message-composer', () => { await page.keyboard.press('Enter'); - await expect(poHomeChannel.composer).toHaveValue('/gimme '); + await expect(poHomeChannel.composer.inputMessage).toHaveValue('/gimme '); - await poHomeChannel.composer.fill(''); + await poHomeChannel.composer.inputMessage.fill(''); }); }); @@ -112,21 +112,21 @@ test.describe.serial('message-composer', () => { await test.step('mention popup', async () => { await page.keyboard.type('hello composer @rocket.cat'); - await expect(poHomeChannel.composerBoxPopup.getByText('rocket.cat')).toBeVisible(); + await expect(poHomeChannel.composer.boxPopup.getByText('rocket.cat')).toBeVisible(); }); }); test.describe('audio recorder', () => { test('should open audio recorder', async () => { await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.composerToolbar.getByRole('button', { name: 'Audio message', exact: true }).click(); + await poHomeChannel.composer.btnAudioMessage.click(); await expect(poHomeChannel.audioRecorder).toBeVisible(); }); test('should stop recording when clicking on cancel', async () => { await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.composerToolbar.getByRole('button', { name: 'Audio message', exact: true }).click(); + await poHomeChannel.composer.btnAudioMessage.click(); await expect(poHomeChannel.audioRecorder).toBeVisible(); await poHomeChannel.audioRecorder.getByRole('button', { name: 'Cancel recording', exact: true }).click(); @@ -135,7 +135,7 @@ test.describe.serial('message-composer', () => { test('should open file modal when clicking on "Finish recording"', async ({ page }) => { await poHomeChannel.navbar.openChat(targetChannel); - await poHomeChannel.composerToolbar.getByRole('button', { name: 'Audio message', exact: true }).click(); + await poHomeChannel.composer.btnAudioMessage.click(); await expect(poHomeChannel.audioRecorder).toBeVisible(); await page.waitForTimeout(1000); diff --git a/apps/meteor/tests/e2e/message-mentions.spec.ts b/apps/meteor/tests/e2e/message-mentions.spec.ts index 9780572dde7ba..87ca04206bad3 100644 --- a/apps/meteor/tests/e2e/message-mentions.spec.ts +++ b/apps/meteor/tests/e2e/message-mentions.spec.ts @@ -109,7 +109,7 @@ test.describe.serial('message-mentions', () => { test('expect show "all" and "here" options', async () => { await poHomeChannel.navbar.openChat('general'); - await poHomeChannel.content.inputMessage.type('@'); + await poHomeChannel.composer.inputMessage.type('@'); await expect(poHomeChannel.content.messagePopupUsers.locator('role=listitem >> text="all"')).toBeVisible(); await expect(poHomeChannel.content.messagePopupUsers.locator('role=listitem >> text="here"')).toBeVisible(); diff --git a/apps/meteor/tests/e2e/messaging.spec.ts b/apps/meteor/tests/e2e/messaging.spec.ts index 74cffb18fb6bc..c6b781aaa2fca 100644 --- a/apps/meteor/tests/e2e/messaging.spec.ts +++ b/apps/meteor/tests/e2e/messaging.spec.ts @@ -87,7 +87,7 @@ test.describe('Messaging', () => { .waitFor(); await page.keyboard.press('Tab'); await page.keyboard.press('Tab'); - await expect(poHomeChannel.composer).toBeFocused(); + await expect(poHomeChannel.composer.inputMessage).toBeFocused(); }); }); @@ -124,7 +124,7 @@ test.describe('Messaging', () => { test('should not restore focus on the last focused if it was triggered by click', async ({ page }) => { await poHomeChannel.navbar.openChat(targetChannel); await page.locator('[data-qa-type="message"]:has-text("msg1")').click(); - await poHomeChannel.composer.click(); + await poHomeChannel.composer.inputMessage.click(); await page.keyboard.press('Shift+Tab'); await expect(page.locator('[data-qa-type="message"]:has-text("msg2")')).toBeFocused(); @@ -165,7 +165,7 @@ test.describe('Messaging', () => { await test.step('focus on the second message', async () => { await page.keyboard.press('ArrowUp'); - expect(await poHomeChannel.composer.inputValue()).toBe('msg2'); + expect(await poHomeChannel.composer.inputMessage.inputValue()).toBe('msg2'); }); await test.step('send edited message', async () => { diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-auto-onhold-chat-closing.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-auto-onhold-chat-closing.spec.ts index e8fb0caa49f6b..56875ec87f0dc 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-auto-onhold-chat-closing.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-auto-onhold-chat-closing.spec.ts @@ -64,7 +64,7 @@ test.describe('omnichannel-auto-onhold-chat-closing', () => { await expect(agent.poHomeChannel.content.lastSystemMessageBody).toHaveText( `Chat On Hold: The chat was manually placed On Hold by user1`, ); - await expect(agent.poHomeChannel.content.inputMessage).not.toBeVisible(); + await expect(agent.poHomeChannel.composer.inputMessage).not.toBeVisible(); await expect(agent.poHomeChannel.content.resumeOnHoldOmnichannelChatButton).toBeVisible(); // current url diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-canned-responses-usage.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-canned-responses-usage.spec.ts index 9ece2ff55f997..15daec85c8070 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-canned-responses-usage.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-canned-responses-usage.spec.ts @@ -107,7 +107,7 @@ test.describe('OC - Canned Responses Usage', () => { }); await test.step('expect canned response text to appear in message composer', async () => { - await expect(agent.poHomeChannel.content.inputMessage).toHaveValue(`${cannedResponseText} `); + await expect(agent.poHomeChannel.composer.inputMessage).toHaveValue(`${cannedResponseText} `); }); await test.step('expect agent to be able to send the canned response message', async () => { @@ -162,11 +162,11 @@ test.describe('OC - Canned Responses Usage', () => { }); await test.step('expect to modify the canned response text before sending', async () => { - await agent.poHomeChannel.content.inputMessage.click(); + await agent.poHomeChannel.composer.inputMessage.click(); await agent.page.keyboard.press('End'); - await agent.poHomeChannel.content.inputMessage.pressSequentially(modifiedText); + await agent.poHomeChannel.composer.inputMessage.pressSequentially(modifiedText); - await expect(agent.poHomeChannel.content.inputMessage).toHaveValue(`${cannedResponseText} ${modifiedText}`); + await expect(agent.poHomeChannel.composer.inputMessage).toHaveValue(`${cannedResponseText} ${modifiedText}`); }); await test.step('expect to send the modified message', async () => { @@ -193,13 +193,13 @@ test.describe('OC - Canned Responses Usage', () => { await test.step('expect to use first canned response', async () => { await agent.poHomeChannel.content.useCannedResponse(cannedResponseName); - await expect(agent.poHomeChannel.content.inputMessage).toHaveValue(`${cannedResponseText} `); + await expect(agent.poHomeChannel.composer.inputMessage).toHaveValue(`${cannedResponseText} `); await agent.page.keyboard.press('Enter'); }); await test.step('expect to use second canned response', async () => { await agent.poHomeChannel.content.useCannedResponse(secondResponseName); - await expect(agent.poHomeChannel.content.inputMessage).toHaveValue(`${secondResponseText} `); + await expect(agent.poHomeChannel.composer.inputMessage).toHaveValue(`${secondResponseText} `); await agent.page.keyboard.press('Enter'); }); diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts index 96bb00336be0c..3e46bfc04960b 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-contact-center-chats.spec.ts @@ -3,7 +3,7 @@ import type { Page } from '@playwright/test'; import { IS_EE } from '../config/constants'; import { Users } from '../fixtures/userStates'; -import { OmnichannelChats } from '../page-objects'; +import { HomeOmnichannel, OmnichannelChats } from '../page-objects'; import { createAgent, makeAgentAvailable } from '../utils/omnichannel/agents'; import { addAgentToDepartment, createDepartment } from '../utils/omnichannel/departments'; import { createConversation, updateRoom } from '../utils/omnichannel/rooms'; @@ -20,6 +20,7 @@ test.use({ storageState: Users.admin.state }); test.describe('OC - Contact Center Chats [Auto Selection]', async () => { let poOmnichats: OmnichannelChats; + let poHomeOmnichannel: HomeOmnichannel; let departments: Awaited>[]; let conversations: Awaited>[]; let agents: Awaited>[]; @@ -151,13 +152,15 @@ test.describe('OC - Contact Center Chats [Auto Selection]', async () => { }); }); - test('OC - Contact Center Chats - Access in progress conversation from another agent', async () => { + test('OC - Contact Center Chats - Access in progress conversation from another agent', async ({ page }) => { + poHomeOmnichannel = new HomeOmnichannel(page); + await test.step('expect to be able to join', async () => { const { visitor: visitorB } = conversations[1].data; await poOmnichats.openChat(visitorB.name); - await expect(poOmnichats.content.btnJoinRoom).toBeVisible(); - await poOmnichats.content.btnJoinRoom.click(); - await expect(poOmnichats.content.btnJoinRoom).not.toBeVisible(); + await expect(poHomeOmnichannel.composer.btnJoinRoom).toBeVisible(); + await poHomeOmnichannel.composer.btnJoinRoom.click(); + await expect(poHomeOmnichannel.composer.btnJoinRoom).not.toBeVisible(); }); }); diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-manager-role.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-manager-role.spec.ts index b6972f52745e3..5df8a4218ab18 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-manager-role.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-manager-role.spec.ts @@ -121,13 +121,13 @@ test.describe('OC - Manager Role', () => { await test.step('expect to be able to join chats', async () => { await poOmnichannel.chats.openChat(ROOM_A); - await expect(poOmnichannel.content.btnJoinRoom).toBeVisible(); - await expect(poOmnichannel.content.inputMessage).not.toBeVisible(); + await expect(poOmnichannel.composer.btnJoinRoom).toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).not.toBeVisible(); - await poOmnichannel.content.btnJoinRoom.click(); + await poOmnichannel.composer.btnJoinRoom.click(); await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel'); - await expect(poOmnichannel.content.btnJoinRoom).not.toBeVisible(); - await expect(poOmnichannel.content.inputMessage).toBeVisible(); + await expect(poOmnichannel.composer.btnJoinRoom).not.toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).toBeVisible(); }); await test.step('expect to be able to put a conversation from another agent on hold', async () => { @@ -135,14 +135,14 @@ test.describe('OC - Manager Role', () => { await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText( `Chat On Hold: The chat was manually placed On Hold by ${MANAGER}`, ); - await expect(poOmnichannel.content.inputMessage).not.toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).not.toBeVisible(); await expect(poOmnichannel.content.btnResume).toBeVisible(); }); await test.step('expect to be able resume a conversation from another agent on hold', async () => { await poOmnichannel.content.btnResume.click(); await expect(poOmnichannel.content.btnResume).not.toBeVisible(); - await expect(poOmnichannel.content.inputMessage).toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).toBeVisible(); await expect(poOmnichannel.quickActionsRoomToolbar.btnOnHold).toBeVisible(); }); diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection-logout.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection-logout.spec.ts index f62ed89b20042..28d0c4be2ffa1 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection-logout.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection-logout.spec.ts @@ -56,7 +56,7 @@ test.describe('OC - Manual Selection After Relogin', () => { await test.step('expect login and see the chat in queue after login', async () => { await poOmnichannel.sidebar.getSidebarItemByName(room.fname).click(); - await expect(poOmnichannel.content.inputMessage).not.toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).not.toBeVisible(); }); await test.step('expect take chat to be visible and return to queue not visible', async () => { @@ -67,7 +67,7 @@ test.describe('OC - Manual Selection After Relogin', () => { await test.step('expect to be able take chat', async () => { await poOmnichannel.content.btnTakeChat.click(); await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel'); - await expect(poOmnichannel.content.inputMessage).toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).toBeVisible(); await expect(poOmnichannel.content.btnTakeChat).not.toBeVisible(); await expect(poOmnichannel.content.btnReturnToQueue).toBeVisible(); await expect(poOmnichannel.sidebar.getSidebarItemByName(room.fname)).toBeVisible(); diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection.spec.ts index 6e249d0924ac2..1a96b2f8eaab7 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-manual-selection.spec.ts @@ -68,14 +68,14 @@ test.describe('OC - Manual Selection', () => { await test.step('expect to be able join chat in read mode', async () => { await poOmnichannel.sidebar.getSidebarItemByName(room.fname).click(); - await expect(poOmnichannel.content.inputMessage).not.toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).not.toBeVisible(); await expect(poOmnichannel.content.btnTakeChat).toBeVisible(); }); await test.step('expect to be able take chat', async () => { await poOmnichannel.content.btnTakeChat.click(); await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel'); - await expect(poOmnichannel.content.inputMessage).toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).toBeVisible(); await expect(poOmnichannel.content.btnTakeChat).not.toBeVisible(); await expect(poOmnichannel.sidebar.getSidebarItemByName(room.fname)).toBeVisible(); }); @@ -96,7 +96,7 @@ test.describe('OC - Manual Selection', () => { await expect(agentB.poHomeOmnichannel.sidebar.getSidebarItemByName(room.fname)).toBeVisible(); await poOmnichannel.sidebar.getSidebarItemByName(room.fname).click(); - await expect(poOmnichannel.content.inputMessage).not.toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).not.toBeVisible(); await expect(poOmnichannel.content.btnTakeChat).toBeVisible(); }); }); diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-monitor-role.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-monitor-role.spec.ts index 53832b328d94a..618b63c13b1b2 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-monitor-role.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-monitor-role.spec.ts @@ -173,13 +173,13 @@ test.describe('OC - Monitor Role', () => { await test.step('expect to be able to join chats from same unit', async () => { await poOmnichannel.chats.openChat(ROOM_A); - await expect(poOmnichannel.content.btnJoinRoom).toBeVisible(); - await expect(poOmnichannel.content.inputMessage).not.toBeVisible(); + await expect(poOmnichannel.composer.btnJoinRoom).toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).not.toBeVisible(); - await poOmnichannel.content.btnJoinRoom.click(); + await poOmnichannel.composer.btnJoinRoom.click(); await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText('joined the channel'); - await expect(poOmnichannel.content.btnJoinRoom).not.toBeVisible(); - await expect(poOmnichannel.content.inputMessage).toBeVisible(); + await expect(poOmnichannel.composer.btnJoinRoom).not.toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).toBeVisible(); }); await test.step('expect to be able to put a conversation from another agent on hold', async () => { @@ -187,14 +187,14 @@ test.describe('OC - Monitor Role', () => { await expect(poOmnichannel.content.lastSystemMessageBody).toHaveText( `Chat On Hold: The chat was manually placed On Hold by ${MONITOR}`, ); - await expect(poOmnichannel.content.inputMessage).not.toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).not.toBeVisible(); await expect(poOmnichannel.content.btnResume).toBeVisible(); }); await test.step('expect to be able resume a conversation from another agent on hold', async () => { await poOmnichannel.content.btnResume.click(); await expect(poOmnichannel.content.btnResume).not.toBeVisible(); - await expect(poOmnichannel.content.inputMessage).toBeVisible(); + await expect(poOmnichannel.composer.inputMessage).toBeVisible(); await expect(poOmnichannel.quickActionsRoomToolbar.btnOnHold).toBeVisible(); }); diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-takeChat.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-takeChat.spec.ts index 78626f77d70b2..2b11fdad694a0 100644 --- a/apps/meteor/tests/e2e/omnichannel/omnichannel-takeChat.spec.ts +++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-takeChat.spec.ts @@ -63,7 +63,7 @@ test.describe('omnichannel-takeChat', () => { await agent.poHomeChannel.navbar.openChat(newVisitor.name); await expect(agent.poHomeChannel.content.btnTakeChat).not.toBeVisible(); - await expect(agent.poHomeChannel.content.inputMessage).toBeVisible(); + await expect(agent.poHomeChannel.composer.inputMessage).toBeVisible(); }); test('When agent is offline should not take the chat', async () => { diff --git a/apps/meteor/tests/e2e/page-objects/fragments/composer.ts b/apps/meteor/tests/e2e/page-objects/fragments/composer.ts new file mode 100644 index 0000000000000..457ffd72fabdf --- /dev/null +++ b/apps/meteor/tests/e2e/page-objects/fragments/composer.ts @@ -0,0 +1,79 @@ +import type { Locator, Page } from 'playwright-core'; + +export abstract class Composer { + constructor(protected root: Locator) { + this.root = root; + } + + get inputMessage(): Locator { + return this.root.locator('[name="msg"]'); + } + + get btnJoinRoom(): Locator { + return this.root.getByRole('button', { name: 'Join' }); + } + + get toolbarPrimaryActions(): Locator { + return this.root.getByRole('toolbar', { name: 'Composer Primary Actions' }); + } + + get allPrimaryActions(): Locator { + return this.toolbarPrimaryActions.getByRole('button'); + } + + get btnEmoji(): Locator { + return this.toolbarPrimaryActions.getByRole('button', { name: 'Emoji', exact: true }); + } + + get btnAudioMessage(): Locator { + return this.toolbarPrimaryActions.getByRole('button', { name: 'Audio message' }); + } + + get btnSend(): Locator { + return this.root.getByRole('button', { name: 'Send' }); + } + + get btnOptionFileUpload(): Locator { + return this.toolbarPrimaryActions.getByRole('button', { name: 'Upload file' }); + } + + get btnVideoMessage(): Locator { + return this.toolbarPrimaryActions.getByRole('button', { name: 'Video message' }); + } + + get btnMenuMoreActions() { + return this.toolbarPrimaryActions.getByRole('button', { name: 'More actions' }); + } + + get btnItalicFormatter(): Locator { + return this.toolbarPrimaryActions.getByRole('button', { name: 'Italic', exact: true }); + } + + get btnBoldFormatter(): Locator { + return this.toolbarPrimaryActions.getByRole('button', { name: 'Bold', exact: true }); + } + + get btnLinkFormatter(): Locator { + return this.toolbarPrimaryActions.getByRole('button', { name: 'Link', exact: true }); + } + + get boxPopup(): Locator { + return this.root.locator('[role="menu"][name="ComposerBoxPopup"]'); + } + + get readOnlyFooter(): Locator { + return this.root.getByText('This room is read only'); + } +} + +export class RoomComposer extends Composer { + constructor(page: Page) { + super(page.locator('footer[aria-label="Room composer"]')); + } +} + +export class ThreadComposer extends Composer { + constructor(page: Page) { + super(page.locator('footer[aria-label="Thread composer"]')); + } +} diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts index e5b1741d3047a..3f36cc6d13ca7 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts @@ -3,6 +3,7 @@ import { resolve, join, relative } from 'node:path'; import type { Locator, Page } from '@playwright/test'; +import { RoomComposer, ThreadComposer } from './composer'; import { expect } from '../../utils/test'; const FIXTURES_PATH = relative(process.cwd(), resolve(__dirname, '../../fixtures/files')); @@ -14,8 +15,14 @@ export function getFilePath(fileName: string): string { export class HomeContent { protected readonly page: Page; + protected readonly composer: RoomComposer; + + protected readonly threadComposer: ThreadComposer; + constructor(page: Page) { this.page = page; + this.composer = new RoomComposer(page); + this.threadComposer = new ThreadComposer(page); } get channelHeader(): Locator { @@ -30,14 +37,6 @@ export class HomeContent { return this.page.locator('main').getByRole('alert', { name: 'Retention policy warning banner' }); } - get inputMessage(): Locator { - return this.page.locator('[name="msg"]'); - } - - get inputThreadMessage(): Locator { - return this.page.getByRole('dialog').locator('[name="msg"]').last(); - } - get messagePopupUsers(): Locator { return this.page.locator('role=menu[name="People"]'); } @@ -74,28 +73,20 @@ export class HomeContent { return this.lastUserMessageBody.locator('role=button[name="This message was ignored"]'); } - get btnJoinRoom(): Locator { - return this.page.locator('role=button[name="Join"]'); - } - - async joinRoom(): Promise { - await this.btnJoinRoom.click(); - } - async joinRoomIfNeeded(): Promise { - if (await this.inputMessage.isEnabled()) { + if (await this.composer.inputMessage.isEnabled()) { return; } - if (!(await this.btnJoinRoom.isVisible())) { + if (!(await this.composer.btnJoinRoom.isVisible())) { return; } - await this.joinRoom(); + await this.composer.btnJoinRoom.click(); } async sendMessage(text: string, enforce = true): Promise { await this.joinRoomIfNeeded(); - await this.page.waitForSelector('[name="msg"]:not([disabled])'); - await this.page.locator('[name="msg"]').fill(text); + await expect(this.composer.inputMessage).toBeEnabled(); + await this.composer.inputMessage.fill(text); if (enforce) { const responsePromise = this.page.waitForResponse( @@ -103,7 +94,7 @@ export class HomeContent { /api\/v1\/method.call\/sendMessage/.test(response.url()) && response.status() === 200 && response.request().method() === 'POST', ); - await this.page.getByRole('button', { name: 'Send', exact: true }).click(); + await this.composer.btnSend.click(); const response = await (await responsePromise).json(); @@ -113,15 +104,16 @@ export class HomeContent { await expect(messageLocator).toBeVisible(); await expect(messageLocator).not.toHaveClass('rcx-message--pending'); } else { - await this.page.getByRole('button', { name: 'Send', exact: true }).click(); + await this.composer.btnSend.click(); } } async dispatchSlashCommand(text: string): Promise { await this.joinRoomIfNeeded(); - await this.page.waitForSelector('[name="msg"]:not([disabled])'); - await this.page.locator('[name="msg"]').fill(''); - await this.page.locator('[name="msg"]').fill(text); + await expect(this.composer.inputMessage).toBeEnabled(); + + await this.composer.inputMessage.fill(''); + await this.composer.inputMessage.fill(text); await this.page.keyboard.press('Enter'); await this.page.keyboard.press('Enter'); } @@ -137,6 +129,7 @@ export class HomeContent { await this.page.locator('role=button[name="Forward"]').click(); } + // TODO: use modal fragments ----------------------------------------- get btnModalCancel(): Locator { return this.page.locator('#modal-root .rcx-button-group--align-end .rcx-button--secondary'); } @@ -187,6 +180,8 @@ export class HomeContent { return this.page.locator('//div[@id="modal-root"]//fieldset//div[1]//span//input'); } + // ----------------------------------------- + get lastMessageFileName(): Locator { return this.page.locator('[data-qa-type="message"]:last-child [data-qa-type="attachment-title-link"]'); } @@ -267,6 +262,7 @@ export class HomeContent { return this.page.locator('div.thread-list ul.thread [data-qa-type="message"]').last().locator('[data-qa-type="attachment-title-link"]'); } + // TODO: improve locator specificity get menuMore(): Locator { return this.page.getByRole('menu', { name: 'More', exact: true }); } @@ -291,26 +287,10 @@ export class HomeContent { return this.menuMore.getByRole('menuitem', { name: 'Star', exact: true }); } - get btnOptionFileUpload(): Locator { - return this.page.locator('[data-qa-id="file-upload"]'); - } - - get btnVideoMessage(): Locator { - return this.page.locator('[data-qa-id="video-message"]'); - } - get btnVoiceCall(): Locator { return this.primaryRoomActionsToolbar.getByRole('button', { name: 'Voice call' }); } - get btnRecordAudio(): Locator { - return this.page.locator('[data-qa-id="audio-message"]'); - } - - get btnMenuMoreActions() { - return this.page.getByRole('button', { name: 'More actions', exact: true }); - } - get userCard(): Locator { return this.page.getByRole('dialog', { name: 'User card', exact: true }); } @@ -359,32 +339,6 @@ export class HomeContent { return this.imageGallery.locator(`button[name="${name}"]`); } - get btnComposerEmoji(): Locator { - return this.page.locator('role=toolbar[name="Composer Primary Actions"] >> role=button[name="Emoji"]'); - } - - get dialogEmojiPicker(): Locator { - return this.page.getByRole('dialog', { name: 'Emoji picker' }); - } - - get scrollerEmojiPicker(): Locator { - return this.dialogEmojiPicker.locator('[data-overlayscrollbars]'); - } - - getEmojiPickerTabByName(name: string) { - return this.dialogEmojiPicker.locator(`role=tablist >> role=tab[name="${name}"]`); - } - - getEmojiByName(name: string) { - return this.dialogEmojiPicker.locator(`role=tabpanel >> role=button[name="${name}"]`); - } - - async pickEmoji(emoji: string, section = 'Smileys & People') { - await this.btnComposerEmoji.click(); - await this.getEmojiPickerTabByName(section).click(); - await this.getEmojiByName(emoji).click(); - } - async dragAndDropTxtFile(): Promise { const contract = await fs.readFile(getFilePath('any_file.txt'), 'utf-8'); const dataTransfer = await this.page.evaluateHandle((contract) => { @@ -396,7 +350,7 @@ export class HomeContent { return data; }, contract); - await this.inputMessage.dispatchEvent('dragenter', { dataTransfer }); + await this.composer.inputMessage.dispatchEvent('dragenter', { dataTransfer }); await this.page.locator('[role=dialog][data-qa="DropTargetOverlay"]').dispatchEvent('drop', { dataTransfer }); } @@ -412,7 +366,7 @@ export class HomeContent { return data; }, contract); - await this.inputMessage.dispatchEvent('dragenter', { dataTransfer }); + await this.composer.inputMessage.dispatchEvent('dragenter', { dataTransfer }); await this.page.locator('[role=dialog][data-qa="DropTargetOverlay"]').dispatchEvent('drop', { dataTransfer }); } @@ -428,7 +382,7 @@ export class HomeContent { return data; }, contract); - await this.inputThreadMessage.dispatchEvent('dragenter', { dataTransfer }); + await this.threadComposer.inputMessage.dispatchEvent('dragenter', { dataTransfer }); await this.page.locator('[role=dialog][data-qa="DropTargetOverlay"]').dispatchEvent('drop', { dataTransfer }); } @@ -561,6 +515,11 @@ export class HomeContent { } async sendMessageInThread(text: string): Promise { + await this.threadComposer.inputMessage.fill(text); + await this.threadComposer.btnSend.click(); + } + + async sendMessageInVideoConfPopup(text: string): Promise { await this.page.getByRole('dialog').getByRole('textbox', { name: 'Message' }).fill(text); await this.page.getByRole('dialog').getByRole('button', { name: 'Send', exact: true }).click(); } @@ -577,10 +536,6 @@ export class HomeContent { return this.page.getByRole('button', { name: 'Clear selection' }); } - get btnJoinChannel() { - return this.page.getByRole('button', { name: 'Join channel' }); - } - get contactUnknownCallout() { return this.page.getByRole('status', { name: 'Unknown contact. This contact is not on the contact list.' }); } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-omnichannel-content.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-omnichannel-content.ts index b15aebfaa611b..47630b06220ad 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-omnichannel-content.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-omnichannel-content.ts @@ -31,10 +31,6 @@ export class HomeOmnichannelContent extends HomeContent { return this.page.locator('role=button[name="Take it!"]'); } - override get inputMessage(): Locator { - return this.page.locator('[name="msg"]'); - } - get contactContextualBar() { return this.page.getByRole('dialog', { name: 'Contact' }); } @@ -60,9 +56,9 @@ export class HomeOmnichannelContent extends HomeContent { } async useCannedResponse(cannedResponseName: string): Promise { - await this.inputMessage.pressSequentially('!'); + await this.composer.inputMessage.pressSequentially('!'); await this.page.locator('[role="menu"][name="ComposerBoxPopup"]').waitFor({ state: 'visible' }); - await this.inputMessage.pressSequentially(cannedResponseName); + await this.composer.inputMessage.pressSequentially(cannedResponseName); await this.page.keyboard.press('Enter'); } } diff --git a/apps/meteor/tests/e2e/page-objects/fragments/index.ts b/apps/meteor/tests/e2e/page-objects/fragments/index.ts index 51ba6595b6d06..f1f349b6a82ab 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/index.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/index.ts @@ -12,3 +12,4 @@ export * from './toast-messages'; export * from './export-messages-tab'; export * from './menu'; export * from './toolbar'; +export * from './composer'; diff --git a/apps/meteor/tests/e2e/page-objects/home-channel.ts b/apps/meteor/tests/e2e/page-objects/home-channel.ts index 478ca3d2f84b6..4efd3bcdc4303 100644 --- a/apps/meteor/tests/e2e/page-objects/home-channel.ts +++ b/apps/meteor/tests/e2e/page-objects/home-channel.ts @@ -1,6 +1,6 @@ import type { Locator, Page } from '@playwright/test'; -import { HomeContent, HomeFlextab, Navbar, Sidepanel, RoomSidebar, ToastMessages } from './fragments'; +import { HomeContent, HomeFlextab, Navbar, Sidepanel, RoomSidebar, ToastMessages, RoomComposer, ThreadComposer } from './fragments'; import { RoomToolbar } from './fragments/toolbar'; import { VoiceCalls } from './fragments/voice-calls'; @@ -23,6 +23,10 @@ export class HomeChannel { readonly toastMessage: ToastMessages; + readonly composer: RoomComposer; + + readonly threadComposer: ThreadComposer; + constructor(page: Page) { this.page = page; this.content = new HomeContent(page); @@ -33,6 +37,8 @@ export class HomeChannel { this.roomToolbar = new RoomToolbar(page); this.voiceCalls = new VoiceCalls(page); this.toastMessage = new ToastMessages(page); + this.composer = new RoomComposer(page); + this.threadComposer = new ThreadComposer(page); } goto() { @@ -43,34 +49,14 @@ export class HomeChannel { return this.page.locator('[data-qa="ContextualbarActionClose"]'); } - get composer(): Locator { - return this.page.locator('textarea[name="msg"]'); - } - - get composerBoxPopup(): Locator { - return this.page.locator('[role="menu"][name="ComposerBoxPopup"]'); - } - get userCardToolbar(): Locator { return this.page.locator('[role=toolbar][aria-label="User card actions"]'); } - get composerToolbar(): Locator { - return this.page.locator('[role=toolbar][aria-label="Composer Primary Actions"]'); - } - - get composerToolbarActions(): Locator { - return this.page.locator('[role=toolbar][aria-label="Composer Primary Actions"] button'); - } - get roomHeaderFavoriteBtn(): Locator { return this.page.getByRole('main').getByRole('button', { name: 'Favorite' }); } - get readOnlyFooter(): Locator { - return this.page.locator('footer', { hasText: 'This room is read only' }); - } - get roomHeaderToolbar(): Locator { return this.page.locator('[role=toolbar][aria-label="Primary Room actions"]'); } @@ -111,10 +97,6 @@ export class HomeChannel { return this.page.getByRole('group', { name: 'Audio recorder', exact: true }); } - get btnJoinRoom(): Locator { - return this.page.getByRole('button', { name: 'Join' }); - } - get statusUploadIndicator(): Locator { return this.page.getByRole('main').getByRole('status'); } @@ -123,6 +105,32 @@ export class HomeChannel { return this.page.locator('main').getByRole('heading', { name: 'Home' }); } + get dialogEmojiPicker(): Locator { + return this.page.getByRole('dialog', { name: 'Emoji picker' }); + } + + get scrollerEmojiPicker(): Locator { + return this.dialogEmojiPicker.locator('[data-overlayscrollbars]'); + } + + get btnJoinChannel() { + return this.page.getByRole('button', { name: 'Join channel' }); + } + + getEmojiPickerTabByName(name: string) { + return this.dialogEmojiPicker.locator(`role=tablist >> role=tab[name="${name}"]`); + } + + getEmojiByName(name: string) { + return this.dialogEmojiPicker.locator(`role=tabpanel >> role=button[name="${name}"]`); + } + + async pickEmoji(emoji: string, section = 'Smileys & People') { + await this.composer.btnEmoji.click(); + await this.getEmojiPickerTabByName(section).click(); + await this.getEmojiByName(emoji).click(); + } + async waitForHome(): Promise { await this.homepageHeader.waitFor({ state: 'visible' }); } diff --git a/apps/meteor/tests/e2e/permissions.spec.ts b/apps/meteor/tests/e2e/permissions.spec.ts index 5ac528ee175cd..a2f230c56373c 100644 --- a/apps/meteor/tests/e2e/permissions.spec.ts +++ b/apps/meteor/tests/e2e/permissions.spec.ts @@ -138,7 +138,7 @@ test.describe.serial('permissions', () => { test('expect option (upload file) not be visible', async () => { await poHomeChannel.navbar.openChat(targetChannel); - await expect(poHomeChannel.content.btnOptionFileUpload).toBeDisabled(); + await expect(poHomeChannel.composer.btnOptionFileUpload).toBeDisabled(); }); test.afterAll(async ({ api }) => { @@ -157,7 +157,7 @@ test.describe.serial('permissions', () => { test('expect option (upload audio) not be visible', async () => { await poHomeChannel.navbar.openChat(targetChannel); - await expect(poHomeChannel.content.btnRecordAudio).toBeDisabled(); + await expect(poHomeChannel.composer.btnAudioMessage).toBeDisabled(); }); test.afterAll(async ({ api }) => { @@ -176,7 +176,7 @@ test.describe.serial('permissions', () => { test('expect option (upload video) not be visible', async () => { await poHomeChannel.navbar.openChat(targetChannel); - await expect(poHomeChannel.content.btnVideoMessage).toBeDisabled(); + await expect(poHomeChannel.composer.btnVideoMessage).toBeDisabled(); }); test.afterAll(async ({ api }) => { diff --git a/apps/meteor/tests/e2e/preview-public-channel.spec.ts b/apps/meteor/tests/e2e/preview-public-channel.spec.ts index f28b5e7ce1640..12331bc14221c 100644 --- a/apps/meteor/tests/e2e/preview-public-channel.spec.ts +++ b/apps/meteor/tests/e2e/preview-public-channel.spec.ts @@ -48,8 +48,8 @@ test.describe('Preview public channel', () => { await poHomeChannel.navbar.openChat(Users.user2.data.username); - await expect(poHomeChannel.content.btnJoinChannel).not.toBeVisible(); - await expect(poHomeChannel.composer).toBeEnabled(); + await expect(poHomeChannel.composer.btnJoinRoom).not.toBeVisible(); + await expect(poHomeChannel.composer.inputMessage).toBeEnabled(); }); test('should not let user role preview public rooms', async ({ api }) => { @@ -58,7 +58,7 @@ test.describe('Preview public channel', () => { await poHomeChannel.navbar.btnDirectory.click(); await poDirectory.openChannel(targetChannel); - await expect(poHomeChannel.content.btnJoinChannel).toBeVisible(); + await expect(poHomeChannel.btnJoinChannel).toBeVisible(); await expect(poHomeChannel.content.lastUserMessageBody).not.toBeVisible(); }); }); @@ -74,7 +74,7 @@ test.describe('Preview public channel', () => { await expect(poHomeChannel.content.lastUserMessageBody).toContainText(targetChannelMessage); - await poHomeChannel.btnJoinRoom.click(); + await poHomeChannel.composer.btnJoinRoom.click(); await expect( page.locator('[role="alert"]', { @@ -90,7 +90,7 @@ test.describe('Preview public channel', () => { await poDirectory.openChannel(targetChannel); await expect(poHomeChannel.content.lastUserMessageBody).not.toBeVisible(); - await poHomeChannel.content.btnJoinChannel.click(); + await poHomeChannel.btnJoinChannel.click(); await expect( page.locator('[role="alert"]', { diff --git a/apps/meteor/tests/e2e/quote-messages.spec.ts b/apps/meteor/tests/e2e/quote-messages.spec.ts index 1723237b91ba9..72d944be30091 100644 --- a/apps/meteor/tests/e2e/quote-messages.spec.ts +++ b/apps/meteor/tests/e2e/quote-messages.spec.ts @@ -53,7 +53,7 @@ test.describe.serial('Quote Messages', () => { await poHomeChannel.content.lastUserMessage.hover(); await poHomeChannel.content.openLastMessageMenu(); await poHomeChannel.content.btnOptionEditMessage.click(); - await poHomeChannel.content.inputMessage.fill(editedQuoteText); + await poHomeChannel.composer.inputMessage.fill(editedQuoteText); await page.keyboard.press('Enter'); }); diff --git a/apps/meteor/tests/e2e/voice-calls-ee.spec.ts b/apps/meteor/tests/e2e/voice-calls-ee.spec.ts index c6bb05cb4c003..d1931f81eaa26 100644 --- a/apps/meteor/tests/e2e/voice-calls-ee.spec.ts +++ b/apps/meteor/tests/e2e/voice-calls-ee.spec.ts @@ -29,7 +29,7 @@ test.describe('Internal Voice Calls - Enterprise Edition', () => { await test.step('should open direct message with user2', async () => { await user1.poHomeChannel.navbar.openChat('user2'); - await expect(user1.poHomeChannel.content.inputMessage).toBeVisible(); + await expect(user1.poHomeChannel.composer.inputMessage).toBeVisible(); }); await test.step('initiate a voice call from room toolbar', async () => { @@ -53,7 +53,7 @@ test.describe('Internal Voice Calls - Enterprise Edition', () => { const [user1, user2] = sessions; await test.step('establish call connection', async () => { await user1.poHomeChannel.navbar.openChat('user2'); - await expect(user1.poHomeChannel.content.inputMessage).toBeVisible(); + await expect(user1.poHomeChannel.composer.inputMessage).toBeVisible(); await user1.poHomeChannel.content.btnVoiceCall.click(); await user1.poHomeChannel.voiceCalls.initiateCall(); await user2.poHomeChannel.voiceCalls.acceptCall(); @@ -107,7 +107,7 @@ test.describe('Internal Voice Calls - Enterprise Edition', () => { await test.step('establish call between user1 and user2', async () => { await user1.poHomeChannel.navbar.openChat('user2'); - await expect(user1.poHomeChannel.content.inputMessage).toBeVisible(); + await expect(user1.poHomeChannel.composer.inputMessage).toBeVisible(); await user1.poHomeChannel.content.btnVoiceCall.click(); await user1.poHomeChannel.voiceCalls.initiateCall(); await user2.poHomeChannel.voiceCalls.acceptCall(); @@ -138,7 +138,7 @@ test.describe('Internal Voice Calls - Enterprise Edition', () => { await test.step('user1 initiates call to user2', async () => { await user1.poHomeChannel.navbar.openChat('user2'); - await expect(user1.poHomeChannel.content.inputMessage).toBeVisible(); + await expect(user1.poHomeChannel.composer.inputMessage).toBeVisible(); await user1.poHomeChannel.content.btnVoiceCall.click(); await user1.poHomeChannel.voiceCalls.initiateCall(); }); diff --git a/packages/apps-engine/deno-runtime/handlers/app/handler.ts b/packages/apps-engine/deno-runtime/handlers/app/handler.ts index 4193e7e948b47..171d179a2d05d 100644 --- a/packages/apps-engine/deno-runtime/handlers/app/handler.ts +++ b/packages/apps-engine/deno-runtime/handlers/app/handler.ts @@ -28,14 +28,23 @@ export default async function handleApp(method: string, params: unknown): Promis // `app` will be undefined if the method here is "app:construct" const app = AppObjectRegistry.get('app'); - app?.getLogger().debug(`'${appMethod}' is being called...`); + app?.getLogger().debug({ msg: `A method is being called...`, appMethod }); if (uikitInteractions.includes(appMethod)) { return handleUIKitInteraction(appMethod, params).then((result) => { if (result instanceof JsonRpcError) { - app?.getLogger().debug(`'${appMethod}' was unsuccessful.`, result.message); + app?.getLogger().debug({ + msg: `Method call was unsuccessful.`, + appMethod, + err: result, + errorMessage: result.message, + }); } else { - app?.getLogger().debug(`'${appMethod}' was successfully called! The result is:`, result); + app?.getLogger().debug({ + msg: `Method was successfully called! The result is:`, + appMethod, + result, + }); } return result; @@ -45,9 +54,18 @@ export default async function handleApp(method: string, params: unknown): Promis if (appMethod.startsWith('check') || appMethod.startsWith('execute')) { return handleListener(appMethod, params).then((result) => { if (result instanceof JsonRpcError) { - app?.getLogger().debug(`'${appMethod}' was unsuccessful.`, result.message); + app?.getLogger().debug({ + msg: `'${appMethod}' was unsuccessful.`, + appMethod, + err: result, + errorMessage: result.message, + }); } else { - app?.getLogger().debug(`'${appMethod}' was successfully called! The result is:`, result); + app?.getLogger().debug({ + msg: `'${appMethod}' was successfully called! The result is:`, + appMethod, + result, + }); } return result; @@ -91,7 +109,11 @@ export default async function handleApp(method: string, params: unknown): Promis throw new JsonRpcError('Method not found', -32601); } - app?.getLogger().debug(`'${appMethod}' was successfully called! The result is:`, result); + app?.getLogger().debug({ + msg: `'${appMethod}' was successfully called! The result is:`, + appMethod, + result, + }); return result; } catch (e: unknown) { diff --git a/packages/apps-engine/deno-runtime/handlers/scheduler-handler.ts b/packages/apps-engine/deno-runtime/handlers/scheduler-handler.ts index 2df1eb564017b..30d69ed7046e0 100644 --- a/packages/apps-engine/deno-runtime/handlers/scheduler-handler.ts +++ b/packages/apps-engine/deno-runtime/handlers/scheduler-handler.ts @@ -28,7 +28,7 @@ export default async function handleScheduler(method: string, params: unknown): }); } - app.getLogger().debug(`Job processor ${processor.id} is being executed...`); + app.getLogger().debug({ msg: 'Job processor is being executed...', processorId: processor.id }); try { await processor.processor( @@ -39,12 +39,12 @@ export default async function handleScheduler(method: string, params: unknown): AppAccessorsInstance.getPersistence(), ); - app.getLogger().debug(`Job processor ${processor.id} was successfully executed`); + app.getLogger().debug({ msg: 'Job processor was successfully executed', processorId: processor.id }); return null; } catch (e) { app.getLogger().error(e); - app.getLogger().error(`Job processor ${processor.id} was unsuccessful`); + app.getLogger().error({ msg: 'Job processor was unsuccessful', processorId: processor.id }); return JsonRpcError.internalError({ message: e.message }); } diff --git a/packages/apps-engine/deno-runtime/handlers/slashcommand-handler.ts b/packages/apps-engine/deno-runtime/handlers/slashcommand-handler.ts index 51e00fa0142d1..c317f891bebf4 100644 --- a/packages/apps-engine/deno-runtime/handlers/slashcommand-handler.ts +++ b/packages/apps-engine/deno-runtime/handlers/slashcommand-handler.ts @@ -30,7 +30,7 @@ export default async function slashCommandHandler(call: string, params: unknown) // If the command is registered, we're pretty safe to assume the app is not undefined const app = AppObjectRegistry.get('app')!; - app.getLogger().debug(`${commandName}'s ${method} is being executed...`, params); + app.getLogger().debug({ msg: `Command is being executed...`, commandName, method, params }); try { if (method === 'executor' || method === 'previewer') { @@ -41,9 +41,9 @@ export default async function slashCommandHandler(call: string, params: unknown) return new JsonRpcError(`Method ${method} not found on slashcommand ${commandName}`, -32000); } - app.getLogger().debug(`${commandName}'s ${method} was successfully executed.`); + app.getLogger().debug({ msg: `Command was successfully executed.`, commandName, method }); } catch (error) { - app.getLogger().debug(`${commandName}'s ${method} was unsuccessful.`); + app.getLogger().debug({ msg: `Command was unsuccessful.`, commandName, method, err: error }); return new JsonRpcError(error.message, -32000); } diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 440b5f011c4a4..35e07ad893b3e 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -1014,7 +1014,7 @@ }, "Cam_off": "Cam Off", "Cam_on": "Cam On", - "Camera_access_not_allowed": "Camera access was not allowed, please check your browser settings.", + "Camera_access_not_allowed": "Video message - camera access was not allowed, please check your browser settings.", "Cancel": "Cancel", "Cancel__planName__subscription": "Cancel {{planName}} subscription", "Cancel_message_input": "Cancel", @@ -3402,7 +3402,7 @@ "Message_Audio": "Audio Message", "Message_AudioRecorderEnabled": "Audio Recorder Enabled", "Message_AudioRecorderEnabled_Description": "Requires 'audio/mp3' files to be an accepted media type within 'File Upload' settings.", - "Message_Audio_Recording_Disabled": "Message audio recording disabled", + "Message_Audio_Recording_Disabled": "Audio message - message audio recording disabled", "Message_Audio_bitRate": "Audio Message Bit Rate", "Message_BadWordsFilterList": "Add Bad Words to the Blacklist", "Message_BadWordsFilterListDescription": "Add List of Comma-separated list of bad words to filter", @@ -7086,5 +7086,8 @@ "timestamps.fullDateTimeLongDescription": "Thursday, December 31, 2020 12:00:00 AM", "__username__profile_picture": "{{username}}'s profile picture", "User_card": "User card", - "timestamps.relativeTimeDescription": "1 year ago" + "timestamps.relativeTimeDescription": "1 year ago", + "Message_composer": "Message composer", + "Thread_composer": "Thread composer", + "Room_composer": "Room composer" } \ No newline at end of file