Skip to content
5 changes: 5 additions & 0 deletions .changeset/tags-save-updatedat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixed saving a livechat tag failing with "Invalid response" — the model mutated its return value with `_updatedAt`, which the endpoint response schema rejects
3 changes: 2 additions & 1 deletion apps/meteor/ee/server/models/raw/LivechatTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ export class LivechatTagRaw extends BaseRaw<ILivechatTag> implements ILivechatTa
_id = (await this.insertOne(record)).insertedId;
}

return Object.assign(record, { _id });
// updateOne/insertOne mutate `record` by injecting `_updatedAt` (setUpdatedAt), so rebuild the declared shape
return { _id, name, description, numDepartments: departments.length, departments };
}

// REMOVE
Expand Down
1 change: 1 addition & 0 deletions apps/meteor/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default {
outputDir: 'tests/e2e/.playwright',
reporter: [
['list'],
process.env.GITHUB_ACTIONS === 'true' && ['github'],
process.env.REPORTER_ROCKETCHAT_REPORT === 'true' && [
'./reporters/rocketchat.ts',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,18 @@ test.describe('E2EE File Encryption', () => {
await page.goto(`/group/${group.name}`);
await page.locator('#main-content').waitFor();
await expect(poHomeChannel.content.encryptedRoomHeaderIcon).toBeVisible();
await expect
.poll(
() =>
page.evaluate(async (rid) => {
// eslint-disable-next-line import-x/no-absolute-path
const { e2e } = require('/client/lib/e2ee/rocketchat.e2e.ts') as typeof import('../../../client/lib/e2ee/rocketchat.e2e');
const room = await e2e.getInstanceByRoomId(rid);
return room?.getState();
}, group._id),
{ message: 'expect room encryption key to be ready before sending messages' },
)
.toBe('READY');
});

test.afterEach(async ({ api }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ test.describe.serial('OC - Manage Agents', () => {
await test.step('expect update "user1" information', async () => {
await poOmnichannelAgents.editAgent.selectStatus('Not Available');
await poOmnichannelAgents.editAgent.selectDepartment(department.data.name);
await poOmnichannelAgents.editAgent.btnSave.click();
await poOmnichannelAgents.editAgent.save();
});

await test.step('expect removing "user1" via sidebar', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ test.describe('OC - Business Hours', () => {
await poOmnichannelBusinessHours.table.findRowByName(BHName).click();
await poOmnichannelBusinessHours.selectDepartment(department2.data.name);
await poOmnichannelBusinessHours.btnSave.click();
await expect(poOmnichannelBusinessHours.btnSave).not.toBeVisible();
});

await test.step('expect department to be in the chosen departments list', async () => {
Expand All @@ -108,6 +109,7 @@ test.describe('OC - Business Hours', () => {
await poOmnichannelBusinessHours.table.findRowByName(BHName).click();
await poOmnichannelBusinessHours.selectDepartment(department2.data.name);
await poOmnichannelBusinessHours.btnSave.click();
await expect(poOmnichannelBusinessHours.btnSave).not.toBeVisible();
});

await test.step('expect department to not be in the chosen departments list', async () => {
Expand Down
6 changes: 4 additions & 2 deletions apps/meteor/tests/e2e/omnichannel/omnichannel-tags.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ test.describe('OC - Manage Tags', () => {
await poOmnichannelTags.table.findRowByName(tag.name).click();
await expect(poOmnichannelTags.editTag.root).toBeVisible();
await poOmnichannelTags.editTag.selectDepartment(department2.data.name);
await poOmnichannelTags.editTag.btnSave.click();
await expect(poOmnichannelTags.editTag.findSelectedDepartment(department2.data.name)).toBeVisible();
await poOmnichannelTags.editTag.save();
});

await test.step('expect department to be in the chosen departments list', async () => {
Expand All @@ -113,7 +114,8 @@ test.describe('OC - Manage Tags', () => {
await poOmnichannelTags.table.findRowByName(tag.name).click();
await expect(poOmnichannelTags.editTag.root).toBeVisible();
await poOmnichannelTags.editTag.selectDepartment(department2.data.name);
await poOmnichannelTags.editTag.btnSave.click();
await expect(poOmnichannelTags.editTag.findSelectedDepartment(department2.data.name)).not.toBeVisible();
await poOmnichannelTags.editTag.save();
});

await test.step('expect department to not be in the chosen departments list', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ class OmnichannelEditTagFlexTab extends FlexTab {
await this.inputDepartments.fill(name);
await this.listbox.selectOption(name);
}

findSelectedDepartment(name: string) {
return this.root.getByLabel('Departments').getByRole('option', { name });
}
}

class OmnichannelTagsTable extends Table {
Expand Down
8 changes: 6 additions & 2 deletions apps/meteor/tests/e2e/threads.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ test.describe.serial('Threads', () => {
await test.step('open threads contextual bar when clicked on thread preview', async () => {
await poHomeChannel.content.lastThreadMessagePreviewText.click();
await expect(page).toHaveURL(/.*thread/);
await expect(poHomeChannel.content.lastUserThreadMessage).toContainText('This is a thread message also sent in channel');
await expect(poHomeChannel.content.lastUserThreadMessage).toContainText('This is a thread message also sent in channel', {
timeout: 15_000,
});
});
await expect(page).not.toHaveURL(/[?&]msg=/);

Expand All @@ -64,7 +66,9 @@ test.describe.serial('Threads', () => {
test('expect not to close thread contextual bar when performing some action', async ({ page }) => {
await poHomeChannel.content.lastThreadMessagePreviewText.click();
await expect(page).toHaveURL(/.*thread/);
await expect(poHomeChannel.content.lastUserThreadMessage).toContainText('This is a thread message also sent in channel');
await expect(poHomeChannel.content.lastUserThreadMessage).toContainText('This is a thread message also sent in channel', {
timeout: 15_000,
});

await poHomeChannel.content.openLastThreadMessageMenu();
await page.locator('role=menuitem[name="Copy text"]').click();
Expand Down
37 changes: 13 additions & 24 deletions apps/meteor/tests/end-to-end/api/rooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2764,6 +2764,17 @@ describe('[Rooms]', () => {
]),
);

const expectSubscriptionFieldToEqual = async (field: 'name' | 'fname', expected: string) => {
for (let attempt = 0; ; attempt++) {
const { body } = await request.get(api('subscriptions.getOne')).set(credentials).query({ roomId });
if (body.subscription?.[field] === expected || attempt >= 20) {
expect(body.subscription?.[field]).to.equal(expected);
return;
}
await sleep(250);
}
};

it('should update group name if user changes username', async () => {
await updateSetting('UI_Use_Real_Name', false);
await request
Expand All @@ -2776,18 +2787,7 @@ describe('[Rooms]', () => {
},
});

// need to wait for the username update finish
await sleep(300);

await request
.get(api('subscriptions.getOne'))
.set(credentials)
.query({ roomId })
.send()
.expect((res) => {
const { subscription } = res.body;
expect(subscription.name).to.equal(`changed.username.${testUser.username},${testUser2.username}`);
});
await expectSubscriptionFieldToEqual('name', `changed.username.${testUser.username},${testUser2.username}`);
});

describe('use real name', () => {
Expand All @@ -2810,18 +2810,7 @@ describe('[Rooms]', () => {
},
});

// need to wait for the name update finish
await sleep(300);

await request
.get(api('subscriptions.getOne'))
.set(credentials)
.query({ roomId })
.send()
.expect((res) => {
const { subscription } = res.body;
expect(subscription.fname).to.equal(`changed.name.${testUser.username}, ${testUser2.name}`);
});
await expectSubscriptionFieldToEqual('fname', `changed.name.${testUser.username}, ${testUser2.name}`);
});
});
});
Expand Down
Loading