{
+ return this.deleteOne({ _id });
+ }
- return this.deleteOne({ service });
+ async findOneByService(
+ serviceName: LoginServiceConfiguration['service'],
+ options?: FindOptions
,
+ ): Promise
{
+ return this.findOne({ service: serviceName.toLowerCase() }, options);
}
}
diff --git a/apps/meteor/server/models/raw/Roles.ts b/apps/meteor/server/models/raw/Roles.ts
index 355faae256e5..84a5b088ea30 100644
--- a/apps/meteor/server/models/raw/Roles.ts
+++ b/apps/meteor/server/models/raw/Roles.ts
@@ -1,7 +1,7 @@
import type { IRole, IRoom, IUser, RocketChatRecordDeleted } from '@rocket.chat/core-typings';
import type { IRolesModel } from '@rocket.chat/model-typings';
import { Subscriptions, Users } from '@rocket.chat/models';
-import type { Collection, FindCursor, Db, Filter, FindOptions, InsertOneResult, UpdateResult, WithId, Document } from 'mongodb';
+import type { Collection, FindCursor, Db, Filter, FindOptions, Document } from 'mongodb';
import { BaseRaw } from './BaseRaw';
@@ -190,21 +190,31 @@ export class RolesRaw extends BaseRaw implements IRolesModel {
return this.find(query, options || {});
}
- updateById(
+ async updateById(
_id: IRole['_id'],
name: IRole['name'],
scope: IRole['scope'],
description: IRole['description'] = '',
mandatory2fa: IRole['mandatory2fa'] = false,
- ): Promise {
- const queryData = {
- name,
- scope,
- description,
- mandatory2fa,
- };
+ ): Promise {
+ const response = await this.findOneAndUpdate(
+ { _id },
+ {
+ $set: {
+ name,
+ scope,
+ description,
+ mandatory2fa,
+ },
+ },
+ { upsert: true, returnDocument: 'after' },
+ );
+
+ if (!response.value) {
+ throw new Error('Role not found');
+ }
- return this.updateOne({ _id }, { $set: queryData }, { upsert: true });
+ return response.value;
}
findUsersInRole(roleId: IRole['_id'], scope?: IRoom['_id']): Promise>;
@@ -242,13 +252,13 @@ export class RolesRaw extends BaseRaw implements IRolesModel {
}
}
- createWithRandomId(
+ async createWithRandomId(
name: IRole['name'],
scope: IRole['scope'] = 'Users',
description = '',
protectedRole = true,
mandatory2fa = false,
- ): Promise>> {
+ ): Promise {
const role = {
name,
scope,
@@ -257,7 +267,12 @@ export class RolesRaw extends BaseRaw implements IRolesModel {
mandatory2fa,
};
- return this.insertOne(role);
+ const res = await this.insertOne(role);
+
+ return {
+ _id: res.insertedId,
+ ...role,
+ };
}
async canAddUserToRole(uid: IUser['_id'], roleId: IRole['_id'], scope?: IRoom['_id']): Promise {
diff --git a/apps/meteor/server/models/raw/Rooms.ts b/apps/meteor/server/models/raw/Rooms.ts
index e0466b48c114..64bde1c32924 100644
--- a/apps/meteor/server/models/raw/Rooms.ts
+++ b/apps/meteor/server/models/raw/Rooms.ts
@@ -1460,6 +1460,14 @@ export class RoomsRaw extends BaseRaw implements IRoomsModel {
return this.find({ createdOTR: true });
}
+ findByUsernamesOrUids(uids: IRoom['u']['_id'][], usernames: IRoom['u']['username'][]): FindCursor {
+ return this.find({ $or: [{ usernames: { $in: usernames } }, { uids: { $in: uids } }] });
+ }
+
+ findDMsByUids(uids: IRoom['u']['_id'][]): FindCursor {
+ return this.find({ uids: { $size: 2, $in: [uids] }, t: 'd' });
+ }
+
// UPDATE
addImportIds(_id: IRoom['_id'], importIds: string[]): Promise {
const query: Filter = { _id };
diff --git a/apps/meteor/server/modules/listeners/listeners.module.ts b/apps/meteor/server/modules/listeners/listeners.module.ts
index 29d92d2f6a72..af85d4a29a5f 100644
--- a/apps/meteor/server/modules/listeners/listeners.module.ts
+++ b/apps/meteor/server/modules/listeners/listeners.module.ts
@@ -3,7 +3,7 @@ import type { ISetting as AppsSetting } from '@rocket.chat/apps-engine/definitio
import type { IServiceClass } from '@rocket.chat/core-services';
import { EnterpriseSettings } from '@rocket.chat/core-services';
import { isSettingColor, isSettingEnterprise, UserStatus } from '@rocket.chat/core-typings';
-import type { IUser, IRoom, VideoConference, ISetting, IOmnichannelRoom, IMessage, IOTRMessage } from '@rocket.chat/core-typings';
+import type { IUser, IRoom, IRole, VideoConference, ISetting, IOmnichannelRoom, IMessage, IOTRMessage } from '@rocket.chat/core-typings';
import { Logger } from '@rocket.chat/logger';
import { parse } from '@rocket.chat/message-parser';
@@ -205,11 +205,10 @@ export class ListenersModule {
});
service.onEvent('watch.roles', ({ clientAction, role }): void => {
- const payload = {
+ notifications.streamRoles.emitWithoutBroadcast('roles', {
type: clientAction,
- ...role,
- };
- notifications.streamRoles.emitWithoutBroadcast('roles', payload as any);
+ ...(role as IRole),
+ });
});
service.onEvent('watch.inquiries', async ({ clientAction, inquiry, diff }): Promise => {
diff --git a/apps/meteor/server/modules/watchers/watchers.module.ts b/apps/meteor/server/modules/watchers/watchers.module.ts
index 05a393c9ada6..684db6945626 100644
--- a/apps/meteor/server/modules/watchers/watchers.module.ts
+++ b/apps/meteor/server/modules/watchers/watchers.module.ts
@@ -422,20 +422,15 @@ export function initWatchers(watcher: DatabaseWatcher, broadcast: BroadcastCallb
}
});
- watcher.on(LivechatPriority.getCollectionName(), async ({ clientAction, id, data: eventData, diff }) => {
+ watcher.on(LivechatPriority.getCollectionName(), async ({ clientAction, id, diff }) => {
if (clientAction !== 'updated' || !diff || !('name' in diff)) {
// For now, we don't support this actions from happening
return;
}
- const data = eventData ?? (await LivechatPriority.findOne({ _id: id }));
- if (!data) {
- return;
- }
-
// This solves the problem of broadcasting, since now, watcher is the one in charge of doing it.
// What i don't like is the idea of giving more responsibilities to watcher, even when this works
- void broadcast('watch.priorities', { clientAction, data, id, diff });
+ void broadcast('watch.priorities', { clientAction, id, diff });
});
watcherStarted = true;
diff --git a/apps/meteor/server/services/messages/hooks/BeforeSavePreventMention.ts b/apps/meteor/server/services/messages/hooks/BeforeSavePreventMention.ts
index b87c0e613d2d..d4a278e85700 100644
--- a/apps/meteor/server/services/messages/hooks/BeforeSavePreventMention.ts
+++ b/apps/meteor/server/services/messages/hooks/BeforeSavePreventMention.ts
@@ -1,11 +1,9 @@
-import { Authorization, MeteorError, type IApiService } from '@rocket.chat/core-services';
+import { Authorization, MeteorError } from '@rocket.chat/core-services';
import { type IMessage, type IUser } from '@rocket.chat/core-typings';
import { i18n } from '../../../lib/i18n';
export class BeforeSavePreventMention {
- constructor(private api?: IApiService) {}
-
async preventMention({
message,
user,
@@ -32,16 +30,9 @@ export class BeforeSavePreventMention {
const action = i18n.t('Notify_all_in_this_room', { lng: user.language });
- // Add a notification to the chat, informing the user that this
- // action is not allowed.
- void this.api?.broadcast('notify.ephemeralMessage', message.u._id, message.rid, {
- // TODO: i18n
- msg: i18n.t('error-action-not-allowed', { action } as any, user.language),
- });
-
// Also throw to stop propagation of 'sendMessage'.
throw new MeteorError('error-action-not-allowed', `Notify ${mention} in this room not allowed`, {
- action: 'Notify_all_in_this_room',
+ action,
});
}
}
diff --git a/apps/meteor/server/services/messages/service.ts b/apps/meteor/server/services/messages/service.ts
index f0c30c359110..e18a9c276c50 100644
--- a/apps/meteor/server/services/messages/service.ts
+++ b/apps/meteor/server/services/messages/service.ts
@@ -40,7 +40,7 @@ export class MessageService extends ServiceClassInternal implements IMessageServ
private checkMAC: BeforeSaveCheckMAC;
async created() {
- this.preventMention = new BeforeSavePreventMention(this.api);
+ this.preventMention = new BeforeSavePreventMention();
this.badWords = new BeforeSaveBadWords();
this.spotify = new BeforeSaveSpotify();
this.jumpToMessage = new BeforeSaveJumpToMessage({
diff --git a/apps/meteor/server/services/omnichannel-voip/service.ts b/apps/meteor/server/services/omnichannel-voip/service.ts
index 3e492a4d6514..6d9f70044644 100644
--- a/apps/meteor/server/services/omnichannel-voip/service.ts
+++ b/apps/meteor/server/services/omnichannel-voip/service.ts
@@ -1,5 +1,5 @@
import type { IOmnichannelVoipService, FindVoipRoomsParams } from '@rocket.chat/core-services';
-import { api, ServiceClassInternal, Voip } from '@rocket.chat/core-services';
+import { api, ServiceClassInternal, VoipAsterisk } from '@rocket.chat/core-services';
import type {
IVoipExtensionBase,
IVoipExtensionWithAgentInfo,
@@ -197,7 +197,7 @@ export class OmnichannelVoipService extends ServiceClassInternal implements IOmn
}
async getFreeExtensions(): Promise {
- const allExtensions = await Voip.getExtensionList();
+ const allExtensions = await VoipAsterisk.getExtensionList();
const allocatedExtensions = await this.getAllocatedExtesionAllocationData({
extension: 1,
});
@@ -349,8 +349,8 @@ export class OmnichannelVoipService extends ServiceClassInternal implements IOmn
}
async getExtensionListWithAgentData(): Promise {
- const { result: extensions } = await Voip.getExtensionList();
- const summary = await (await Voip.cachedQueueDetails())();
+ const { result: extensions } = await VoipAsterisk.getExtensionList();
+ const summary = await (await VoipAsterisk.cachedQueueDetails())();
const allocatedExtensions = await this.getAllocatedExtesionAllocationData({
extension: 1,
_id: 1,
diff --git a/apps/meteor/server/services/startup.ts b/apps/meteor/server/services/startup.ts
index ed3a5870019c..05a095279855 100644
--- a/apps/meteor/server/services/startup.ts
+++ b/apps/meteor/server/services/startup.ts
@@ -30,7 +30,7 @@ import { UiKitCoreAppService } from './uikit-core-app/service';
import { UploadService } from './upload/service';
import { UserService } from './user/service';
import { VideoConfService } from './video-conference/service';
-import { VoipService } from './voip/service';
+import { VoipAsteriskService } from './voip-asterisk/service';
export const registerServices = async (): Promise => {
const { db } = MongoInternals.defaultRemoteCollectionDriver().mongo;
@@ -46,7 +46,7 @@ export const registerServices = async (): Promise => {
api.registerService(new NPSService());
api.registerService(new RoomService());
api.registerService(new SAUMonitorService());
- api.registerService(new VoipService(db));
+ api.registerService(new VoipAsteriskService(db));
api.registerService(new OmnichannelService());
api.registerService(new OmnichannelVoipService());
api.registerService(new TeamService());
diff --git a/apps/meteor/server/services/voip/connector/asterisk/Command.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/Command.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/Command.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/Command.ts
diff --git a/apps/meteor/server/services/voip/connector/asterisk/CommandHandler.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/CommandHandler.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/CommandHandler.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/CommandHandler.ts
diff --git a/apps/meteor/server/services/voip/connector/asterisk/Commands.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/Commands.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/Commands.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/Commands.ts
diff --git a/apps/meteor/server/services/voip/connector/asterisk/ICallbackContext.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/ICallbackContext.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/ICallbackContext.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/ICallbackContext.ts
diff --git a/apps/meteor/server/services/voip/connector/asterisk/IConnection.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/IConnection.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/IConnection.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/IConnection.ts
diff --git a/apps/meteor/server/services/voip/connector/asterisk/ami/ACDQueue.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/ACDQueue.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/ami/ACDQueue.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/ACDQueue.ts
diff --git a/apps/meteor/server/services/voip/connector/asterisk/ami/AMIConnection.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/AMIConnection.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/ami/AMIConnection.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/AMIConnection.ts
diff --git a/apps/meteor/server/services/voip/connector/asterisk/ami/CallbackContext.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/CallbackContext.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/ami/CallbackContext.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/CallbackContext.ts
diff --git a/apps/meteor/server/services/voip/connector/asterisk/ami/CommandFactory.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/CommandFactory.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/ami/CommandFactory.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/CommandFactory.ts
diff --git a/apps/meteor/server/services/voip/connector/asterisk/ami/ContinuousMonitor.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/ContinuousMonitor.ts
similarity index 96%
rename from apps/meteor/server/services/voip/connector/asterisk/ami/ContinuousMonitor.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/ContinuousMonitor.ts
index f4d2a0d3c298..38f2ce32e99c 100644
--- a/apps/meteor/server/services/voip/connector/asterisk/ami/ContinuousMonitor.ts
+++ b/apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/ContinuousMonitor.ts
@@ -47,11 +47,11 @@ import { Logger } from '@rocket.chat/logger';
import { Users, PbxEvents } from '@rocket.chat/models';
import type { Db } from 'mongodb';
+import { notifyOnPbxEventChangedById } from '../../../../../../app/lib/server/lib/notifyListener';
import { Command, CommandType } from '../Command';
import { Commands } from '../Commands';
import { ACDQueue } from './ACDQueue';
import { CallbackContext } from './CallbackContext';
-// import { sendMessage } from '../../../../../../app/lib/server/functions/sendMessage';
export class ContinuousMonitor extends Command {
private logger: Logger;
@@ -140,13 +140,15 @@ export class ContinuousMonitor extends Command {
// This event represents when an agent drops a call because of disconnection
// May happen for any reason outside of our control, like closing the browswer
// Or network/power issues
- await PbxEvents.insertOne({
+ const { insertedId } = await PbxEvents.insertOne({
event: eventName,
uniqueId: `${eventName}-${event.contactstatus}-${now.getTime()}`,
ts: now,
agentExtension: event.aor,
});
+ void notifyOnPbxEventChangedById(insertedId, 'inserted');
+
return;
}
@@ -159,7 +161,7 @@ export class ContinuousMonitor extends Command {
// NOTE: using the uniqueId prop of event is not the recommented approach, since it's an opaque ID
// However, since we're not using it for anything special, it's a "fair use"
// uniqueId => {server}/{epoch}.{id of channel associated with this call}
- await PbxEvents.insertOne({
+ const { insertedId } = await PbxEvents.insertOne({
uniqueId,
event: eventName,
ts: now,
@@ -170,6 +172,8 @@ export class ContinuousMonitor extends Command {
callUniqueIdFallback: event.linkedid,
agentExtension: event?.connectedlinenum,
});
+
+ void notifyOnPbxEventChangedById(insertedId, 'inserted');
} catch (e) {
this.logger.debug('Event was handled by other instance');
}
@@ -282,7 +286,7 @@ export class ContinuousMonitor extends Command {
* and event.calleridnum is the extension that is initiating a call.
*/
try {
- await PbxEvents.insertOne({
+ const { insertedId } = await PbxEvents.insertOne({
uniqueId: `${event.event}-${event.calleridnum}-${event.channel}-${event.destchannel}-${event.uniqueid}`,
event: event.event,
ts: new Date(),
@@ -291,6 +295,8 @@ export class ContinuousMonitor extends Command {
callUniqueIdFallback: event.linkedid,
agentExtension: event.calleridnum,
});
+
+ void notifyOnPbxEventChangedById(insertedId, 'inserted');
} catch (e) {
// This could mean we received a duplicate event
// This is quite common since DialEnd event happens "multiple times" at the end of the call
diff --git a/apps/meteor/server/services/voip/connector/asterisk/ami/PJSIPEndpoint.ts b/apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/PJSIPEndpoint.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/asterisk/ami/PJSIPEndpoint.ts
rename to apps/meteor/server/services/voip-asterisk/connector/asterisk/ami/PJSIPEndpoint.ts
diff --git a/apps/meteor/server/services/voip/connector/websocket/WebsocketConnection.ts b/apps/meteor/server/services/voip-asterisk/connector/websocket/WebsocketConnection.ts
similarity index 100%
rename from apps/meteor/server/services/voip/connector/websocket/WebsocketConnection.ts
rename to apps/meteor/server/services/voip-asterisk/connector/websocket/WebsocketConnection.ts
diff --git a/apps/meteor/server/services/voip/lib/Helper.ts b/apps/meteor/server/services/voip-asterisk/lib/Helper.ts
similarity index 100%
rename from apps/meteor/server/services/voip/lib/Helper.ts
rename to apps/meteor/server/services/voip-asterisk/lib/Helper.ts
diff --git a/apps/meteor/server/services/voip/service.ts b/apps/meteor/server/services/voip-asterisk/service.ts
similarity index 89%
rename from apps/meteor/server/services/voip/service.ts
rename to apps/meteor/server/services/voip-asterisk/service.ts
index 93d8bcefd95d..bd17f156851a 100644
--- a/apps/meteor/server/services/voip/service.ts
+++ b/apps/meteor/server/services/voip-asterisk/service.ts
@@ -21,8 +21,8 @@ import { CommandHandler } from './connector/asterisk/CommandHandler';
import { Commands } from './connector/asterisk/Commands';
import { getServerConfigDataFromSettings, voipEnabled } from './lib/Helper';
-export class VoipService extends ServiceClassInternal implements IVoipService {
- protected name = 'voip';
+export class VoipAsteriskService extends ServiceClassInternal implements IVoipService {
+ protected name = 'voip-asterisk';
private logger: Logger;
@@ -33,7 +33,7 @@ export class VoipService extends ServiceClassInternal implements IVoipService {
constructor(db: Db) {
super();
- this.logger = new Logger('VoIPService');
+ this.logger = new Logger('VoIPAsteriskService');
this.commandHandler = new CommandHandler(db);
if (!voipEnabled()) {
this.logger.warn({ msg: 'Voip is not enabled. Cant start the service' });
@@ -45,9 +45,9 @@ export class VoipService extends ServiceClassInternal implements IVoipService {
}
async init(): Promise {
- this.logger.info('Starting VoIP service');
+ this.logger.info('Starting VoIP Asterisk service');
if (this.active) {
- this.logger.warn({ msg: 'VoIP service already started' });
+ this.logger.warn({ msg: 'VoIP Asterisk service already started' });
return;
}
@@ -55,16 +55,16 @@ export class VoipService extends ServiceClassInternal implements IVoipService {
await this.commandHandler.initConnection(CommandType.AMI);
this.active = true;
void api.broadcast('connector.statuschanged', true);
- this.logger.info('VoIP service started');
+ this.logger.info('VoIP Asterisk service started');
} catch (err) {
- this.logger.error({ msg: 'Error initializing VOIP service', err });
+ this.logger.error({ msg: 'Error initializing VOIP Asterisk service', err });
}
}
async stop(): Promise {
- this.logger.info('Stopping VoIP service');
+ this.logger.info('Stopping VoIP Asterisk service');
if (!this.active) {
- this.logger.warn({ msg: 'VoIP service already stopped' });
+ this.logger.warn({ msg: 'VoIP Asterisk service already stopped' });
return;
}
@@ -72,21 +72,21 @@ export class VoipService extends ServiceClassInternal implements IVoipService {
this.commandHandler.stop();
this.active = false;
void api.broadcast('connector.statuschanged', false);
- this.logger.info('VoIP service stopped');
+ this.logger.info('VoIP Asterisk service stopped');
} catch (err) {
- this.logger.error({ msg: 'Error stopping VoIP service', err });
+ this.logger.error({ msg: 'Error stopping VoIP Asterisk service', err });
}
}
async refresh(): Promise {
- this.logger.info('Restarting VoIP service due to settings changes');
+ this.logger.info('Restarting VoIP Asterisk service due to settings changes');
try {
// Disable voip service
await this.stop();
// To then restart it
await this.init();
} catch (err) {
- this.logger.error({ msg: 'Error refreshing VoIP service', err });
+ this.logger.error({ msg: 'Error refreshing VoIP Asterisk service', err });
}
}
diff --git a/apps/meteor/server/settings/file-upload.ts b/apps/meteor/server/settings/file-upload.ts
index 4be9dfd117a7..76e788cda0e2 100644
--- a/apps/meteor/server/settings/file-upload.ts
+++ b/apps/meteor/server/settings/file-upload.ts
@@ -187,6 +187,13 @@ export const createFileUploadSettings = () =>
value: 'AmazonS3',
},
});
+ await this.add('FileUpload_S3_Proxy_UserDataFiles', false, {
+ type: 'boolean',
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'AmazonS3',
+ },
+ });
});
await this.section('Google Cloud Storage', async function () {
@@ -244,6 +251,13 @@ export const createFileUploadSettings = () =>
value: 'GoogleCloudStorage',
},
});
+ await this.add('FileUpload_GoogleStorage_Proxy_UserDataFiles', false, {
+ type: 'boolean',
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'GoogleCloudStorage',
+ },
+ });
});
await this.section('File System', async function () {
@@ -302,6 +316,13 @@ export const createFileUploadSettings = () =>
value: 'Webdav',
},
});
+ await this.add('FileUpload_Webdav_Proxy_UserDataFiles', false, {
+ type: 'boolean',
+ enableQuery: {
+ _id: 'FileUpload_Storage_Type',
+ value: 'Webdav',
+ },
+ });
});
await this.add('FileUpload_Enabled_Direct', true, {
diff --git a/apps/meteor/tests/data/rooms.helper.js b/apps/meteor/tests/data/rooms.helper.js
index e8c2481ffc36..6e74509deab4 100644
--- a/apps/meteor/tests/data/rooms.helper.js
+++ b/apps/meteor/tests/data/rooms.helper.js
@@ -51,7 +51,7 @@ export const asyncCreateRoom = ({ name, type, username, members = [] }) =>
createRoom({ name, type, username, members }).end(resolve);
});
-function actionRoom({ action, type, roomId, extraData = {} }) {
+function actionRoom({ action, type, roomId, overrideCredentials = credentials, extraData = {} }) {
if (!type) {
throw new Error(`"type" is required in "${action}Room" test helper`);
}
@@ -66,7 +66,7 @@ function actionRoom({ action, type, roomId, extraData = {} }) {
return new Promise((resolve) => {
request
.post(api(`${endpoints[type]}.${action}`))
- .set(credentials)
+ .set(overrideCredentials)
.send({
roomId,
...extraData,
@@ -75,7 +75,7 @@ function actionRoom({ action, type, roomId, extraData = {} }) {
});
}
-export const deleteRoom = ({ type, roomId }) => actionRoom({ action: 'delete', type, roomId });
+export const deleteRoom = ({ type, roomId }) => actionRoom({ action: 'delete', type, roomId, overrideCredentials: credentials });
export const closeRoom = ({ type, roomId }) => actionRoom({ action: 'close', type, roomId });
diff --git a/apps/meteor/tests/e2e/administration.spec.ts b/apps/meteor/tests/e2e/administration.spec.ts
index fb9dc655b4c9..48657efea73a 100644
--- a/apps/meteor/tests/e2e/administration.spec.ts
+++ b/apps/meteor/tests/e2e/administration.spec.ts
@@ -184,6 +184,27 @@ test.describe.parallel('administration', () => {
await poAdmin.btnCreateRole.click();
await page.waitForSelector('role=dialog[name="Custom roles"]');
});
+
+ test.describe('Users in role', () => {
+ const channelName = faker.string.uuid();
+ test.beforeAll(async ({ api }) => {
+ // TODO: refactor createChannel utility in order to get channel data when creating
+ const response = await api.post('/channels.create', { name: channelName, members: ['user1'] });
+ const { channel } = await response.json();
+
+ await api.post('/channels.addOwner', { roomId: channel._id, userId: Users.user1.data._id });
+ await api.post('/channels.removeOwner', { roomId: channel._id, userId: Users.admin.data._id });
+ })
+
+ test('admin should be able to get the owners of a room that wasnt created by him', async ({ page }) => {
+ await poAdmin.openRoleByName('Owner').click();
+ await poAdmin.btnUsersInRole.click();
+ await poAdmin.inputRoom.fill(channelName);
+ await page.getByRole('option', { name: channelName }).click();
+
+ await expect(poAdmin.getUserRowByUsername('user1')).toBeVisible();
+ })
+ })
});
test.describe('Mailer', () => {
diff --git a/apps/meteor/tests/e2e/channel-management.spec.ts b/apps/meteor/tests/e2e/channel-management.spec.ts
index ea2632355954..aeaa74773354 100644
--- a/apps/meteor/tests/e2e/channel-management.spec.ts
+++ b/apps/meteor/tests/e2e/channel-management.spec.ts
@@ -247,10 +247,19 @@ test.describe.serial('channel-management', () => {
targetChannel = hugeName;
await page.setViewportSize({ width: 640, height: 460 });
- await expect(page.getByRole('heading', { name: hugeName })).toHaveCSS('width', '423px');
+ await expect(page.getByRole('heading', { name: hugeName })).toHaveCSS('width', '419px');
});
- test('should info contextualbar when clicking on roomName', async ({ page }) => {
+ test('should open sidebar clicking on sidebar toggler', async ({ page }) => {
+ await poHomeChannel.sidenav.openChat(targetChannel);
+
+ await page.setViewportSize({ width: 640, height: 460 });
+ await page.getByRole('button', { name: 'Open sidebar' }).click();
+
+ await expect(page.getByRole('navigation')).toBeVisible();
+ });
+
+ test('should open room info when clicking on roomName', async ({ page }) => {
await poHomeChannel.sidenav.openChat(targetChannel);
await page.getByRole('button', { name: targetChannel }).first().focus();
await page.keyboard.press('Space');
diff --git a/apps/meteor/tests/e2e/e2e-encryption.spec.ts b/apps/meteor/tests/e2e/e2e-encryption.spec.ts
index b63efa2d092f..c1a1ba0d2872 100644
--- a/apps/meteor/tests/e2e/e2e-encryption.spec.ts
+++ b/apps/meteor/tests/e2e/e2e-encryption.spec.ts
@@ -214,66 +214,6 @@ test.describe.serial('e2e-encryption', () => {
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
});
- test('expect create a private encrypted channel and send an attachment with encrypted file description', async ({ page }) => {
- const channelName = faker.string.uuid();
-
- await poHomeChannel.sidenav.openNewByLabel('Channel');
- await poHomeChannel.sidenav.inputChannelName.fill(channelName);
- await poHomeChannel.sidenav.checkboxEncryption.click();
- await poHomeChannel.sidenav.btnCreate.click();
-
- await expect(page).toHaveURL(`/group/${channelName}`);
-
- await poHomeChannel.dismissToast();
-
- await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
-
- await poHomeChannel.content.dragAndDropTxtFile();
- await poHomeChannel.content.descriptionInput.fill('any_description');
- await poHomeChannel.content.fileNameInput.fill('any_file1.txt');
- await poHomeChannel.content.btnModalConfirm.click();
-
- await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
-
- await expect(poHomeChannel.content.getFileDescription).toHaveText('any_description');
- await expect(poHomeChannel.content.lastMessageFileName).toContainText('any_file1.txt');
- });
-
- test('expect create a private encrypted channel and send an attachment with encrypted file description in a thread message', async ({
- page,
- }) => {
- const channelName = faker.string.uuid();
-
- await poHomeChannel.sidenav.openNewByLabel('Channel');
- await poHomeChannel.sidenav.inputChannelName.fill(channelName);
- await poHomeChannel.sidenav.checkboxEncryption.click();
- await poHomeChannel.sidenav.btnCreate.click();
-
- await expect(page).toHaveURL(`/group/${channelName}`);
-
- await poHomeChannel.dismissToast();
-
- await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
-
- await poHomeChannel.content.sendMessage('This is a thread main message.');
-
- await expect(poHomeChannel.content.lastUserMessageBody).toHaveText('This is a thread main message.');
- await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
-
- await page.locator('[data-qa-type="message"]').last().hover();
- await page.locator('role=button[name="Reply in thread"]').click();
-
- await expect(page).toHaveURL(/.*thread/);
-
- await poHomeChannel.content.dragAndDropTxtFileToThread();
- await poHomeChannel.content.descriptionInput.fill('any_description');
- await poHomeChannel.content.fileNameInput.fill('any_file1.txt');
- await poHomeChannel.content.btnModalConfirm.click();
-
- await expect(poHomeChannel.content.lastThreadMessageFileDescription).toHaveText('any_description');
- await expect(poHomeChannel.content.lastThreadMessageFileName).toContainText('any_file1.txt');
- });
-
test('expect placeholder text in place of encrypted message, when E2EE is not setup', async ({ page }) => {
const channelName = faker.string.uuid();
@@ -311,48 +251,6 @@ test.describe.serial('e2e-encryption', () => {
await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
});
- test('expect placeholder text in place of encrypted file description, when E2EE is not setup', async ({ page }) => {
- const channelName = faker.string.uuid();
-
- await poHomeChannel.sidenav.openNewByLabel('Channel');
- await poHomeChannel.sidenav.inputChannelName.fill(channelName);
- await poHomeChannel.sidenav.checkboxEncryption.click();
- await poHomeChannel.sidenav.btnCreate.click();
-
- await expect(page).toHaveURL(`/group/${channelName}`);
-
- await poHomeChannel.dismissToast();
-
- await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
-
- await poHomeChannel.content.dragAndDropTxtFile();
- await poHomeChannel.content.descriptionInput.fill('any_description');
- await poHomeChannel.content.fileNameInput.fill('any_file1.txt');
- await poHomeChannel.content.btnModalConfirm.click();
-
- await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
-
- await expect(poHomeChannel.content.getFileDescription).toHaveText('any_description');
- await expect(poHomeChannel.content.lastMessageFileName).toContainText('any_file1.txt');
-
- // Logout to remove e2ee keys
- await poHomeChannel.sidenav.logout();
-
- // Login again
- await page.locator('role=button[name="Login"]').waitFor();
- await injectInitialData();
- await restoreState(page, Users.admin, { except: ['private_key', 'public_key'] });
-
- await poHomeChannel.sidenav.openChat(channelName);
-
- await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
-
- await expect(poHomeChannel.content.lastUserMessage).toContainText(
- 'This message is end-to-end encrypted. To view it, you must enter your encryption key in your account settings.',
- );
- await expect(poHomeChannel.content.lastUserMessage.locator('.rcx-icon--name-key')).toBeVisible();
- });
-
test.describe('reset keys', () => {
let anotherClientPage: Page;
diff --git a/apps/meteor/tests/e2e/fixtures/userStates.ts b/apps/meteor/tests/e2e/fixtures/userStates.ts
index 4541f69d06e8..e948d6acf5a7 100644
--- a/apps/meteor/tests/e2e/fixtures/userStates.ts
+++ b/apps/meteor/tests/e2e/fixtures/userStates.ts
@@ -6,6 +6,7 @@ import { BASE_URL } from '../config/constants';
export type IUserState = {
data: {
+ _id: string;
username: string;
loginToken: string;
loginExpire: Date;
@@ -27,6 +28,7 @@ function generateContext(username: string): IUserState {
return {
data: {
+ _id: username,
username,
loginToken: token.token,
loginExpire: token.when,
diff --git a/apps/meteor/tests/e2e/message-mentions.spec.ts b/apps/meteor/tests/e2e/message-mentions.spec.ts
index 01fb2dde4217..1d956dfcb735 100644
--- a/apps/meteor/tests/e2e/message-mentions.spec.ts
+++ b/apps/meteor/tests/e2e/message-mentions.spec.ts
@@ -38,6 +38,68 @@ test.describe.serial('message-mentions', () => {
await expect(poHomeChannel.content.messagePopupUsers.locator('role=listitem >> text="here"')).toBeVisible();
});
+ test.describe('Should not allow to send @all mention if permission to do so is disabled', () => {
+ let targetChannel2: string;
+ test.beforeAll(async ({ api }) => {
+ expect((await api.post('/permissions.update', { permissions: [{ '_id': 'mention-all', 'roles': [] }] })).status()).toBe(200);
+ });
+
+ test.afterAll(async ({ api }) => {
+ expect((await api.post('/permissions.update', { permissions: [{ '_id': 'mention-all', 'roles': ['admin', 'owner', 'moderator', 'user'] }] })).status()).toBe(200);
+ await deleteChannel(api, targetChannel2);
+ });
+
+ test('expect to receive an error as notification when sending @all while permission is disabled', async ({ page }) => {
+ const adminPage = new HomeChannel(page);
+
+ await test.step('create private room', async () => {
+ targetChannel2 = faker.string.uuid();
+
+ await poHomeChannel.sidenav.openNewByLabel('Channel');
+ await poHomeChannel.sidenav.inputChannelName.type(targetChannel2);
+ await poHomeChannel.sidenav.btnCreate.click();
+
+ await expect(page).toHaveURL(`/group/${targetChannel2}`);
+ });
+ await test.step('receive notify message', async () => {
+ await adminPage.sidenav.openChat(targetChannel2);
+ await adminPage.content.dispatchSlashCommand('@all');
+ await expect(adminPage.content.lastUserMessage).toContainText('Notify all in this room is not allowed');
+ });
+ });
+ });
+
+ test.describe('Should not allow to send @here mention if permission to do so is disabled', () => {
+ let targetChannel2: string;
+ test.beforeAll(async ({ api }) => {
+ expect((await api.post('/permissions.update', { permissions: [{ '_id': 'mention-here', 'roles': [] }] })).status()).toBe(200);
+ });
+
+ test.afterAll(async ({ api }) => {
+ expect((await api.post('/permissions.update', { permissions: [{ '_id': 'mention-here', 'roles': ['admin', 'owner', 'moderator', 'user'] }] })).status()).toBe(200);
+ await deleteChannel(api, targetChannel2);
+ });
+
+ test('expect to receive an error as notification when sending here while permission is disabled', async ({ page }) => {
+ const adminPage = new HomeChannel(page);
+
+ await test.step('create private room', async () => {
+ targetChannel2 = faker.string.uuid();
+
+ await poHomeChannel.sidenav.openNewByLabel('Channel');
+ await poHomeChannel.sidenav.inputChannelName.type(targetChannel2);
+ await poHomeChannel.sidenav.btnCreate.click();
+
+ await expect(page).toHaveURL(`/group/${targetChannel2}`);
+ });
+ await test.step('receive notify message', async () => {
+ await adminPage.sidenav.openChat(targetChannel2);
+ await adminPage.content.dispatchSlashCommand('@here');
+ await expect(adminPage.content.lastUserMessage).toContainText('Notify all in this room is not allowed');
+ });
+ });
+ });
+
test.describe('users not in channel', () => {
let targetChannel: string;
let targetChannel2: string;
diff --git a/apps/meteor/tests/e2e/messaging.spec.ts b/apps/meteor/tests/e2e/messaging.spec.ts
index edc322c574a0..226b75ecc9a8 100644
--- a/apps/meteor/tests/e2e/messaging.spec.ts
+++ b/apps/meteor/tests/e2e/messaging.spec.ts
@@ -105,7 +105,7 @@ test.describe.serial('Messaging', () => {
await expect(page.locator('[data-qa-type="message"]').last()).not.toBeFocused();
});
- test('should focus on the recent message when moving the focus on the list and theres no previous focus', async ({ page }) => {
+ test('should focus the latest message when moving the focus on the list and theres no previous focus', async ({ page }) => {
await poHomeChannel.sidenav.openChat(targetChannel);
await page.getByRole('button', { name: targetChannel }).first().focus();
@@ -115,7 +115,7 @@ test.describe.serial('Messaging', () => {
await page.keyboard.press('Tab');
await expect(page.locator('[data-qa-type="message"]').last()).toBeFocused();
- await page.getByRole('button', { name: targetChannel }).first().click();
+ await page.getByRole('button', { name: targetChannel }).first().focus();
// move focus to the list again
await page.keyboard.press('Tab');
diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
index a3d105136efe..163a0f40f2b3 100644
--- a/apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
+++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-current-chats.spec.ts
@@ -23,6 +23,7 @@ test.describe('OC - Current Chats [Auto Selection]', async () => {
let departments: Awaited>[];
let conversations: Awaited>[];
let agents: Awaited>[];
+ let tags: Awaited>[];
// Allow manual on hold
test.beforeAll(async ({ api }) => {
@@ -61,9 +62,9 @@ test.describe('OC - Current Chats [Auto Selection]', async () => {
// Create tags
test.beforeAll(async ({ api }) => {
- const promises = await Promise.all([createTag(api, 'tagA'), createTag(api, 'tagB')]);
+ tags = await Promise.all([createTag(api, { name: 'tagA' }), createTag(api, { name: 'tagB' })]);
- promises.forEach((res) => expect(res.status()).toBe(200));
+ tags.forEach((res) => expect(res.response.status()).toBe(200));
});
// Create rooms
@@ -120,10 +121,11 @@ test.describe('OC - Current Chats [Auto Selection]', async () => {
...departments.map((department) => department.delete()),
// Delete agents
...agents.map((agent) => agent.delete()),
+ // Delete tags
+ ...tags.map((tag) => tag.delete()),
// Reset setting
api.post('/settings/Livechat_allow_manual_on_hold', { value: false }),
api.post('/settings/Livechat_allow_manual_on_hold_upon_agent_engagement_only', { value: true }),
- // TODO: remove tags
]);
});
diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-livechat-tab-communication.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-livechat-tab-communication.spec.ts
index 17e32fd51d70..27c800fd0a5f 100644
--- a/apps/meteor/tests/e2e/omnichannel/omnichannel-livechat-tab-communication.spec.ts
+++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-livechat-tab-communication.spec.ts
@@ -35,6 +35,8 @@ test.describe('OC - Livechat - Cross Tab Communication', () => {
test.afterAll(async () => {
await poHomeOmnichannel.page?.close();
await agent.delete();
+ await pageLivechat1.page.close();
+ await pageLivechat2.page.close();
});
test('OC - Livechat - Send messages, close chat and start again 2 tabs', async () => {
diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-tags.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-tags.spec.ts
new file mode 100644
index 000000000000..4ad7bde6d760
--- /dev/null
+++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-tags.spec.ts
@@ -0,0 +1,139 @@
+import { faker } from '@faker-js/faker';
+import type { Page } from '@playwright/test';
+
+import { IS_EE } from '../config/constants';
+import { Users } from '../fixtures/userStates';
+import { OmnichannelTags } from '../page-objects';
+import { createAgent } from '../utils/omnichannel/agents';
+import { createDepartment } from '../utils/omnichannel/departments';
+import { createTag } from '../utils/omnichannel/tags';
+import { test, expect } from '../utils/test';
+
+test.use({ storageState: Users.admin.state });
+
+test.describe('OC - Manage Tags', () => {
+ test.skip(!IS_EE, 'OC - Manage Tags > Enterprise Edition Only');
+
+ let poOmnichannelTags: OmnichannelTags;
+
+ let department: Awaited>;
+ let department2: Awaited>;
+ let agent: Awaited>;
+
+ test.beforeAll(async ({ api }) => {
+ department = await createDepartment(api);
+ department2 = await createDepartment(api);
+ });
+
+ test.beforeAll(async ({ api }) => {
+ agent = await createAgent(api, 'user2');
+ });
+
+ test.afterAll(async () => {
+ await department.delete();
+ await agent.delete();
+ });
+
+ test.beforeEach(async ({ page }: { page: Page }) => {
+ poOmnichannelTags = new OmnichannelTags(page);
+ });
+
+ test('OC - Manage Tags - Create Tag', async ({ page }) => {
+ const tagName = faker.string.uuid();
+
+ await page.goto('/omnichannel');
+ await poOmnichannelTags.sidenav.linkTags.click();
+
+ await test.step('expect correct form default state', async () => {
+ await poOmnichannelTags.btnCreateTag.click();
+ await expect(poOmnichannelTags.contextualBar).toBeVisible();
+ await expect(poOmnichannelTags.btnSave).toBeDisabled();
+ await expect(poOmnichannelTags.btnCancel).toBeEnabled();
+ await poOmnichannelTags.btnCancel.click();
+ await expect(poOmnichannelTags.contextualBar).not.toBeVisible();
+ });
+
+ await test.step('expect to create new tag', async () => {
+ await poOmnichannelTags.btnCreateTag.click();
+ await poOmnichannelTags.inputName.fill(tagName);
+ await poOmnichannelTags.selectDepartment(department.data);
+ await poOmnichannelTags.btnSave.click();
+ await expect(poOmnichannelTags.contextualBar).not.toBeVisible();
+
+ await test.step('expect tag to have been created', async () => {
+ await poOmnichannelTags.search(tagName);
+ await expect(poOmnichannelTags.findRowByName(tagName)).toBeVisible();
+ });
+ });
+
+ await test.step('expect to delete tag', async () => {
+ await test.step('expect to be able to cancel delete', async () => {
+ await poOmnichannelTags.btnDeleteByName(tagName).click();
+ await expect(poOmnichannelTags.confirmDeleteModal).toBeVisible();
+ await poOmnichannelTags.btnCancelDeleteModal.click();
+ await expect(poOmnichannelTags.confirmDeleteModal).not.toBeVisible();
+ });
+
+ await test.step('expect to confirm delete', async () => {
+ await poOmnichannelTags.btnDeleteByName(tagName).click();
+ await expect(poOmnichannelTags.confirmDeleteModal).toBeVisible();
+ await poOmnichannelTags.btnConfirmDeleteModal.click();
+ await expect(poOmnichannelTags.confirmDeleteModal).not.toBeVisible();
+ await expect(page.locator('h3 >> text="No results found"')).toBeVisible();
+ });
+ });
+ });
+
+ test('OC - Manage Tags - Edit tag departments', async ({ api, page }) => {
+ const tag = await test.step('expect to create new tag', async () => {
+ const { data: tag } = await createTag(api, {
+ name: faker.string.uuid(),
+ departments: [department.data._id],
+ });
+
+ return tag;
+ });
+
+ await page.goto('/omnichannel');
+ await poOmnichannelTags.sidenav.linkTags.click();
+
+ await test.step('expect to add tag departments', async () => {
+ await poOmnichannelTags.search(tag.name);
+ await poOmnichannelTags.findRowByName(tag.name).click();
+ await expect(poOmnichannelTags.contextualBar).toBeVisible();
+ await poOmnichannelTags.selectDepartment({ name: department2.data.name, _id: department2.data._id });
+ await poOmnichannelTags.btnSave.click();
+ });
+
+ await test.step('expect department to be in the chosen departments list', async () => {
+ await poOmnichannelTags.search(tag.name);
+ await poOmnichannelTags.findRowByName(tag.name).click();
+ await expect(poOmnichannelTags.contextualBar).toBeVisible();
+ await expect(page.getByRole('option', { name: department2.data.name })).toBeVisible();
+ await poOmnichannelTags.btnContextualbarClose.click();
+ });
+
+ await test.step('expect to remove tag departments', async () => {
+ await poOmnichannelTags.search(tag.name);
+ await poOmnichannelTags.findRowByName(tag.name).click();
+ await expect(poOmnichannelTags.contextualBar).toBeVisible();
+ await poOmnichannelTags.selectDepartment({ name: department2.data.name, _id: department2.data._id });
+ await poOmnichannelTags.btnSave.click();
+ });
+
+ await test.step('expect department to not be in the chosen departments list', async () => {
+ await poOmnichannelTags.search(tag.name);
+ await poOmnichannelTags.findRowByName(tag.name).click();
+ await expect(poOmnichannelTags.contextualBar).toBeVisible();
+ await expect(page.getByRole('option', { name: department2.data.name })).toBeHidden();
+ });
+
+ await test.step('expect to delete tag', async () => {
+ await poOmnichannelTags.btnDeleteByName(tag.name).click();
+ await expect(poOmnichannelTags.confirmDeleteModal).toBeVisible();
+ await poOmnichannelTags.btnConfirmDeleteModal.click();
+ await expect(poOmnichannelTags.confirmDeleteModal).not.toBeVisible();
+ await expect(page.locator('h3 >> text="No results found"')).toBeVisible();
+ });
+ });
+});
\ No newline at end of file
diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-triggers-after-registration.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-triggers-after-registration.spec.ts
index 07939182715a..539037219e62 100644
--- a/apps/meteor/tests/e2e/omnichannel/omnichannel-triggers-after-registration.spec.ts
+++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-triggers-after-registration.spec.ts
@@ -66,6 +66,39 @@ test.describe('OC - Livechat New Chat Triggers - After Registration', () => {
});
});
+ test.describe('OC - Livechat Triggers - After Registration - Reload', async () => {
+ test('expect trigger message after registration', async () => {
+ await test.step('expect trigger message after registration to be visible', async () => {
+ await poLiveChat.page.goto('/livechat');
+ await poLiveChat.openAnyLiveChat();
+ await poLiveChat.sendMessage(newUser, false);
+ await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
+ })
+
+ await test.step('expect trigger message after registration to be visible after reload', async () => {
+ await poLiveChat.page.reload();
+ await poLiveChat.openAnyLiveChat();
+ await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
+ })
+
+ await test.step('expect to close room and reload', async () => {
+ await poLiveChat.onlineAgentMessage.type('message_after_trigger');
+ await poLiveChat.btnSendMessageToOnlineAgent.click();
+ await expect(poLiveChat.txtChatMessage('message_after_trigger')).toBeVisible();
+ await poLiveChat.closeChat();
+
+ await expect(poLiveChat.btnNewChat).toBeVisible();
+ await poLiveChat.startNewChat();
+ await poLiveChat.page.reload()
+ })
+
+ await test.step('expect trigger message after registration to be visible after reload on new chat', async () => {
+ await poLiveChat.openAnyLiveChat();
+ await expect(poLiveChat.txtChatMessage(triggerMessage)).toBeVisible();
+ })
+ });
+ });
+
test.describe('OC - Livechat New Chat Triggers - After Registration, clear Local storage', async () => {
test.beforeAll(async ({ api }) => {
await api.post('/settings/Livechat_clear_local_storage_when_chat_ended', { value: true });
diff --git a/apps/meteor/tests/e2e/omnichannel/omnichannel-units.spec.ts b/apps/meteor/tests/e2e/omnichannel/omnichannel-units.spec.ts
index 5e24dc8622ae..146885aef55e 100644
--- a/apps/meteor/tests/e2e/omnichannel/omnichannel-units.spec.ts
+++ b/apps/meteor/tests/e2e/omnichannel/omnichannel-units.spec.ts
@@ -18,6 +18,7 @@ test.describe('OC - Manage Units', () => {
let poOmnichannelUnits: OmnichannelUnits;
let department: Awaited>;
+ let department2: Awaited>;
let agent: Awaited>;
@@ -25,6 +26,7 @@ test.describe('OC - Manage Units', () => {
test.beforeAll(async ({ api }) => {
department = await createDepartment(api);
+ department2 = await createDepartment(api);
});
test.beforeAll(async ({ api }) => {
@@ -37,20 +39,20 @@ test.describe('OC - Manage Units', () => {
test.afterAll(async () => {
await department.delete();
+ await department2.delete();
await monitor.delete();
await agent.delete();
});
test.beforeEach(async ({ page }: { page: Page }) => {
poOmnichannelUnits = new OmnichannelUnits(page);
+ await page.goto('/omnichannel');
+ await poOmnichannelUnits.sidenav.linkUnits.click();
});
test('OC - Manage Units - Create Unit', async ({ page }) => {
const unitName = faker.string.uuid();
- await page.goto('/omnichannel');
- await poOmnichannelUnits.sidenav.linkUnits.click();
-
await test.step('expect correct form default state', async () => {
await poOmnichannelUnits.btnCreateUnit.click();
await expect(poOmnichannelUnits.contextualBar).toBeVisible();
@@ -76,49 +78,30 @@ test.describe('OC - Manage Units', () => {
});
await test.step('expect to delete unit', async () => {
- await test.step('expect confirm delete unit', async () => {
- await test.step('expect to be able to cancel delete', async () => {
- await poOmnichannelUnits.btnDeleteByName(unitName).click();
- await expect(poOmnichannelUnits.confirmDeleteModal).toBeVisible();
- await poOmnichannelUnits.btnCancelDeleteModal.click();
- await expect(poOmnichannelUnits.confirmDeleteModal).not.toBeVisible();
- });
-
- await test.step('expect to confirm delete', async () => {
- await poOmnichannelUnits.btnDeleteByName(unitName).click();
- await expect(poOmnichannelUnits.confirmDeleteModal).toBeVisible();
- await poOmnichannelUnits.btnConfirmDeleteModal.click();
- await expect(poOmnichannelUnits.confirmDeleteModal).not.toBeVisible();
- });
- });
-
- await test.step('expect to have been deleted', async () => {
- if (await poOmnichannelUnits.inputSearch.isVisible()) {
- await poOmnichannelUnits.search(unitName);
- await expect(poOmnichannelUnits.findRowByName(unitName)).not.toBeVisible();
- } else {
- await expect(page.locator('h3 >> text="No units yet"')).toBeVisible();
- }
- });
+ await poOmnichannelUnits.btnDeleteByName(unitName).click();
+ await expect(poOmnichannelUnits.confirmDeleteModal).toBeVisible();
+ await poOmnichannelUnits.btnConfirmDeleteModal.click();
+ await expect(poOmnichannelUnits.confirmDeleteModal).not.toBeVisible();
+ await expect(page.locator('h3 >> text="No units yet"')).toBeVisible();
});
});
- test('OC - Manage Units - Edit unit', async ({ api, page }) => {
+ test('OC - Manage Units - Edit unit name', async ({ api, page }) => {
+ const unitName = faker.string.uuid();
const editedUnitName = faker.string.uuid();
const unit = await test.step('expect to create new unit', async () => {
- const { data: unit } = await createOrUpdateUnit(api, {
- name: faker.string.uuid(),
+ const { data: newUnit } = await createOrUpdateUnit(api, {
+ name: unitName,
visibility: 'public',
monitors: [{ monitorId: monitor.data._id, username: 'user2' }],
departments: [{ departmentId: department.data._id }],
});
- return unit;
+ return newUnit;
});
- await page.goto('/omnichannel');
- await poOmnichannelUnits.sidenav.linkUnits.click();
+ await page.reload();
await test.step('expect to edit unit', async () => {
await poOmnichannelUnits.search(unit.name);
@@ -138,29 +121,75 @@ test.describe('OC - Manage Units', () => {
await poOmnichannelUnits.findRowByName(editedUnitName).click();
await expect(poOmnichannelUnits.contextualBar).toBeVisible();
- await test.step('expect confirm delete unit', async () => {
- await test.step('expect to be able to cancel delete', async () => {
- await poOmnichannelUnits.btnDelete.click();
- await expect(poOmnichannelUnits.confirmDeleteModal).toBeVisible();
- await poOmnichannelUnits.btnCancelDeleteModal.click();
- await expect(poOmnichannelUnits.confirmDeleteModal).not.toBeVisible();
- });
-
- await test.step('expect to confirm delete', async () => {
- await poOmnichannelUnits.btnDelete.click();
- await expect(poOmnichannelUnits.confirmDeleteModal).toBeVisible();
- await poOmnichannelUnits.btnConfirmDeleteModal.click();
- await expect(poOmnichannelUnits.confirmDeleteModal).not.toBeVisible();
- });
-
- await expect(poOmnichannelUnits.contextualBar).not.toBeVisible();
+ await test.step('expect to confirm delete', async () => {
+ await poOmnichannelUnits.btnDelete.click();
+ await expect(poOmnichannelUnits.confirmDeleteModal).toBeVisible();
+ await poOmnichannelUnits.btnConfirmDeleteModal.click();
+ await expect(poOmnichannelUnits.confirmDeleteModal).not.toBeVisible();
});
- await test.step('expect to have been deleted', async () => {
- await expect(poOmnichannelUnits.inputSearch).toBeVisible();
- await poOmnichannelUnits.inputSearch.clear();
- await expect(page.locator('h3 >> text="No units yet"')).toBeVisible();
- });
+ await expect(poOmnichannelUnits.contextualBar).not.toBeVisible();
});
});
+
+ test('OC - Manage Units - Edit unit departments', async ({ api, page }) => {
+ const unit = await test.step('expect to create new unit', async () => {
+ const { data: unit } = await createOrUpdateUnit(api, {
+ name: faker.string.uuid(),
+ visibility: 'public',
+ monitors: [{ monitorId: monitor.data._id, username: 'user2' }],
+ departments: [{ departmentId: department.data._id }],
+ });
+
+ return unit;
+ });
+
+ await page.reload();
+
+ await test.step('expect to add unit departments', async () => {
+ await poOmnichannelUnits.search(unit.name);
+ await poOmnichannelUnits.findRowByName(unit.name).click();
+ await expect(poOmnichannelUnits.contextualBar).toBeVisible();
+ await poOmnichannelUnits.selectDepartment({ name: department2.data.name, _id: department2.data._id });
+ await poOmnichannelUnits.btnSave.click();
+ });
+
+ await test.step('expect department to be in the chosen departments list', async () => {
+ await poOmnichannelUnits.search(unit.name);
+ await poOmnichannelUnits.findRowByName(unit.name).click();
+ await expect(poOmnichannelUnits.contextualBar).toBeVisible();
+ await expect(page.getByRole('option', { name: department2.data.name })).toBeVisible();
+ await poOmnichannelUnits.btnContextualbarClose.click();
+ });
+
+ await test.step('expect to remove unit departments', async () => {
+ await poOmnichannelUnits.search(unit.name);
+ await poOmnichannelUnits.findRowByName(unit.name).click();
+ await expect(poOmnichannelUnits.contextualBar).toBeVisible();
+ await poOmnichannelUnits.selectDepartment({ name: department2.data.name, _id: department2.data._id });
+ await poOmnichannelUnits.selectMonitor('user2');
+ await poOmnichannelUnits.btnSave.click();
+ });
+
+ await test.step('expect department to not be in the chosen departments list', async () => {
+ await poOmnichannelUnits.search(unit.name);
+ await poOmnichannelUnits.findRowByName(unit.name).click();
+ await expect(poOmnichannelUnits.contextualBar).toBeVisible();
+ await expect(page.getByRole('option', { name: department2.data.name })).toBeHidden();
+ await poOmnichannelUnits.btnContextualbarClose.click();
+ });
+
+ await test.step('expect to delete unit', async () => {
+ await poOmnichannelUnits.findRowByName(unit.name).click();
+ await expect(poOmnichannelUnits.contextualBar).toBeVisible();
+ await test.step('expect to confirm delete', async () => {
+ await poOmnichannelUnits.btnDelete.click();
+ await expect(poOmnichannelUnits.confirmDeleteModal).toBeVisible();
+ await poOmnichannelUnits.btnConfirmDeleteModal.click();
+ await expect(poOmnichannelUnits.confirmDeleteModal).not.toBeVisible();
+ });
+
+ await expect(poOmnichannelUnits.contextualBar).not.toBeVisible();
+ });
+ })
});
diff --git a/apps/meteor/tests/e2e/page-objects/admin.ts b/apps/meteor/tests/e2e/page-objects/admin.ts
index b036fa339575..5f61d2ef43e1 100644
--- a/apps/meteor/tests/e2e/page-objects/admin.ts
+++ b/apps/meteor/tests/e2e/page-objects/admin.ts
@@ -177,11 +177,27 @@ export class Admin {
return this.page.locator('//label[@title="Assets_logo"]/following-sibling::span >> role=button[name="Delete"]');
}
+ get inputAssetsLogo(): Locator {
+ return this.page.locator('//label[@title="Assets_logo"]/following-sibling::span >> input[type="file"]');
+ }
+
get btnCreateRole(): Locator {
return this.page.locator('button[name="New role"]');
}
- get inputAssetsLogo(): Locator {
- return this.page.locator('//label[@title="Assets_logo"]/following-sibling::span >> input[type="file"]');
+ openRoleByName(name: string): Locator {
+ return this.page.getByRole('table').getByRole('button', { name });
+ }
+
+ get btnUsersInRole(): Locator {
+ return this.page.getByRole('dialog').getByRole('button', { name: 'Users in role' });
+ }
+
+ get inputRoom(): Locator {
+ return this.page.locator('input[placeholder="Room"]');
+ }
+
+ getUserRowByUsername(username: string): Locator {
+ return this.page.locator('tr', { hasText: username })
}
}
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 5b66c03454d1..01237e68cfbc 100644
--- a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts
+++ b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts
@@ -247,7 +247,7 @@ export class HomeContent {
await this.page.locator(`role=dialog[name="Emoji picker"] >> role=tabpanel >> role=button[name="${emoji}"]`).click();
}
- async dragAndDropTxtFileToThread(): Promise {
+ async dragAndDropTxtFile(): Promise {
const contract = await fs.readFile('./tests/e2e/fixtures/files/any_file.txt', 'utf-8');
const dataTransfer = await this.page.evaluateHandle((contract) => {
const data = new DataTransfer();
@@ -258,16 +258,16 @@ export class HomeContent {
return data;
}, contract);
- await this.inputThreadMessage.dispatchEvent('dragenter', { dataTransfer });
+ await this.inputMessage.dispatchEvent('dragenter', { dataTransfer });
await this.page.locator('[role=dialog][data-qa="DropTargetOverlay"]').dispatchEvent('drop', { dataTransfer });
}
- async dragAndDropTxtFile(): Promise {
- const contract = await fs.readFile('./tests/e2e/fixtures/files/any_file.txt', 'utf-8');
+ async dragAndDropLstFile(): Promise {
+ const contract = await fs.readFile('./tests/e2e/fixtures/files/lst-test.lst', 'utf-8');
const dataTransfer = await this.page.evaluateHandle((contract) => {
const data = new DataTransfer();
- const file = new File([`${contract}`], 'any_file.txt', {
+ const file = new File([`${contract}`], 'lst-test.lst', {
type: 'text/plain',
});
data.items.add(file);
@@ -279,18 +279,18 @@ export class HomeContent {
await this.page.locator('[role=dialog][data-qa="DropTargetOverlay"]').dispatchEvent('drop', { dataTransfer });
}
- async dragAndDropLstFile(): Promise {
- const contract = await fs.readFile('./tests/e2e/fixtures/files/lst-test.lst', 'utf-8');
+ async dragAndDropTxtFileToThread(): Promise {
+ const contract = await fs.readFile('./tests/e2e/fixtures/files/any_file.txt', 'utf-8');
const dataTransfer = await this.page.evaluateHandle((contract) => {
const data = new DataTransfer();
- const file = new File([`${contract}`], 'lst-test.lst', {
+ const file = new File([`${contract}`], 'any_file.txt', {
type: 'text/plain',
});
data.items.add(file);
return data;
}, contract);
- await this.inputMessage.dispatchEvent('dragenter', { dataTransfer });
+ await this.inputThreadMessage.dispatchEvent('dragenter', { dataTransfer });
await this.page.locator('[role=dialog][data-qa="DropTargetOverlay"]').dispatchEvent('drop', { dataTransfer });
}
diff --git a/apps/meteor/tests/e2e/page-objects/fragments/omnichannel-sidenav.ts b/apps/meteor/tests/e2e/page-objects/fragments/omnichannel-sidenav.ts
index 04af530ea734..63fc3c391935 100644
--- a/apps/meteor/tests/e2e/page-objects/fragments/omnichannel-sidenav.ts
+++ b/apps/meteor/tests/e2e/page-objects/fragments/omnichannel-sidenav.ts
@@ -70,4 +70,8 @@ export class OmnichannelSidenav {
get linkLivechatAppearance(): Locator {
return this.page.locator('a[href="/omnichannel/appearance"]');
}
+
+ get linkTags(): Locator {
+ return this.page.locator('a[href="/omnichannel/tags"]');
+ }
}
diff --git a/apps/meteor/tests/e2e/page-objects/index.ts b/apps/meteor/tests/e2e/page-objects/index.ts
index b8f335a6f92d..5d8284fb420b 100644
--- a/apps/meteor/tests/e2e/page-objects/index.ts
+++ b/apps/meteor/tests/e2e/page-objects/index.ts
@@ -16,4 +16,5 @@ export * from './omnichannel-units';
export * from './home-omnichannel';
export * from './omnichannel-monitors';
export * from './omnichannel-settings';
+export * from './omnichannel-tags';
export * from './utils';
diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel-tags.ts b/apps/meteor/tests/e2e/page-objects/omnichannel-tags.ts
new file mode 100644
index 000000000000..064877aab1c6
--- /dev/null
+++ b/apps/meteor/tests/e2e/page-objects/omnichannel-tags.ts
@@ -0,0 +1,71 @@
+import type { Locator } from '@playwright/test';
+
+import { OmnichannelAdministration } from './omnichannel-administration';
+
+export class OmnichannelTags extends OmnichannelAdministration {
+ get btnCreateTag(): Locator {
+ return this.page.locator('header').locator('role=button[name="Create tag"]');
+ }
+
+ get contextualBar(): Locator {
+ return this.page.locator('div[role="dialog"].rcx-vertical-bar');
+ }
+
+ get btnSave(): Locator {
+ return this.contextualBar.locator('role=button[name="Save"]');
+ }
+
+ get btnCancel(): Locator {
+ return this.contextualBar.locator('role=button[name="Cancel"]');
+ }
+
+ get inputName(): Locator {
+ return this.page.locator('[name="name"]');
+ }
+
+ get inputSearch(): Locator {
+ return this.page.locator('[placeholder="Search"]');
+ }
+
+ get confirmDeleteModal(): Locator {
+ return this.page.locator('dialog:has(h2:has-text("Are you sure?"))');
+ }
+
+ get btnCancelDeleteModal(): Locator {
+ return this.confirmDeleteModal.locator('role=button[name="Cancel"]');
+ }
+
+ get btnConfirmDeleteModal(): Locator {
+ return this.confirmDeleteModal.locator('role=button[name="Delete"]');
+ }
+
+ get btnContextualbarClose(): Locator {
+ return this.contextualBar.locator('button[aria-label="Close"]');
+ }
+
+ btnDeleteByName(name: string): Locator {
+ return this.page.locator(`role=link[name="${name} Remove"] >> role=button`);
+ }
+
+ findRowByName(name: string): Locator {
+ return this.page.locator(`tr:has-text("${name}")`);
+ }
+
+ get inputDepartments(): Locator {
+ return this.page.locator('input[placeholder="Select an option"]');
+ }
+
+ private selectOption(name: string): Locator {
+ return this.page.locator(`[role=option][value="${name}"]`);
+ }
+
+ async search(text: string) {
+ await this.inputSearch.fill(text);
+ }
+
+ async selectDepartment({ name, _id }: { name: string; _id: string }) {
+ await this.inputDepartments.click();
+ await this.inputDepartments.fill(name);
+ await this.selectOption(_id).click();
+ }
+}
diff --git a/apps/meteor/tests/e2e/page-objects/omnichannel-units.ts b/apps/meteor/tests/e2e/page-objects/omnichannel-units.ts
index 5aa41afe449a..f5d02e2150c7 100644
--- a/apps/meteor/tests/e2e/page-objects/omnichannel-units.ts
+++ b/apps/meteor/tests/e2e/page-objects/omnichannel-units.ts
@@ -35,6 +35,10 @@ export class OmnichannelUnits extends OmnichannelAdministration {
return this.page.locator('button', { has: this.page.locator('select[name="visibility"]') });
}
+ get btnContextualbarClose(): Locator {
+ return this.page.locator('[data-qa="ContextualbarActionClose"]');
+ }
+
private selectOption(name: string) {
return this.page.locator(`[role=option][value="${name}"]`);
}
diff --git a/apps/meteor/tests/e2e/read-receipts.spec.ts b/apps/meteor/tests/e2e/read-receipts.spec.ts
new file mode 100644
index 000000000000..524b79d4e919
--- /dev/null
+++ b/apps/meteor/tests/e2e/read-receipts.spec.ts
@@ -0,0 +1,69 @@
+import { IS_EE } from './config/constants';
+import { createAuxContext } from './fixtures/createAuxContext';
+import { Users } from './fixtures/userStates';
+import { HomeChannel } from './page-objects';
+import { createTargetChannel, setSettingValueById } from './utils';
+import { expect, test } from './utils/test';
+
+test.use({ storageState: Users.admin.state });
+
+test.describe.serial('read-receipts', () => {
+ let poHomeChannel: HomeChannel;
+ let targetChannel: string;
+
+ test.skip(!IS_EE, 'Enterprise Only');
+
+ test.beforeAll(async ({ api }) => {
+ targetChannel = await createTargetChannel(api);
+ });
+
+ test.beforeEach(async ({ page }) => {
+ poHomeChannel = new HomeChannel(page);
+
+ await page.goto('/home');
+ });
+
+ test.describe('read receipt settings disabled', async () => {
+ test('should not show read receipts item menu', async ({ page }) => {
+ await poHomeChannel.sidenav.openChat(targetChannel);
+ await poHomeChannel.content.sendMessage('hello world');
+ await poHomeChannel.content.openLastMessageMenu();
+ expect(page.locator('role=menuitem[name="Read receipts"]')).not.toBeVisible;
+ });
+ });
+
+ test.describe('read receipts enabled', async () => {
+ test.beforeAll(async ({ api }) => {
+ await setSettingValueById(api, 'Message_Read_Receipt_Enabled', true);
+ await setSettingValueById(api, 'Message_Read_Receipt_Store_Users', true);
+ });
+
+ test.afterAll(async ({ api }) => {
+ await setSettingValueById(api, 'Message_Read_Receipt_Enabled', false);
+ await setSettingValueById(api, 'Message_Read_Receipt_Store_Users', false);
+ });
+
+ test('should show read receipts message sent status in the sent message', async ({ browser }) => {
+ const { page } = await createAuxContext(browser, Users.user1);
+ const auxContext = { page, poHomeChannel: new HomeChannel(page) };
+ await auxContext.poHomeChannel.sidenav.openChat(targetChannel);
+ await auxContext.poHomeChannel.content.sendMessage('hello admin');
+
+ await expect(auxContext.poHomeChannel.content.lastUserMessage.getByRole('status', { name: 'Message sent' })).toBeVisible();
+ await auxContext.page.close();
+ });
+
+ test('should show read receipts message viewed status in the sent message', async () => {
+ await poHomeChannel.sidenav.openChat(targetChannel);
+ await expect(poHomeChannel.content.lastUserMessage.getByRole('status', { name: 'Message viewed' })).toBeVisible();
+ });
+
+ test('should show the reads receipt modal with the users who read the message', async ({ page }) => {
+ await poHomeChannel.sidenav.openChat(targetChannel);
+ await poHomeChannel.content.openLastMessageMenu();
+ await page.locator('role=menuitem[name="Read receipts"]').click();
+
+ await expect(page.getByRole('dialog').getByRole('listitem')).toHaveCount(2);
+ });
+ });
+});
diff --git a/apps/meteor/tests/e2e/threads.spec.ts b/apps/meteor/tests/e2e/threads.spec.ts
index 99dad85131f7..a7fa19422ff5 100644
--- a/apps/meteor/tests/e2e/threads.spec.ts
+++ b/apps/meteor/tests/e2e/threads.spec.ts
@@ -15,7 +15,6 @@ test.describe.serial('Threads', () => {
await page.goto('/home');
await poHomeChannel.sidenav.openChat(targetChannel);
});
-
test('expect thread message preview if alsoSendToChannel checkbox is checked', async ({ page }) => {
await poHomeChannel.content.sendMessage('this is a message for reply');
await page.locator('[data-qa-type="message"]').last().hover();
@@ -68,6 +67,20 @@ test.describe.serial('Threads', () => {
await expect(poHomeChannel.content.lastThreadMessageText).toContainText('This is a thread message also sent in channel');
});
});
+ test('expect upload a file attachment in thread with description', async ({ page }) => {
+ await poHomeChannel.content.lastThreadMessagePreviewText.click();
+
+ await expect(page).toHaveURL(/.*thread/);
+
+ await poHomeChannel.content.dragAndDropTxtFileToThread();
+ await poHomeChannel.content.descriptionInput.fill('any_description');
+ await poHomeChannel.content.fileNameInput.fill('any_file1.txt');
+ await poHomeChannel.content.btnModalConfirm.click();
+
+ await expect(poHomeChannel.content.lastThreadMessageFileDescription).toHaveText('any_description');
+ await expect(poHomeChannel.content.lastThreadMessageFileName).toContainText('any_file1.txt');
+ });
+
test.describe('thread message actions', () => {
test.beforeEach(async ({ page }) => {
poHomeChannel = new HomeChannel(page);
@@ -128,7 +141,7 @@ test.describe.serial('Threads', () => {
await context.grantPermissions(['clipboard-read', 'clipboard-write']);
await poHomeChannel.content.openLastThreadMessageMenu();
await page.locator('role=menuitem[name="Copy text"]').click();
-
+
const clipboardText = await page.evaluate("navigator.clipboard.readText()");
expect(clipboardText).toBe('this is a message for reply');
});
diff --git a/apps/meteor/tests/e2e/translations.spec.ts b/apps/meteor/tests/e2e/translations.spec.ts
index cd7fd1355018..05854fcb71a5 100644
--- a/apps/meteor/tests/e2e/translations.spec.ts
+++ b/apps/meteor/tests/e2e/translations.spec.ts
@@ -6,36 +6,50 @@ import { test, expect } from './utils/test';
test.use({ storageState: Users.admin.state });
test.describe('Translations', () => {
- test.beforeAll(async ({ api }) => {
- expect((await setUserPreferences(api, { language: '' })).status()).toBe(200);
- expect((await setSettingValueById(api, 'Language', 'en')).status()).toBe(200);
- expect((await setSettingValueById(api, 'Site_Name', 'Rocket.Chat')).status()).toBe(200);
+ test.beforeAll(async ({ api }) => {
+ expect((await setUserPreferences(api, { language: '' })).status()).toBe(200);
+ expect((await setSettingValueById(api, 'Language', 'en')).status()).toBe(200);
+ expect((await setSettingValueById(api, 'Site_Name', 'Rocket.Chat')).status()).toBe(200);
});
- test.afterAll(async ({ api }) => {
- expect((await setUserPreferences(api, { language: '' })).status()).toBe(200);
- expect((await setSettingValueById(api, 'Language', 'en')).status()).toBe(200);
+ test.afterAll(async ({ api }) => {
+ expect((await setUserPreferences(api, { language: '' })).status()).toBe(200);
+ expect((await setSettingValueById(api, 'Language', 'en')).status()).toBe(200);
+ });
+
+ test("expect to display text in the user's preference language", async ({ page, api }) => {
+ await page.goto('/home');
+ await page.waitForTimeout(5000);
+ await expect(page.locator('h2')).toHaveText('Welcome to Rocket.Chat');
+
+ const response = page.waitForResponse('**/i18n/pt-BR.json');
+ expect((await setUserPreferences(api, { language: 'pt-BR' })).status()).toBe(200);
+ await response;
+ await expect(page.locator('h2')).toHaveText('Bem-vindo ao Rocket.Chat');
+ expect((await setUserPreferences(api, { language: '' })).status()).toBe(200);
+ });
+
+ test('expect to keep chosen language after refresh', async ({ page, api }) => {
+ await page.goto('/home');
+ await expect(page.locator('h2')).toHaveText('Welcome to Rocket.Chat');
+
+ const response = page.waitForResponse('**/i18n/pt-BR.json');
+ expect((await setUserPreferences(api, { language: 'pt-BR' })).status()).toBe(200);
+ await response;
+ await expect(page.locator('h2')).toHaveText('Bem-vindo ao Rocket.Chat');
+
+ // Test if selected language remaing after refresh
+ await page.goto('/home');
+ await expect(page.locator('h2')).toHaveText('Bem-vindo ao Rocket.Chat');
+
+ expect((await setUserPreferences(api, { language: '' })).status()).toBe(200);
+ });
+
+ test.describe('Browser', async () => {
+ test.use({ locale: 'pt-BR' });
+ test("expect to display text in the browser's language", async ({ page }) => {
+ await page.goto('/home');
+ await expect(page.locator('h2')).toHaveText('Bem-vindo ao Rocket.Chat');
+ });
});
-
- test('expect to display text in the user\'s preference language', async ({ page, api }) => {
- await page.goto('/home');
- await page.waitForTimeout(5000);
- await expect(page.locator('h2')).toHaveText('Welcome to Rocket.Chat');
-
- const response = page.waitForResponse('**/i18n/pt-BR.json');
- expect((await setUserPreferences(api, { language: 'pt-BR' })).status()).toBe(200);
- await response;
- await expect(page.locator('h2')).toHaveText('Bem-vindo ao Rocket.Chat');
- expect((await setUserPreferences(api, { language: '' })).status()).toBe(200);
- });
-
- // Browser language not working on CI for some reason. This test passes locally.
- test.describe.skip('Browser', async () => {
- test.use({ locale: 'pt-BR' });
- test('expect to display text in the browser\'s language', async ({ page }) => {
- await page.goto('/home');
- await page.waitForTimeout(5000);
- await expect(page.locator('h2')).toHaveText('Bem-vindo ao Rocket.Chat');
- });
- });
});
diff --git a/apps/meteor/tests/e2e/utils/index.ts b/apps/meteor/tests/e2e/utils/index.ts
index 1939b8b2cb11..9f83fc0ae246 100644
--- a/apps/meteor/tests/e2e/utils/index.ts
+++ b/apps/meteor/tests/e2e/utils/index.ts
@@ -1 +1,2 @@
export * from './create-target-channel';
+export * from './setSettingValueById';
diff --git a/apps/meteor/tests/e2e/utils/omnichannel/tags.ts b/apps/meteor/tests/e2e/utils/omnichannel/tags.ts
index 2df9e57e1c7a..078ca8dd02f7 100644
--- a/apps/meteor/tests/e2e/utils/omnichannel/tags.ts
+++ b/apps/meteor/tests/e2e/utils/omnichannel/tags.ts
@@ -1,6 +1,37 @@
+import { ILivechatTag } from '@rocket.chat/core-typings';
+
import { BaseTest } from '../test';
+import { parseMeteorResponse } from './utils';
+
+type CreateTagParams = {
+ id?: string | null;
+ name?: string;
+ description?: string;
+ departments?: { departmentId: string }[];
+};
-export const createTag = async (api: BaseTest['api'], name: string) =>
- api.post('/method.call/livechat:saveTag', {
- message: JSON.stringify({ msg: 'method', id: '33', method: 'livechat:saveTag', params: [null, { name, description: '' }, []] }),
+const removeTag = async (api: BaseTest['api'], id: string) =>
+ api.post('/method.call/omnichannel:removeTag', {
+ message: JSON.stringify({ msg: 'method', id: '33', method: 'livechat:removeTag', params: [id] }),
});
+
+export const createTag = async (
+ api: BaseTest['api'],
+ { id = null, name, description = '', departments = [] }: CreateTagParams = {},
+ ) => {
+ const response = await api.post('/method.call/livechat:saveTag', {
+ message: JSON.stringify({
+ msg: 'method',
+ id: '33',
+ method: 'livechat:saveTag',
+ params: [id, { name, description }, departments]})
+ });
+
+ const tag = await parseMeteorResponse(response);
+
+ return {
+ response,
+ data: tag,
+ delete: async () => removeTag(api, tag?._id),
+ };
+};
diff --git a/apps/meteor/tests/end-to-end/api/09-rooms.js b/apps/meteor/tests/end-to-end/api/09-rooms.js
index ba1ff2c9d729..b9b8f71036af 100644
--- a/apps/meteor/tests/end-to-end/api/09-rooms.js
+++ b/apps/meteor/tests/end-to-end/api/09-rooms.js
@@ -9,7 +9,8 @@ import { getCredentials, api, request, credentials } from '../../data/api-data.j
import { sendSimpleMessage, deleteMessage } from '../../data/chat.helper';
import { imgURL, lstURL, svgLogoFileName, svgLogoURL } from '../../data/interactions';
import { getSettingValueById, updateEEPermission, updatePermission, updateSetting } from '../../data/permissions.helper';
-import { closeRoom, createRoom, deleteRoom } from '../../data/rooms.helper';
+import { createRoom, deleteRoom } from '../../data/rooms.helper';
+import { deleteTeam } from '../../data/teams.helper';
import { password } from '../../data/user';
import { createUser, deleteUser, login } from '../../data/users.helper';
import { IS_EE } from '../../e2e/config/constants';
@@ -50,12 +51,13 @@ describe('[Rooms]', function () {
describe('/rooms.saveNotification:', () => {
let testChannel;
- it('create an channel', (done) => {
- createRoom({ type: 'c', name: `channel.test.${Date.now()}-${Math.random()}` }).end((err, res) => {
- testChannel = res.body.channel;
- done();
- });
+
+ before(async () => {
+ testChannel = (await createRoom({ type: 'c', name: `channel.test.${Date.now()}-${Math.random()}` })).body.channel;
});
+
+ after(() => deleteRoom({ type: 'c', roomId: testChannel._id }));
+
it('/rooms.saveNotification:', (done) => {
request
.post(api('rooms.saveNotification'))
@@ -83,10 +85,13 @@ describe('[Rooms]', function () {
let testChannel;
let user;
let userCredentials;
+ const testChannelName = `channel.test.upload.${Date.now()}-${Math.random()}`;
let blockedMediaTypes;
+
before(async () => {
user = await createUser({ joinDefaultChannels: false });
userCredentials = await login(user.username, password);
+ testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel;
blockedMediaTypes = await getSettingValueById('FileUpload_MediaTypeBlackList');
const newBlockedMediaTypes = blockedMediaTypes
.split(',')
@@ -95,23 +100,16 @@ describe('[Rooms]', function () {
await updateSetting('FileUpload_MediaTypeBlackList', newBlockedMediaTypes);
});
- after(async () => {
- await deleteUser(user);
- user = undefined;
-
- await updateSetting('FileUpload_Restrict_to_room_members', false);
- await updateSetting('FileUpload_ProtectFiles', true);
- await updateSetting('FileUpload_MediaTypeBlackList', blockedMediaTypes);
- });
-
- const testChannelName = `channel.test.upload.${Date.now()}-${Math.random()}`;
+ after(() =>
+ Promise.all([
+ deleteRoom({ type: 'c', roomId: testChannel._id }),
+ deleteUser(user),
+ updateSetting('FileUpload_Restrict_to_room_members', true),
+ updateSetting('FileUpload_ProtectFiles', true),
+ updateSetting('FileUpload_MediaTypeBlackList', blockedMediaTypes),
+ ]),
+ );
- it('create an channel', (done) => {
- createRoom({ type: 'c', name: testChannelName }).end((err, res) => {
- testChannel = res.body.channel;
- done();
- });
- });
it("don't upload a file to room with file field other than file", (done) => {
request
.post(api(`rooms.upload/${testChannel._id}`))
@@ -301,44 +299,18 @@ describe('[Rooms]', function () {
await request.get(thumbUrl).set(credentials).expect('Content-Type', 'image/jpeg');
});
-
- it('should correctly save e2ee file description and properties', async () => {
- await request
- .post(api(`rooms.upload/${testChannel._id}`))
- .set(credentials)
- .field('t', 'e2e')
- .field('e2e', 'pending')
- .field('description', 'some_file_description')
- .attach('file', imgURL)
- .expect('Content-Type', 'application/json')
- .expect(200)
- .expect((res) => {
- expect(res.body).to.have.property('success', true);
- expect(res.body).to.have.property('message');
- expect(res.body.message).to.have.property('attachments');
- expect(res.body.message.attachments).to.be.an('array').of.length(1);
- expect(res.body.message.attachments[0]).to.have.property('image_type', 'image/png');
- expect(res.body.message.attachments[0]).to.have.property('title', '1024x1024.png');
- expect(res.body.message).to.have.property('files');
- expect(res.body.message.files).to.be.an('array').of.length(2);
- expect(res.body.message.files[0]).to.have.property('type', 'image/png');
- expect(res.body.message.files[0]).to.have.property('name', '1024x1024.png');
- expect(res.body.message.attachments[0]).to.have.property('description', 'some_file_description');
- expect(res.body.message).to.have.property('t', 'e2e');
- expect(res.body.message).to.have.property('e2e', 'pending');
- });
- });
});
describe('/rooms.favorite', () => {
let testChannel;
const testChannelName = `channel.test.${Date.now()}-${Math.random()}`;
- it('create an channel', (done) => {
- createRoom({ type: 'c', name: testChannelName }).end((err, res) => {
- testChannel = res.body.channel;
- done();
- });
+
+ before(async () => {
+ testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel;
});
+
+ after(() => deleteRoom({ type: 'c', roomId: testChannel._id }));
+
it('should favorite the room when send favorite: true by roomName', (done) => {
request
.post(api('rooms.favorite'))
@@ -415,6 +387,15 @@ describe('[Rooms]', function () {
});
describe('/rooms.nameExists', () => {
+ let testChannel;
+ const testChannelName = `channel.test.${Date.now()}-${Math.random()}`;
+
+ before(async () => {
+ testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel;
+ });
+
+ after(() => deleteRoom({ type: 'c', roomId: testChannel._id }));
+
it('should return 401 unauthorized when user is not logged in', (done) => {
request
.get(api('rooms.nameExists'))
@@ -426,15 +407,6 @@ describe('[Rooms]', function () {
.end(done);
});
- // eslint-disable-next-line no-unused-vars
- let testChannel;
- const testChannelName = `channel.test.${Date.now()}-${Math.random()}`;
- it('create an channel', (done) => {
- createRoom({ type: 'c', name: testChannelName }).end((err, res) => {
- testChannel = res.body.channel;
- done();
- });
- });
it('should return true if this room name exists', (done) => {
request
.get(api('rooms.nameExists'))
@@ -469,72 +441,31 @@ describe('[Rooms]', function () {
describe('[/rooms.cleanHistory]', () => {
let publicChannel;
let privateChannel;
- let directMessageChannel;
+ let directMessageChannelId;
let user;
- beforeEach((done) => {
- const username = `user.test.${Date.now()}`;
- const email = `${username}@rocket.chat`;
- request
- .post(api('users.create'))
- .set(credentials)
- .send({ email, name: username, username, password })
- .end((err, res) => {
- user = res.body.user;
- done(err);
- });
- });
-
let userCredentials;
- beforeEach((done) => {
- request
- .post(api('login'))
- .send({
- user: user.username,
- password,
- })
- .expect('Content-Type', 'application/json')
- .expect(200)
- .expect((res) => {
- userCredentials = {};
- userCredentials['X-Auth-Token'] = res.body.data.authToken;
- userCredentials['X-User-Id'] = res.body.data.userId;
- })
- .end(done);
- });
- afterEach((done) => {
- request
- .post(api('users.delete'))
- .set(credentials)
- .send({
- userId: user._id,
- })
- .end(done);
- user = undefined;
- });
- before(async () => {
+
+ beforeEach(async () => {
+ user = await createUser();
+ userCredentials = await login(user.username, password);
await updateSetting('Message_ShowDeletedStatus', true);
+
+ publicChannel = (await createRoom({ type: 'c', name: `testeChannel${+new Date()}` })).body.channel;
+ privateChannel = (await createRoom({ type: 'p', name: `testPrivateChannel${+new Date()}` })).body.group;
+ directMessageChannelId = (await createRoom({ type: 'd', username: 'rocket.cat' })).body.room.rid;
});
- after(async () => {
- await updateSetting('Message_ShowDeletedStatus', false);
- });
- it('create a public channel', (done) => {
- createRoom({ type: 'c', name: `testeChannel${+new Date()}` }).end((err, res) => {
- publicChannel = res.body.channel;
- done();
- });
- });
- it('create a private channel', (done) => {
- createRoom({ type: 'p', name: `testPrivateChannel${+new Date()}` }).end((err, res) => {
- privateChannel = res.body.group;
- done(err);
- });
- });
- it('create a direct message', (done) => {
- createRoom({ type: 'd', username: 'rocket.cat' }).end((err, res) => {
- directMessageChannel = res.body.room.rid;
- done(err);
- });
- });
+
+ afterEach(() =>
+ Promise.all([
+ deleteUser(user),
+ deleteRoom({ type: 'c', roomId: publicChannel._id }),
+ deleteRoom({ type: 'p', roomId: privateChannel._id }),
+ deleteRoom({ type: 'd', roomId: directMessageChannelId }),
+ ]),
+ );
+
+ after(() => updateSetting('Message_ShowDeletedStatus', false));
+
it('should return success when send a valid public channel', (done) => {
request
.post(api('rooms.cleanHistory'))
@@ -654,7 +585,7 @@ describe('[Rooms]', function () {
.post(api('rooms.cleanHistory'))
.set(credentials)
.send({
- roomId: directMessageChannel,
+ roomId: directMessageChannelId,
latest: '2016-12-09T13:42:25.304Z',
oldest: '2016-08-30T13:42:25.304Z',
})
@@ -670,7 +601,7 @@ describe('[Rooms]', function () {
.post(api('rooms.cleanHistory'))
.set(userCredentials)
.send({
- roomId: directMessageChannel,
+ roomId: directMessageChannelId,
latest: '2016-12-09T13:42:25.304Z',
oldest: '2016-08-30T13:42:25.304Z',
})
@@ -705,27 +636,21 @@ describe('[Rooms]', function () {
];
const testChannelName = `channel.test.${Date.now()}-${Math.random()}`;
const testGroupName = `group.test.${Date.now()}-${Math.random()}`;
- after((done) => {
- closeRoom({ type: 'd', roomId: testDM._id }).then(done);
- });
- it('create an channel', (done) => {
- createRoom({ type: 'c', name: testChannelName }).end((err, res) => {
- testChannel = res.body.channel;
- done();
- });
- });
- it('create a group', (done) => {
- createRoom({ type: 'p', name: testGroupName }).end((err, res) => {
- testGroup = res.body.group;
- done();
- });
- });
- it('create a Direct message room with rocket.cat', (done) => {
- createRoom({ type: 'd', username: 'rocket.cat' }).end((err, res) => {
- testDM = res.body.room;
- done();
- });
+
+ before(async () => {
+ testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel;
+ testGroup = (await createRoom({ type: 'p', name: testGroupName })).body.group;
+ testDM = (await createRoom({ type: 'd', username: 'rocket.cat' })).body.room;
});
+
+ after(() =>
+ Promise.all([
+ deleteRoom({ type: 'd', roomId: testDM._id }),
+ deleteRoom({ type: 'c', roomId: testChannel._id }),
+ deleteRoom({ type: 'p', roomId: testGroup._id }),
+ ]),
+ );
+
it('should return the info about the created channel correctly searching by roomId', (done) => {
request
.get(api('rooms.info'))
@@ -823,29 +748,30 @@ describe('[Rooms]', function () {
let testChannel;
let testGroup;
let testDM;
- const testChannelName = `channel.test.${Date.now()}-${Math.random()}`;
- const testGroupName = `group.test.${Date.now()}-${Math.random()}`;
- after((done) => {
- closeRoom({ type: 'd', roomId: testDM._id }).then(done);
- });
- it('create an channel', (done) => {
- createRoom({ type: 'c', name: testChannelName }).end((err, res) => {
- testChannel = res.body.channel;
- done();
- });
- });
- it('create a group', (done) => {
- createRoom({ type: 'p', name: testGroupName }).end((err, res) => {
- testGroup = res.body.group;
- done();
- });
- });
- it('create a Direct message room with rocket.cat', (done) => {
- createRoom({ type: 'd', username: 'rocket.cat' }).end((err, res) => {
- testDM = res.body.room;
- done();
- });
- });
+ let user2;
+ let user2Credentials;
+ const testChannelName = `channel.leave.${Date.now()}-${Math.random()}`;
+ const testGroupName = `group.leave.${Date.now()}-${Math.random()}`;
+
+ before(async () => {
+ user2 = await createUser();
+ user2Credentials = await login(user2.username, password);
+ testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel;
+ testGroup = (await createRoom({ type: 'p', name: testGroupName })).body.group;
+ testDM = (await createRoom({ type: 'd', username: user2.username })).body.room;
+ });
+
+ after(() =>
+ Promise.all([
+ deleteRoom({ type: 'd', roomId: testDM._id }),
+ deleteRoom({ type: 'c', roomId: testChannel._id }),
+ deleteRoom({ type: 'p', roomId: testGroup._id }),
+ updatePermission('leave-c', ['admin', 'user', 'bot', 'anonymous', 'app']),
+ updatePermission('leave-p', ['admin', 'user', 'bot', 'anonymous', 'app']),
+ deleteUser(user2),
+ ]),
+ );
+
it('should return an Error when trying leave a DM room', (done) => {
request
.post(api('rooms.leave'))
@@ -920,69 +846,52 @@ describe('[Rooms]', function () {
.end(done);
});
});
- it('should leave the public channel when the room has at least another owner and the user has the necessary permission(leave-c)', (done) => {
- updatePermission('leave-c', ['admin']).then(() => {
- request
- .post(api('channels.addAll'))
- .set(credentials)
- .send({
- roomId: testChannel._id,
- })
- .end(() => {
- request
- .post(api('channels.addOwner'))
- .set(credentials)
- .send({
- roomId: testChannel._id,
- userId: 'rocket.cat',
- })
- .end(() => {
- request
- .post(api('rooms.leave'))
- .set(credentials)
- .send({
- roomId: testChannel._id,
- })
- .expect(200)
- .expect((res) => {
- expect(res.body).to.have.property('success', true);
- })
- .end(done);
- });
- });
+ it('should leave the public channel when the room has at least another owner and the user has the necessary permission(leave-c)', async () => {
+ await updatePermission('leave-c', ['admin']);
+ await request.post(api('channels.addAll')).set(credentials).send({
+ roomId: testChannel._id,
+ });
+
+ await request.post(api('channels.addOwner')).set(credentials).send({
+ roomId: testChannel._id,
+ userId: user2._id,
+ });
+
+ await request
+ .post(api('rooms.leave'))
+ .set(credentials)
+ .send({
+ roomId: testChannel._id,
+ })
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ });
+
+ await request.post(api('channels.addOwner')).set(user2Credentials).send({
+ roomId: testChannel._id,
+ userId: credentials['X-User-Id'],
});
});
- it('should leave the private group when the room has at least another owner and the user has the necessary permission(leave-p)', (done) => {
- updatePermission('leave-p', ['admin']).then(() => {
- request
- .post(api('groups.addAll'))
- .set(credentials)
- .send({
- roomId: testGroup._id,
- })
- .end(() => {
- request
- .post(api('groups.addOwner'))
- .set(credentials)
- .send({
- roomId: testGroup._id,
- userId: 'rocket.cat',
- })
- .end(() => {
- request
- .post(api('rooms.leave'))
- .set(credentials)
- .send({
- roomId: testGroup._id,
- })
- .expect(200)
- .expect((res) => {
- expect(res.body).to.have.property('success', true);
- })
- .end(done);
- });
- });
+ it('should leave the private group when the room has at least another owner and the user has the necessary permission(leave-p)', async () => {
+ await updatePermission('leave-p', ['user']);
+ await request.post(api('groups.addAll')).set(credentials).send({
+ roomId: testGroup._id,
+ });
+ await request.post(api('groups.addOwner')).set(credentials).send({
+ roomId: testGroup._id,
+ userId: user2._id,
});
+ await request
+ .post(api('rooms.leave'))
+ .set(user2Credentials)
+ .send({
+ roomId: testGroup._id,
+ })
+ .expect(200)
+ .expect((res) => {
+ expect(res.body).to.have.property('success', true);
+ });
});
});
@@ -990,17 +899,27 @@ describe('[Rooms]', function () {
let testChannel;
const testChannelName = `channel.test.${Date.now()}-${Math.random()}`;
let messageSent;
- before((done) => {
- createRoom({ type: 'c', name: testChannelName }).end((err, res) => {
- testChannel = res.body.channel;
- sendSimpleMessage({
+ let privateTeam;
+
+ before(async () => {
+ testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel;
+ messageSent = (
+ await sendSimpleMessage({
roomId: testChannel._id,
- }).end((err, res) => {
- messageSent = res.body.message;
- done();
- });
- });
+ })
+ ).body.message;
});
+
+ after(() =>
+ Promise.all([
+ deleteRoom({ type: 'c', roomId: testChannel._id }),
+ updateSetting('Discussion_enabled', true),
+ updatePermission('start-discussion', ['admin', 'user', 'guest', 'app']),
+ updatePermission('start-discussion-other-user', ['admin', 'user', 'guest', 'app']),
+ deleteTeam(credentials, privateTeam.name),
+ ]),
+ );
+
it('should throw an error when the user tries to create a discussion and the feature is disabled', (done) => {
updateSetting('Discussion_enabled', false).then(() => {
request
@@ -1190,8 +1109,6 @@ describe('[Rooms]', function () {
});
describe('it should create a *private* discussion if the parent channel is public and inside a private team', async () => {
- let privateTeam;
-
it('should create a team', (done) => {
request
.post(api('teams.create'))
@@ -1251,24 +1168,25 @@ describe('[Rooms]', function () {
describe('/rooms.getDiscussions', () => {
let testChannel;
const testChannelName = `channel.test.getDiscussions${Date.now()}-${Math.random()}`;
- let discussion;
- before((done) => {
- createRoom({ type: 'c', name: testChannelName }).end((err, res) => {
- testChannel = res.body.channel;
- request
- .post(api('rooms.createDiscussion'))
- .set(credentials)
- .send({
- prid: testChannel._id,
- t_name: `discussion-create-from-tests-${testChannel.name}`,
- })
- .end((err, res) => {
- discussion = res.body.discussion;
- done();
- });
- });
+
+ before(async () => {
+ testChannel = (await createRoom({ type: 'c', name: testChannelName })).body.channel;
+ await request
+ .post(api('rooms.createDiscussion'))
+ .set(credentials)
+ .send({
+ prid: testChannel._id,
+ t_name: `discussion-create-from-tests-${testChannel.name}`,
+ });
});
- after(() => closeRoom({ type: 'p', roomId: discussion._id }));
+
+ after(() =>
+ Promise.all([
+ deleteRoom({ type: 'c', roomId: testChannel._id }),
+ updatePermission('view-c-room', ['admin', 'user', 'bot', 'app', 'anonymous']),
+ ]),
+ );
+
it('should throw an error when the user tries to gets a list of discussion without a required parameter "roomId"', (done) => {
request
.get(api('rooms.getDiscussions'))
@@ -1339,6 +1257,7 @@ describe('[Rooms]', function () {
.end(done);
});
});
+
describe('[/rooms.autocomplete.channelAndPrivate.withPagination]', () => {
it('should return an error when the required parameter "selector" is not provided', (done) => {
request
@@ -1411,25 +1330,27 @@ describe('[Rooms]', function () {
.end(done);
});
});
+
describe('[/rooms.autocomplete.adminRooms]', () => {
let testGroup;
const testGroupName = `channel.test.adminRoom${Date.now()}-${Math.random()}`;
const name = {
name: testGroupName,
};
- before((done) => {
- createRoom({ type: 'p', name: testGroupName }).end((err, res) => {
- testGroup = res.body.group;
- request
- .post(api('rooms.createDiscussion'))
- .set(credentials)
- .send({
- prid: testGroup._id,
- t_name: `${testGroupName}-discussion`,
- })
- .end(done);
- });
+
+ before(async () => {
+ testGroup = (await createRoom({ type: 'p', name: testGroupName })).body.group;
+ await request
+ .post(api('rooms.createDiscussion'))
+ .set(credentials)
+ .send({
+ prid: testGroup._id,
+ t_name: `${testGroupName}-discussion`,
+ });
});
+
+ after(() => Promise.all([deleteRoom({ type: 'p', roomId: testGroup._id }), updateEEPermission('can-audit', ['admin', 'auditor'])]));
+
(IS_EE ? it : it.skip)('should return an error when the required parameter "selector" is not provided', (done) => {
updateEEPermission('can-audit', ['admin']).then(() => {
request
@@ -1457,7 +1378,7 @@ describe('[Rooms]', function () {
})
.end(done);
});
- it('should return FIX the rooms to fill auto complete', (done) => {
+ it('should return the rooms to fill auto complete', (done) => {
request
.get(api('rooms.autocomplete.adminRooms?'))
.set(credentials)
@@ -1474,6 +1395,7 @@ describe('[Rooms]', function () {
.end(done);
});
});
+
describe('/rooms.adminRooms', () => {
const suffix = `test-${Date.now()}`;
const fnameRoom = `Ελληνικά-${suffix}`;
@@ -1482,22 +1404,23 @@ describe('[Rooms]', function () {
let testGroup;
- before((done) => {
- updateSetting('UI_Allow_room_names_with_special_chars', true).then(() => {
- createRoom({ type: 'p', name: fnameRoom }).end((err, res) => {
- testGroup = res.body.group;
- request
- .post(api('rooms.createDiscussion'))
- .set(credentials)
- .send({
- prid: testGroup._id,
- t_name: discussionRoomName,
- })
- .end(done);
- });
+ before(async () => {
+ await updateSetting('UI_Allow_room_names_with_special_chars', true);
+ testGroup = (await createRoom({ type: 'p', name: fnameRoom })).body.group;
+ await request.post(api('rooms.createDiscussion')).set(credentials).send({
+ prid: testGroup._id,
+ t_name: discussionRoomName,
});
});
+ after(() =>
+ Promise.all([
+ updateSetting('UI_Allow_room_names_with_special_chars', false),
+ deleteRoom({ type: 'p', roomId: testGroup._id }),
+ updatePermission('view-room-administration', ['admin']),
+ ]),
+ );
+
it('should throw an error when the user tries to gets a list of discussion and he cannot access the room', (done) => {
updatePermission('view-room-administration', []).then(() => {
request
@@ -1671,6 +1594,8 @@ describe('[Rooms]', function () {
roomId = result.body.room.rid;
});
+ after(async () => Promise.all([updateSetting('UI_Use_Real_Name', false), deleteRoom({ type: 'd', roomId }), deleteUser(testUser)]));
+
it('should update group name if user changes username', async () => {
await updateSetting('UI_Use_Real_Name', false);
await request
@@ -1726,10 +1651,14 @@ describe('[Rooms]', function () {
describe('/rooms.delete', () => {
let testChannel;
+
before('create an channel', async () => {
const result = await createRoom({ type: 'c', name: `channel.test.${Date.now()}-${Math.random()}` });
testChannel = result.body.channel;
});
+
+ after(() => deleteRoom({ type: 'c', roomId: testChannel._id }));
+
it('should throw an error when roomId is not provided', (done) => {
request
.post(api('rooms.delete'))
diff --git a/apps/meteor/tests/mocks/client/marketplace.tsx b/apps/meteor/tests/mocks/client/marketplace.tsx
new file mode 100644
index 000000000000..f0147509cb12
--- /dev/null
+++ b/apps/meteor/tests/mocks/client/marketplace.tsx
@@ -0,0 +1,69 @@
+import { faker } from '@faker-js/faker';
+import { AppClientManager } from '@rocket.chat/apps-engine/client/AppClientManager';
+import { AppsEngineUIHost } from '@rocket.chat/apps-engine/client/AppsEngineUIHost';
+import type { IExternalComponentRoomInfo } from '@rocket.chat/apps-engine/client/definition';
+import React from 'react';
+import type { ReactNode } from 'react';
+
+import { AppsContext, type IAppsOrchestrator } from '../../../client/contexts/AppsContext';
+import { AsyncStatePhase } from '../../../client/lib/asyncState';
+import { createFakeApp, createFakeExternalComponentRoomInfo, createFakeExternalComponentUserInfo } from '../data';
+
+class MockedAppsEngineUIHost extends AppsEngineUIHost {
+ public async getClientRoomInfo(): Promise {
+ return createFakeExternalComponentRoomInfo();
+ }
+
+ public async getClientUserInfo() {
+ return createFakeExternalComponentUserInfo();
+ }
+}
+
+class MockedAppClientManager extends AppClientManager {}
+
+export const mockAppsOrchestrator = () => {
+ const appsEngineUIHost = new MockedAppsEngineUIHost();
+ const manager = new MockedAppClientManager(appsEngineUIHost);
+
+ const orchestrator: IAppsOrchestrator = {
+ load: () => Promise.resolve(),
+ getAppClientManager: () => manager,
+ handleError: () => undefined,
+ getInstalledApps: async () => [],
+ getAppsFromMarketplace: async () => [],
+ getAppsOnBundle: async () => [],
+ getApp: () => Promise.reject(new Error('not implemented')),
+ setAppSettings: async () => undefined,
+ installApp: () => Promise.reject(new Error('not implemented')),
+ updateApp: () => Promise.reject(new Error('not implemented')),
+ buildExternalUrl: () => Promise.reject(new Error('not implemented')),
+ buildExternalAppRequest: () => Promise.reject(new Error('not implemented')),
+ buildIncompatibleExternalUrl: () => Promise.reject(new Error('not implemented')),
+ getCategories: () => Promise.reject(new Error('not implemented')),
+ };
+
+ return orchestrator;
+};
+
+export const mockedAppsContext = (children: ReactNode) => (
+ Promise.resolve(),
+ orchestrator: mockAppsOrchestrator(),
+ }}
+ >
+ {children}
+
+);
diff --git a/apps/meteor/tests/mocks/data.ts b/apps/meteor/tests/mocks/data.ts
index 182c7cbede5d..812de9579b4e 100644
--- a/apps/meteor/tests/mocks/data.ts
+++ b/apps/meteor/tests/mocks/data.ts
@@ -1,5 +1,7 @@
import { faker } from '@faker-js/faker';
-import type { IMessage, IRoom, ISubscription, IUser } from '@rocket.chat/core-typings';
+import type { IExternalComponentRoomInfo, IExternalComponentUserInfo } from '@rocket.chat/apps-engine/client/definition';
+import type { LicenseInfo } from '@rocket.chat/core-typings';
+import { AppSubscriptionStatus, type App, type IMessage, type IRoom, type ISubscription, type IUser } from '@rocket.chat/core-typings';
import { parse } from '@rocket.chat/message-parser';
import type { MessageWithMdEnforced } from '../../client/lib/parseMessageTextToAstMarkdown';
@@ -89,3 +91,140 @@ export function createFakeMessageWithMd(overrides?: Partial = {}): App {
+ const appId = faker.database.mongodbObjectId();
+
+ const app: App = {
+ id: appId,
+ iconFileData: faker.image.dataUri(),
+ name: faker.commerce.productName(),
+ appRequestStats: {
+ appId: partialApp.id ?? appId,
+ totalSeen: faker.number.int({ min: 0, max: 100 }),
+ totalUnseen: faker.number.int({ min: 0, max: 100 }),
+ },
+ author: {
+ name: faker.company.name(),
+ homepage: faker.internet.url(),
+ support: faker.internet.email(),
+ },
+ description: faker.lorem.paragraph(),
+ shortDescription: faker.lorem.sentence(),
+ privacyPolicySummary: faker.lorem.sentence(),
+ detailedDescription: {
+ raw: faker.lorem.paragraph(),
+ rendered: faker.lorem.paragraph(),
+ },
+ detailedChangelog: {
+ raw: faker.lorem.paragraph(),
+ rendered: faker.lorem.paragraph(),
+ },
+ categories: [],
+ version: faker.system.semver(),
+ versionIncompatible: faker.datatype.boolean(),
+ price: faker.number.float({ min: 0, max: 1000 }),
+ purchaseType: faker.helpers.arrayElement(['buy', 'subscription']),
+ pricingPlans: [],
+ iconFileContent: faker.image.dataUri(),
+ isSubscribed: faker.datatype.boolean(),
+ bundledIn: [],
+ marketplaceVersion: faker.system.semver(),
+ get latest() {
+ return app;
+ },
+ subscriptionInfo: {
+ typeOf: faker.lorem.word(),
+ status: faker.helpers.enumValue(AppSubscriptionStatus),
+ statusFromBilling: faker.datatype.boolean(),
+ isSeatBased: faker.datatype.boolean(),
+ seats: faker.number.int({ min: 0, max: 50 }),
+ maxSeats: faker.number.int({ min: 50, max: 100 }),
+ license: {
+ license: faker.lorem.word(),
+ version: faker.number.int({ min: 0, max: 3 }),
+ expireDate: faker.date.future().toISOString(),
+ },
+ startDate: faker.date.past().toISOString(),
+ periodEnd: faker.date.future().toISOString(),
+ endDate: faker.date.future().toISOString(),
+ isSubscribedViaBundle: faker.datatype.boolean(),
+ },
+ tosLink: faker.internet.url(),
+ privacyLink: faker.internet.url(),
+ modifiedAt: faker.date.recent().toISOString(),
+ permissions: faker.helpers.multiple(() => ({
+ name: faker.hacker.verb(),
+ required: faker.datatype.boolean(),
+ })),
+ languages: faker.helpers.multiple(() => faker.location.countryCode()),
+ createdDate: faker.date.past().toISOString(),
+ private: faker.datatype.boolean(),
+ documentationUrl: faker.internet.url(),
+ migrated: faker.datatype.boolean(),
+ ...partialApp,
+ };
+
+ return app;
+}
+
+export const createFakeExternalComponentUserInfo = (partial: Partial = {}): IExternalComponentUserInfo => ({
+ id: faker.database.mongodbObjectId(),
+ username: faker.internet.userName(),
+ avatarUrl: faker.image.avatar(),
+ ...partial,
+});
+
+export const createFakeExternalComponentRoomInfo = (partial: Partial = {}): IExternalComponentRoomInfo => ({
+ id: faker.database.mongodbObjectId(),
+ members: faker.helpers.multiple(createFakeExternalComponentUserInfo),
+ slugifiedName: faker.lorem.slug(),
+ ...partial,
+});
+
+export const createFakeLicenseInfo = (partial: Partial> = {}): Omit => ({
+ activeModules: faker.helpers.arrayElements([
+ 'auditing',
+ 'canned-responses',
+ 'ldap-enterprise',
+ 'livechat-enterprise',
+ 'voip-enterprise',
+ 'omnichannel-mobile-enterprise',
+ 'engagement-dashboard',
+ 'push-privacy',
+ 'scalability',
+ 'teams-mention',
+ 'saml-enterprise',
+ 'oauth-enterprise',
+ 'device-management',
+ 'federation',
+ 'videoconference-enterprise',
+ 'message-read-receipt',
+ 'outlook-calendar',
+ 'hide-watermark',
+ 'custom-roles',
+ 'accessibility-certification',
+ ]),
+ preventedActions: {
+ activeUsers: faker.datatype.boolean(),
+ guestUsers: faker.datatype.boolean(),
+ roomsPerGuest: faker.datatype.boolean(),
+ privateApps: faker.datatype.boolean(),
+ marketplaceApps: faker.datatype.boolean(),
+ monthlyActiveContacts: faker.datatype.boolean(),
+ },
+ limits: {
+ activeUsers: { value: faker.number.int({ min: 0 }), max: faker.number.int({ min: 0 }) },
+ guestUsers: { value: faker.number.int({ min: 0 }), max: faker.number.int({ min: 0 }) },
+ roomsPerGuest: { value: faker.number.int({ min: 0 }), max: faker.number.int({ min: 0 }) },
+ privateApps: { value: faker.number.int({ min: 0 }), max: faker.number.int({ min: 0 }) },
+ marketplaceApps: { value: faker.number.int({ min: 0 }), max: faker.number.int({ min: 0 }) },
+ monthlyActiveContacts: { value: faker.number.int({ min: 0 }), max: faker.number.int({ min: 0 }) },
+ },
+ tags: faker.helpers.multiple(() => ({
+ name: faker.commerce.productAdjective(),
+ color: faker.internet.color(),
+ })),
+ trial: faker.datatype.boolean(),
+ ...partial,
+});
diff --git a/docker-compose-ci.yml b/docker-compose-ci.yml
index f3ce12026d49..a533ae29d2df 100644
--- a/docker-compose-ci.yml
+++ b/docker-compose-ci.yml
@@ -19,6 +19,7 @@ services:
- 'ROCKETCHAT_LICENSE=${ENTERPRISE_LICENSE}'
- 'COVERAGE_DIR=${COVERAGE_DIR}'
- 'COVERAGE_REPORTER=${COVERAGE_REPORTER}'
+ - DISABLE_DB_WATCHERS=${DISABLE_DB_WATCHERS}
extra_hosts:
- 'host.docker.internal:host-gateway'
depends_on:
@@ -115,6 +116,7 @@ services:
- MONGO_URL=${MONGO_URL}
- 'TRANSPORTER=${TRANSPORTER}'
- MOLECULER_LOG_LEVEL=info
+ - DISABLE_DB_WATCHERS=${DISABLE_DB_WATCHERS}
extra_hosts:
- 'host.docker.internal:host-gateway'
depends_on:
diff --git a/ee/apps/account-service/CHANGELOG.md b/ee/apps/account-service/CHANGELOG.md
index c4e97fc8dad8..666eda95454d 100644
--- a/ee/apps/account-service/CHANGELOG.md
+++ b/ee/apps/account-service/CHANGELOG.md
@@ -1,5 +1,70 @@
# @rocket.chat/account-service
+## 0.3.13
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, da45cb6998, 845fd64f45, b94ca7c30b, 9902554388, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/rest-typings@6.8.0
+ - @rocket.chat/core-typings@6.8.0
+ - @rocket.chat/model-typings@0.4.0
+ - @rocket.chat/core-services@0.3.14
+ - @rocket.chat/models@0.0.38
+
+
+## 0.3.13-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-services@0.3.14-rc.2
+ - @rocket.chat/core-typings@6.8.0-rc.2
+ - @rocket.chat/rest-typings@6.8.0-rc.2
+ - @rocket.chat/model-typings@0.4.0-rc.2
+ - @rocket.chat/models@0.0.38-rc.2
+
+
+## 0.3.14-rc.1
+
+## 0.3.13
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.8.0-rc.1
+ - @rocket.chat/rest-typings@6.8.0-rc.1
+ - @rocket.chat/core-services@0.3.13-rc.1
+ - @rocket.chat/model-typings@0.4.0-rc.1
+ - @rocket.chat/models@0.0.37-rc.1
+
+
+## 0.3.14-rc.0
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, da45cb6998, 845fd64f45, 9902554388, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/rest-typings@6.8.0-rc.0
+ - @rocket.chat/core-typings@6.8.0-rc.0
+ - @rocket.chat/model-typings@0.4.0-rc.0
+ - @rocket.chat/core-services@0.3.12-rc.0
+ - @rocket.chat/models@0.0.36-rc.0
+
+## 0.3.13
+
+### Patch Changes
+
+- Updated dependencies []:
+ - @rocket.chat/core-typings@6.7.2
+ - @rocket.chat/rest-typings@6.7.2
+ - @rocket.chat/core-services@0.3.13
+ - @rocket.chat/model-typings@0.3.9
+ - @rocket.chat/models@0.0.37
+
+
## 0.3.12
### Patch Changes
diff --git a/ee/apps/account-service/package.json b/ee/apps/account-service/package.json
index b9d48f501fcc..0ccbbce820f2 100644
--- a/ee/apps/account-service/package.json
+++ b/ee/apps/account-service/package.json
@@ -1,7 +1,7 @@
{
"name": "@rocket.chat/account-service",
"private": true,
- "version": "0.3.12",
+ "version": "0.3.13",
"description": "Rocket.Chat Account service",
"scripts": {
"build": "tsc -p tsconfig.json",
diff --git a/ee/apps/authorization-service/CHANGELOG.md b/ee/apps/authorization-service/CHANGELOG.md
index c63443e10bdf..80940bcb4ff4 100644
--- a/ee/apps/authorization-service/CHANGELOG.md
+++ b/ee/apps/authorization-service/CHANGELOG.md
@@ -1,5 +1,69 @@
# @rocket.chat/authorization-service
+## 0.3.14
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, da45cb6998, 845fd64f45, b94ca7c30b, 9902554388, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/rest-typings@6.8.0
+ - @rocket.chat/core-typings@6.8.0
+ - @rocket.chat/model-typings@0.4.0
+ - @rocket.chat/core-services@0.3.14
+ - @rocket.chat/models@0.0.38
+
+
+## 0.3.14-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-services@0.3.14-rc.2
+ - @rocket.chat/core-typings@6.8.0-rc.2
+ - @rocket.chat/rest-typings@6.8.0-rc.2
+ - @rocket.chat/model-typings@0.4.0-rc.2
+ - @rocket.chat/models@0.0.38-rc.2
+
+
+## 0.3.14-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.8.0-rc.1
+ - @rocket.chat/rest-typings@6.8.0-rc.1
+ - @rocket.chat/core-services@0.3.14-rc.1
+ - @rocket.chat/model-typings@0.4.0-rc.1
+ - @rocket.chat/models@0.0.37-rc.1
+
+
+## 0.3.14-rc.0
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, da45cb6998, 845fd64f45, 9902554388, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/rest-typings@6.8.0-rc.0
+ - @rocket.chat/core-typings@6.8.0-rc.0
+ - @rocket.chat/model-typings@0.4.0-rc.0
+ - @rocket.chat/core-services@0.3.12-rc.0
+ - @rocket.chat/models@0.0.36-rc.0
+
+## 0.3.13
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.7.2
+ - @rocket.chat/rest-typings@6.7.2
+ - @rocket.chat/core-services@0.3.13
+ - @rocket.chat/model-typings@0.3.9
+ - @rocket.chat/models@0.0.37
+
+
## 0.3.12
### Patch Changes
diff --git a/ee/apps/authorization-service/package.json b/ee/apps/authorization-service/package.json
index 3ae981b6eb60..13546b16d3b3 100644
--- a/ee/apps/authorization-service/package.json
+++ b/ee/apps/authorization-service/package.json
@@ -1,7 +1,7 @@
{
"name": "@rocket.chat/authorization-service",
"private": true,
- "version": "0.3.12",
+ "version": "0.3.14",
"description": "Rocket.Chat Authorization service",
"scripts": {
"build": "tsc -p tsconfig.json",
diff --git a/ee/apps/ddp-streamer/CHANGELOG.md b/ee/apps/ddp-streamer/CHANGELOG.md
index 0f6fefba7377..5376a1baad58 100644
--- a/ee/apps/ddp-streamer/CHANGELOG.md
+++ b/ee/apps/ddp-streamer/CHANGELOG.md
@@ -1,5 +1,87 @@
# @rocket.chat/ddp-streamer
+## 0.2.13
+
+### Patch Changes
+
+- ([#32374](https://github.com/RocketChat/Rocket.Chat/pull/32374)) Fixed an issue with some apps that didn't implement executeViewCloseHandler. This causes opened modals to be open forever on UI (unless Esc was clicked). This is because when the UI attempts to close it, it calls the aforementioned handler, and since it didn't exist, apps engine errored out.
+
+ This returned an empty response to the UI, which ignored the response and continued to show the view.
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, da45cb6998, 845fd64f45, b94ca7c30b, 9902554388, 8b0986d15a, 4aba7c8a26, c0d54d742a]:
+
+ - @rocket.chat/rest-typings@6.8.0
+ - @rocket.chat/core-typings@6.8.0
+ - @rocket.chat/model-typings@0.4.0
+ - @rocket.chat/core-services@0.3.14
+ - @rocket.chat/ui-contexts@6.0.0
+ - @rocket.chat/models@0.0.38
+ - @rocket.chat/instance-status@0.0.38
+
+
+## 0.2.13-rc.2
+
+### Patch Changes
+
+- ([#32374](https://github.com/RocketChat/Rocket.Chat/pull/32374)) Fixed an issue with some apps that didn't implement executeViewCloseHandler. This causes opened modals to be open forever on UI (unless Esc was clicked). This is because when the UI attempts to close it, it calls the aforementioned handler, and since it didn't exist, apps engine errored out.
+
+ This returned an empty response to the UI, which ignored the response and continued to show the view.
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-services@0.3.14-rc.2
+ - @rocket.chat/core-typings@6.8.0-rc.2
+ - @rocket.chat/rest-typings@6.8.0-rc.2
+ - @rocket.chat/model-typings@0.4.0-rc.2
+ - @rocket.chat/ui-contexts@6.0.0-rc.2
+ - @rocket.chat/models@0.0.38-rc.2
+ - @rocket.chat/instance-status@0.0.38-rc.2
+
+
+## 0.2.13-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.8.0-rc.1
+ - @rocket.chat/rest-typings@6.8.0-rc.1
+ - @rocket.chat/core-services@0.3.13-rc.1
+ - @rocket.chat/model-typings@0.4.0-rc.1
+ - @rocket.chat/ui-contexts@6.0.0-rc.1
+ - @rocket.chat/models@0.0.37-rc.1
+ - @rocket.chat/instance-status@0.0.37-rc.1
+
+
+## 0.2.13-rc.0
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, da45cb6998, 845fd64f45, 9902554388, 8b0986d15a, 4aba7c8a26, c0d54d742a]:
+
+ - @rocket.chat/rest-typings@6.8.0-rc.0
+ - @rocket.chat/core-typings@6.8.0-rc.0
+ - @rocket.chat/model-typings@0.4.0-rc.0
+ - @rocket.chat/core-services@0.3.12-rc.0
+ - @rocket.chat/ui-contexts@6.0.0-rc.0
+ - @rocket.chat/models@0.0.36-rc.0
+ - @rocket.chat/instance-status@0.0.36-rc.0
+
+## 0.2.12
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.7.2
+ - @rocket.chat/rest-typings@6.7.2
+ - @rocket.chat/core-services@0.3.13
+ - @rocket.chat/model-typings@0.3.9
+ - @rocket.chat/ui-contexts@5.0.2
+ - @rocket.chat/models@0.0.37
+ - @rocket.chat/instance-status@0.0.37
+
+
## 0.2.11
### Patch Changes
diff --git a/ee/apps/ddp-streamer/package.json b/ee/apps/ddp-streamer/package.json
index 99719f43b80c..8cc41e5b8e3c 100644
--- a/ee/apps/ddp-streamer/package.json
+++ b/ee/apps/ddp-streamer/package.json
@@ -1,7 +1,7 @@
{
"name": "@rocket.chat/ddp-streamer",
"private": true,
- "version": "0.2.11",
+ "version": "0.2.13",
"description": "Rocket.Chat DDP-Streamer service",
"scripts": {
"build": "tsc -p tsconfig.json",
@@ -15,7 +15,7 @@
],
"author": "Rocket.Chat",
"dependencies": {
- "@rocket.chat/apps-engine": "^1.42.1",
+ "@rocket.chat/apps-engine": "1.42.2",
"@rocket.chat/core-services": "workspace:^",
"@rocket.chat/core-typings": "workspace:^",
"@rocket.chat/emitter": "~0.31.25",
diff --git a/ee/apps/omnichannel-transcript/CHANGELOG.md b/ee/apps/omnichannel-transcript/CHANGELOG.md
index 24d7adb2379c..a2530269d793 100644
--- a/ee/apps/omnichannel-transcript/CHANGELOG.md
+++ b/ee/apps/omnichannel-transcript/CHANGELOG.md
@@ -1,5 +1,73 @@
# @rocket.chat/omnichannel-transcript
+## 0.3.14
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, da45cb6998, b94ca7c30b, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0
+ - @rocket.chat/model-typings@0.4.0
+ - @rocket.chat/core-services@0.3.14
+ - @rocket.chat/omnichannel-services@0.1.14
+ - @rocket.chat/pdf-worker@0.0.38
+ - @rocket.chat/models@0.0.38
+
+
+## 0.3.14-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-services@0.3.14-rc.2
+ - @rocket.chat/core-typings@6.8.0-rc.2
+ - @rocket.chat/omnichannel-services@0.1.14-rc.2
+ - @rocket.chat/pdf-worker@0.0.38-rc.2
+ - @rocket.chat/model-typings@0.4.0-rc.2
+ - @rocket.chat/models@0.0.38-rc.2
+
+
+## 0.3.14-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.8.0-rc.1
+ - @rocket.chat/omnichannel-services@0.1.13-rc.1
+ - @rocket.chat/pdf-worker@0.0.37-rc.1
+ - @rocket.chat/core-services@0.3.14-rc.1
+ - @rocket.chat/model-typings@0.4.0-rc.1
+ - @rocket.chat/models@0.0.37-rc.1
+
+
+## 0.3.14-rc.0
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, da45cb6998, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0-rc.0
+ - @rocket.chat/model-typings@0.4.0-rc.0
+ - @rocket.chat/core-services@0.3.12-rc.0
+ - @rocket.chat/omnichannel-services@0.1.12-rc.0
+ - @rocket.chat/pdf-worker@0.0.36-rc.0
+ - @rocket.chat/models@0.0.36-rc.0
+
+## 0.3.13
+
+### Patch Changes
+
+- Updated dependencies []:
+ - @rocket.chat/core-typings@6.7.2
+ - @rocket.chat/omnichannel-services@0.1.13
+ - @rocket.chat/pdf-worker@0.0.37
+ - @rocket.chat/core-services@0.3.13
+ - @rocket.chat/model-typings@0.3.9
+ - @rocket.chat/models@0.0.37
+
+
## 0.3.12
### Patch Changes
diff --git a/ee/apps/omnichannel-transcript/package.json b/ee/apps/omnichannel-transcript/package.json
index ab649cc233e3..5a8da65d51a4 100644
--- a/ee/apps/omnichannel-transcript/package.json
+++ b/ee/apps/omnichannel-transcript/package.json
@@ -1,7 +1,7 @@
{
"name": "@rocket.chat/omnichannel-transcript",
"private": true,
- "version": "0.3.12",
+ "version": "0.3.14",
"description": "Rocket.Chat service",
"scripts": {
"build": "tsc -p tsconfig.json",
diff --git a/ee/apps/presence-service/CHANGELOG.md b/ee/apps/presence-service/CHANGELOG.md
index fcfd87a7806b..3bd7b9952832 100644
--- a/ee/apps/presence-service/CHANGELOG.md
+++ b/ee/apps/presence-service/CHANGELOG.md
@@ -1,5 +1,68 @@
# @rocket.chat/presence-service
+## 0.3.14
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, da45cb6998, b94ca7c30b, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0
+ - @rocket.chat/model-typings@0.4.0
+ - @rocket.chat/core-services@0.3.14
+ - @rocket.chat/presence@0.1.14
+ - @rocket.chat/models@0.0.38
+
+
+## 0.3.14-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-services@0.3.14-rc.2
+ - @rocket.chat/core-typings@6.8.0-rc.2
+ - @rocket.chat/presence@0.1.14-rc.2
+ - @rocket.chat/model-typings@0.4.0-rc.2
+ - @rocket.chat/models@0.0.38-rc.2
+
+
+## 0.3.14-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.8.0-rc.1
+ - @rocket.chat/presence@0.1.13-rc.1
+ - @rocket.chat/core-services@0.3.14-rc.1
+ - @rocket.chat/model-typings@0.4.0-rc.1
+ - @rocket.chat/models@0.0.37-rc.1
+
+
+## 0.3.14-rc.0
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, da45cb6998, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0-rc.0
+ - @rocket.chat/model-typings@0.4.0-rc.0
+ - @rocket.chat/core-services@0.3.12-rc.0
+ - @rocket.chat/presence@0.1.12-rc.0
+ - @rocket.chat/models@0.0.36-rc.0
+
+## 0.3.13
+
+### Patch Changes
+
+- Updated dependencies []:
+ - @rocket.chat/core-typings@6.7.2
+ - @rocket.chat/presence@0.1.13
+ - @rocket.chat/core-services@0.3.13
+ - @rocket.chat/model-typings@0.3.9
+ - @rocket.chat/models@0.0.37
+
+
## 0.3.12
### Patch Changes
diff --git a/ee/apps/presence-service/package.json b/ee/apps/presence-service/package.json
index 5d6d323bd0a7..10b47541cb82 100644
--- a/ee/apps/presence-service/package.json
+++ b/ee/apps/presence-service/package.json
@@ -1,7 +1,7 @@
{
"name": "@rocket.chat/presence-service",
"private": true,
- "version": "0.3.12",
+ "version": "0.3.14",
"description": "Rocket.Chat Presence service",
"scripts": {
"build": "tsc -p tsconfig.json",
diff --git a/ee/apps/queue-worker/CHANGELOG.md b/ee/apps/queue-worker/CHANGELOG.md
index 029e6e9fd522..2834b6301181 100644
--- a/ee/apps/queue-worker/CHANGELOG.md
+++ b/ee/apps/queue-worker/CHANGELOG.md
@@ -1,5 +1,69 @@
# @rocket.chat/queue-worker
+## 0.3.14
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, da45cb6998, b94ca7c30b, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0
+ - @rocket.chat/model-typings@0.4.0
+ - @rocket.chat/core-services@0.3.14
+ - @rocket.chat/omnichannel-services@0.1.14
+ - @rocket.chat/models@0.0.38
+
+
+## 0.3.14-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-services@0.3.14-rc.2
+ - @rocket.chat/core-typings@6.8.0-rc.2
+ - @rocket.chat/omnichannel-services@0.1.14-rc.2
+ - @rocket.chat/model-typings@0.4.0-rc.2
+ - @rocket.chat/models@0.0.38-rc.2
+
+
+## 0.3.14-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.8.0-rc.1
+ - @rocket.chat/omnichannel-services@0.1.13-rc.1
+ - @rocket.chat/core-services@0.3.14-rc.1
+ - @rocket.chat/model-typings@0.4.0-rc.1
+ - @rocket.chat/models@0.0.37-rc.1
+
+
+## 0.3.14-rc.0
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, da45cb6998, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0-rc.0
+ - @rocket.chat/model-typings@0.4.0-rc.0
+ - @rocket.chat/core-services@0.3.12-rc.0
+ - @rocket.chat/omnichannel-services@0.1.12-rc.0
+ - @rocket.chat/models@0.0.36-rc.0
+
+## 0.3.13
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.7.2
+ - @rocket.chat/omnichannel-services@0.1.13
+ - @rocket.chat/core-services@0.3.13
+ - @rocket.chat/model-typings@0.3.9
+ - @rocket.chat/models@0.0.37
+
+
## 0.3.12
### Patch Changes
diff --git a/ee/apps/queue-worker/package.json b/ee/apps/queue-worker/package.json
index 3e43a06b392b..4864e4a34c9b 100644
--- a/ee/apps/queue-worker/package.json
+++ b/ee/apps/queue-worker/package.json
@@ -1,7 +1,7 @@
{
"name": "@rocket.chat/queue-worker",
"private": true,
- "version": "0.3.12",
+ "version": "0.3.14",
"description": "Rocket.Chat service",
"scripts": {
"build": "tsc -p tsconfig.json",
diff --git a/ee/apps/stream-hub-service/CHANGELOG.md b/ee/apps/stream-hub-service/CHANGELOG.md
index 0d1bd29705ea..e6a8f79aedd8 100644
--- a/ee/apps/stream-hub-service/CHANGELOG.md
+++ b/ee/apps/stream-hub-service/CHANGELOG.md
@@ -1,5 +1,64 @@
# @rocket.chat/stream-hub-service
+## 0.3.14
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, da45cb6998, b94ca7c30b, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0
+ - @rocket.chat/model-typings@0.4.0
+ - @rocket.chat/core-services@0.3.14
+ - @rocket.chat/models@0.0.38
+
+
+## 0.3.14-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-services@0.3.14-rc.2
+ - @rocket.chat/core-typings@6.8.0-rc.2
+ - @rocket.chat/model-typings@0.4.0-rc.2
+ - @rocket.chat/models@0.0.38-rc.2
+
+
+## 0.3.14-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.8.0-rc.1
+ - @rocket.chat/core-services@0.3.14-rc.1
+ - @rocket.chat/model-typings@0.4.0-rc.1
+ - @rocket.chat/models@0.0.37-rc.1
+
+
+## 0.3.14-rc.0
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, da45cb6998, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0-rc.0
+ - @rocket.chat/model-typings@0.4.0-rc.0
+ - @rocket.chat/core-services@0.3.12-rc.0
+ - @rocket.chat/models@0.0.36-rc.0
+
+## 0.3.13
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.7.2
+ - @rocket.chat/core-services@0.3.13
+ - @rocket.chat/model-typings@0.3.9
+ - @rocket.chat/models@0.0.37
+
+
## 0.3.12
### Patch Changes
diff --git a/ee/apps/stream-hub-service/package.json b/ee/apps/stream-hub-service/package.json
index ba373555cd2c..76076b4d3030 100644
--- a/ee/apps/stream-hub-service/package.json
+++ b/ee/apps/stream-hub-service/package.json
@@ -1,7 +1,7 @@
{
"name": "@rocket.chat/stream-hub-service",
"private": true,
- "version": "0.3.12",
+ "version": "0.3.14",
"description": "Rocket.Chat Stream Hub service",
"scripts": {
"build": "tsc -p tsconfig.json",
diff --git a/ee/packages/api-client/CHANGELOG.md b/ee/packages/api-client/CHANGELOG.md
index f3849bb93a11..28df5106b12f 100644
--- a/ee/packages/api-client/CHANGELOG.md
+++ b/ee/packages/api-client/CHANGELOG.md
@@ -1,6 +1,54 @@
# @rocket.chat/api-client
-## 0.1.30
+## 0.1.32
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, 845fd64f45, b94ca7c30b, 9902554388, 4aba7c8a26]:
+
+ - @rocket.chat/rest-typings@6.8.0
+ - @rocket.chat/core-typings@6.8.0
+
+
+## 0.1.32-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-typings@6.8.0-rc.2
+ - @rocket.chat/rest-typings@6.8.0-rc.2
+
+
+## 0.1.32-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+- @rocket.chat/rest-typings@6.8.0-rc.1
+
+
+## 0.1.32-rc.0
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, 845fd64f45, 9902554388, 4aba7c8a26]:
+
+ - @rocket.chat/rest-typings@6.8.0-rc.0
+ - @rocket.chat/core-typings@6.8.0-rc.0
+
+## 0.1.31
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.7.2
+ - @rocket.chat/rest-typings@6.7.2
+
+
+> > > > > > > origin/master
### Patch Changes
diff --git a/ee/packages/api-client/package.json b/ee/packages/api-client/package.json
index 3cbfa21c4d6b..096eec4ee113 100644
--- a/ee/packages/api-client/package.json
+++ b/ee/packages/api-client/package.json
@@ -1,7 +1,7 @@
{
"name": "@rocket.chat/api-client",
"private": true,
- "version": "0.1.30",
+ "version": "0.1.32",
"devDependencies": {
"@swc/core": "^1.3.95",
"@swc/jest": "^0.2.29",
diff --git a/ee/packages/ddp-client/CHANGELOG.md b/ee/packages/ddp-client/CHANGELOG.md
index 1016e8a42d93..80aada44fcab 100644
--- a/ee/packages/ddp-client/CHANGELOG.md
+++ b/ee/packages/ddp-client/CHANGELOG.md
@@ -1,6 +1,51 @@
# @rocket.chat/ddp-client
-## 0.2.21
+## 0.2.23
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, 9a6a7d0a40, 845fd64f45, b94ca7c30b, 9902554388]:
+
+ - @rocket.chat/rest-typings@6.8.0
+ - @rocket.chat/api-client@0.1.32
+
+
+## 0.2.23-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/rest-typings@6.8.0-rc.2
+ - @rocket.chat/api-client@0.1.32-rc.2
+
+
+## 0.2.23-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/api-client@0.1.31-rc.1
+
+
+## 0.2.23-rc.0
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, 9a6a7d0a40, 845fd64f45, 9902554388]:
+
+ - @rocket.chat/rest-typings@6.8.0-rc.0
+ - @rocket.chat/api-client@0.1.30-rc.0
+
+## 0.2.22
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/api-client@0.1.31
+
### Patch Changes
diff --git a/ee/packages/ddp-client/package.json b/ee/packages/ddp-client/package.json
index 52c0dd2a1593..daf3a22c5da6 100644
--- a/ee/packages/ddp-client/package.json
+++ b/ee/packages/ddp-client/package.json
@@ -1,7 +1,7 @@
{
"name": "@rocket.chat/ddp-client",
"private": true,
- "version": "0.2.21",
+ "version": "0.2.23",
"devDependencies": {
"@swc/core": "^1.3.95",
"@swc/jest": "^0.2.29",
diff --git a/ee/packages/license/CHANGELOG.md b/ee/packages/license/CHANGELOG.md
index ea79637134fa..603f131dc407 100644
--- a/ee/packages/license/CHANGELOG.md
+++ b/ee/packages/license/CHANGELOG.md
@@ -1,5 +1,49 @@
# @rocket.chat/license
+## 0.1.14
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, b94ca7c30b, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0
+
+
+## 0.1.14-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-typings@6.8.0-rc.2
+
+
+## 0.1.14-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.8.0-rc.1
+
+
+## 0.1.14-rc.0
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0-rc.0
+
+## 0.1.13
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.7.2
+
+
## 0.1.12
### Patch Changes
diff --git a/ee/packages/license/package.json b/ee/packages/license/package.json
index 54a3923c3484..a07a8db51af0 100644
--- a/ee/packages/license/package.json
+++ b/ee/packages/license/package.json
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/license",
- "version": "0.1.12",
+ "version": "0.1.14",
"private": true,
"devDependencies": {
"@swc/core": "^1.3.95",
diff --git a/ee/packages/omnichannel-services/CHANGELOG.md b/ee/packages/omnichannel-services/CHANGELOG.md
index e6766a9425b4..e9364326e949 100644
--- a/ee/packages/omnichannel-services/CHANGELOG.md
+++ b/ee/packages/omnichannel-services/CHANGELOG.md
@@ -1,5 +1,74 @@
# @rocket.chat/omnichannel-services
+## 0.1.14
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, da45cb6998, 845fd64f45, b94ca7c30b, 9902554388, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/rest-typings@6.8.0
+ - @rocket.chat/core-typings@6.8.0
+ - @rocket.chat/model-typings@0.4.0
+ - @rocket.chat/core-services@0.3.14
+ - @rocket.chat/pdf-worker@0.0.38
+ - @rocket.chat/models@0.0.38
+
+
+## 0.1.14-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-services@0.3.14-rc.2
+ - @rocket.chat/core-typings@6.8.0-rc.2
+ - @rocket.chat/rest-typings@6.8.0-rc.2
+ - @rocket.chat/pdf-worker@0.0.38-rc.2
+ - @rocket.chat/model-typings@0.4.0-rc.2
+ - @rocket.chat/models@0.0.38-rc.2
+
+
+## 0.1.14-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+- @rocket.chat/core-typings@6.8.0-rc.1
+- @rocket.chat/rest-typings@6.8.0-rc.1
+- @rocket.chat/pdf-worker@0.0.37-rc.1
+- @rocket.chat/core-services@0.3.13-rc.1
+- @rocket.chat/model-typings@0.4.0-rc.1
+- @rocket.chat/models@0.0.37-rc.1
+
+
+## 0.1.14-rc.0
+
+### Patch Changes
+
+- Updated dependencies [845fd64f45, c47a8e3514, 9a6a7d0a40, da45cb6998, 845fd64f45, 9902554388, 8b0986d15a, 4aba7c8a26]:
+
+ - @rocket.chat/rest-typings@6.8.0-rc.0
+ - @rocket.chat/core-typings@6.8.0-rc.0
+ - @rocket.chat/model-typings@0.4.0-rc.0
+ - @rocket.chat/core-services@0.3.12-rc.0
+ - @rocket.chat/pdf-worker@0.0.36-rc.0
+ - @rocket.chat/models@0.0.36-rc.0
+
+## 0.1.13
+
+### Patch Changes
+
+- Updated dependencies []:
+
+- @rocket.chat/core-typings@6.7.2
+- @rocket.chat/rest-typings@6.7.2
+- @rocket.chat/pdf-worker@0.0.37
+- @rocket.chat/core-services@0.3.13
+- @rocket.chat/model-typings@0.3.9
+- @rocket.chat/models@0.0.37
+
+
## 0.1.12
### Patch Changes
diff --git a/ee/packages/omnichannel-services/package.json b/ee/packages/omnichannel-services/package.json
index 1a7be642e1cf..a9a99ff25fd7 100644
--- a/ee/packages/omnichannel-services/package.json
+++ b/ee/packages/omnichannel-services/package.json
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/omnichannel-services",
- "version": "0.1.12",
+ "version": "0.1.14",
"private": true,
"devDependencies": {
"@rocket.chat/eslint-config": "workspace:^",
diff --git a/ee/packages/omnichannel-services/src/OmnichannelTranscript.ts b/ee/packages/omnichannel-services/src/OmnichannelTranscript.ts
index 02816b7aebc3..2d273991508b 100644
--- a/ee/packages/omnichannel-services/src/OmnichannelTranscript.ts
+++ b/ee/packages/omnichannel-services/src/OmnichannelTranscript.ts
@@ -232,8 +232,21 @@ export class OmnichannelTranscript extends ServiceClass implements IOmnichannelT
continue;
}
- const fileBuffer = await uploadService.getFileBuffer({ file: uploadedFile });
- files.push({ name: file.name, buffer: fileBuffer, extension: uploadedFile.extension });
+ try {
+ const fileBuffer = await uploadService.getFileBuffer({ file: uploadedFile });
+ files.push({ name: file.name, buffer: fileBuffer, extension: uploadedFile.extension });
+ } catch (e: unknown) {
+ this.log.error(`Failed to get file ${file._id}`, e);
+ // Push empty buffer so parser processes this as "unsupported file"
+ files.push({ name: file.name, buffer: null });
+
+ // TODO: this is a NATS error message, even when we shouldn't tie it, since it's the only way we have right now we'll live with it for a while
+ if ((e as Error).message === 'MAX_PAYLOAD_EXCEEDED') {
+ this.log.error(
+ `File is too big to be processed by NATS. See NATS config for allowing bigger messages to be sent between services`,
+ );
+ }
+ }
}
// When you send a file message, the things you type in the modal are not "msg", they're in "description" of the attachment
diff --git a/ee/packages/pdf-worker/CHANGELOG.md b/ee/packages/pdf-worker/CHANGELOG.md
index 6dfd98fe9871..5cd81d9558ac 100644
--- a/ee/packages/pdf-worker/CHANGELOG.md
+++ b/ee/packages/pdf-worker/CHANGELOG.md
@@ -1,5 +1,49 @@
# @rocket.chat/pdf-worker
+## 0.0.38
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, b94ca7c30b, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0
+
+
+## 0.0.38-rc.2
+
+### Patch Changes
+
+- Updated dependencies [b94ca7c30b]:
+
+ - @rocket.chat/core-typings@6.8.0-rc.2
+
+
+## 0.0.38-rc.1
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.8.0-rc.1
+
+
+## 0.0.38-rc.0
+
+### Patch Changes
+
+- Updated dependencies [c47a8e3514, 4aba7c8a26]:
+
+ - @rocket.chat/core-typings@6.8.0-rc.0
+
+## 0.0.37
+
+### Patch Changes
+
+- Updated dependencies []:
+
+ - @rocket.chat/core-typings@6.7.2
+
+
## 0.0.36
### Patch Changes
diff --git a/ee/packages/pdf-worker/jest.config.ts b/ee/packages/pdf-worker/jest.config.ts
index 4f4e7697b108..acf158bdd7d8 100644
--- a/ee/packages/pdf-worker/jest.config.ts
+++ b/ee/packages/pdf-worker/jest.config.ts
@@ -2,7 +2,7 @@ export default {
preset: 'ts-jest',
errorOnDeprecated: true,
testEnvironment: 'jsdom',
- modulePathIgnorePatterns: ['/dist/'],
+ modulePathIgnorePatterns: ['/dist/', '/src/worker.spec.ts'],
moduleNameMapper: {
'\\.css$': 'identity-obj-proxy',
},
diff --git a/ee/packages/pdf-worker/jest.worker.config.ts b/ee/packages/pdf-worker/jest.worker.config.ts
new file mode 100644
index 000000000000..83706fdd37ec
--- /dev/null
+++ b/ee/packages/pdf-worker/jest.worker.config.ts
@@ -0,0 +1,5 @@
+export default {
+ preset: 'ts-jest',
+ errorOnDeprecated: true,
+ modulePathIgnorePatterns: ['/dist/', '