From 78addc31ff3895d2e4287debd792904098bb2437 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Sun, 27 Jul 2025 11:16:46 -0300 Subject: [PATCH 01/10] fix: bh not working on weekend if uses different timezone than UTC --- ...ilterBusinessHoursThatMustBeOpened.spec.ts | 211 +++++++++++++++++- .../filterBusinessHoursThatMustBeOpened.ts | 8 +- 2 files changed, 216 insertions(+), 3 deletions(-) diff --git a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts index 7255b3b03792a..38fb7128c1e22 100644 --- a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts +++ b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts @@ -3,7 +3,7 @@ import { LivechatBusinessHourTypes } from '@rocket.chat/core-typings'; import { filterBusinessHoursThatMustBeOpened } from './filterBusinessHoursThatMustBeOpened'; describe('different timezones between server and business hours', () => { - beforeEach(() => jest.useFakeTimers().setSystemTime(new Date('2024-04-20T20:10:11Z'))); + beforeEach(() => jest.useFakeTimers().setSystemTime(new Date('2025-07-27T11:02:11Z'))); afterEach(() => jest.useRealTimers()); it('should return a bh when the finish time resolves to a different day on server', async () => { const bh = await filterBusinessHoursThatMustBeOpened([ @@ -51,4 +51,213 @@ describe('different timezones between server and business hours', () => { expect(bh.length).toEqual(1); }); + + it('should return a bh when the finish time resolves to a different day on server', async () => { + const bh = await filterBusinessHoursThatMustBeOpened([ + { + _id: '68516f256ebb4bdceda2757e', + active: true, + type: LivechatBusinessHourTypes.DEFAULT, + ts: new Date(), + name: '', + workHours: [ + { + day: 'Sunday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Saturday', + time: '18:30', + }, + cron: { + dayOfWeek: 'Saturday', + time: '15:30', + }, + }, + finish: { + time: '23:59', + utc: { + dayOfWeek: 'Sunday', + time: '18:29', + }, + cron: { + dayOfWeek: 'Sunday', + time: '15:29', + }, + }, + open: true, + code: '', + }, + { + day: 'Monday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Sunday', + time: '18:30', + }, + cron: { + dayOfWeek: 'Sunday', + time: '15:30', + }, + }, + finish: { + time: '23:59', + utc: { + dayOfWeek: 'Monday', + time: '18:29', + }, + cron: { + dayOfWeek: 'Monday', + time: '15:29', + }, + }, + open: true, + code: '', + }, + { + day: 'Tuesday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Monday', + time: '18:30', + }, + cron: { + dayOfWeek: 'Monday', + time: '15:30', + }, + }, + finish: { + time: '23:59', + utc: { + dayOfWeek: 'Tuesday', + time: '18:29', + }, + cron: { + dayOfWeek: 'Tuesday', + time: '15:29', + }, + }, + open: true, + code: '', + }, + { + day: 'Wednesday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Tuesday', + time: '18:30', + }, + cron: { + dayOfWeek: 'Tuesday', + time: '15:30', + }, + }, + finish: { + time: '23:59', + utc: { + dayOfWeek: 'Wednesday', + time: '18:29', + }, + cron: { + dayOfWeek: 'Wednesday', + time: '15:29', + }, + }, + open: true, + code: '', + }, + { + day: 'Thursday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Wednesday', + time: '18:30', + }, + cron: { + dayOfWeek: 'Wednesday', + time: '15:30', + }, + }, + finish: { + time: '23:59', + utc: { + dayOfWeek: 'Thursday', + time: '18:29', + }, + cron: { + dayOfWeek: 'Thursday', + time: '15:29', + }, + }, + open: true, + code: '', + }, + { + day: 'Friday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Thursday', + time: '18:30', + }, + cron: { + dayOfWeek: 'Thursday', + time: '15:30', + }, + }, + finish: { + time: '23:59', + utc: { + dayOfWeek: 'Friday', + time: '18:29', + }, + cron: { + dayOfWeek: 'Friday', + time: '15:29', + }, + }, + open: true, + code: '', + }, + { + day: 'Saturday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Friday', + time: '18:30', + }, + cron: { + dayOfWeek: 'Friday', + time: '15:30', + }, + }, + finish: { + time: '23:59', + utc: { + dayOfWeek: 'Saturday', + time: '18:29', + }, + cron: { + dayOfWeek: 'Saturday', + time: '15:29', + }, + }, + open: true, + code: '', + }, + ], + timezone: { + name: 'Asia/Kolkata', + utc: '+05:30', + }, + }, + ]); + + expect(bh.length).toEqual(1); + }); }); diff --git a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts index c06dbaac4e185..52e35c8bd0048 100644 --- a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts +++ b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts @@ -16,8 +16,12 @@ export const filterBusinessHoursThatMustBeOpened = async ( const localTimeStart = moment(`${hour.start.cron.dayOfWeek}:${hour.start.cron.time}:00`, 'dddd:HH:mm:ss'); const localTimeFinish = moment(`${hour.finish.cron.dayOfWeek}:${hour.finish.cron.time}:00`, 'dddd:HH:mm:ss'); - // The way we create the instances sunday will be the first day of the current week not the next one, that way it will never met isBefore - if (localTimeFinish.isBefore(localTimeStart)) { + /** because we use `dayOfWeek` moment decides if saturday/sunday belongs to the current week or the next one, this is a bit + * confusing and for that reason we need this workaround + */ + if (localTimeStart.isAfter(localTimeFinish)) { + localTimeStart.subtract(1, 'week'); + } else if (localTimeFinish.isBefore(localTimeStart)) { localTimeFinish.add(1, 'week'); } From baffba35ad94757f0cabc0b37d856851a3ab5396 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 25 Jul 2025 18:20:40 -0400 Subject: [PATCH 02/10] Create thick-hotels-occur.md --- .changeset/thick-hotels-occur.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/thick-hotels-occur.md diff --git a/.changeset/thick-hotels-occur.md b/.changeset/thick-hotels-occur.md new file mode 100644 index 0000000000000..e91972c9cb0a1 --- /dev/null +++ b/.changeset/thick-hotels-occur.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +fixes an issue where bussines hours are not working on weekends when the timezone of bh sleeps into another day From 752f3fef57746bd49aa4257e31b6ad0a2e016c52 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 25 Jul 2025 18:21:25 -0400 Subject: [PATCH 03/10] Update thick-hotels-occur.md --- .changeset/thick-hotels-occur.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/thick-hotels-occur.md b/.changeset/thick-hotels-occur.md index e91972c9cb0a1..22ab272bfad4b 100644 --- a/.changeset/thick-hotels-occur.md +++ b/.changeset/thick-hotels-occur.md @@ -2,4 +2,4 @@ "@rocket.chat/meteor": patch --- -fixes an issue where bussines hours are not working on weekends when the timezone of bh sleeps into another day +fixes an issue where bussines hours are not working on weekends when the timezone of bh slip into another day From 130aae57c65cce635a82a41afb5ddb7e6862444a Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Sat, 26 Jul 2025 20:05:04 -0300 Subject: [PATCH 04/10] fix for saturday --- .../filterBusinessHoursThatMustBeOpened.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts index 52e35c8bd0048..a13506a51778b 100644 --- a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts +++ b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts @@ -19,9 +19,26 @@ export const filterBusinessHoursThatMustBeOpened = async ( /** because we use `dayOfWeek` moment decides if saturday/sunday belongs to the current week or the next one, this is a bit * confusing and for that reason we need this workaround */ + + const currentDay = currentTime.format('dddd'); + const localTimeStartDay = localTimeStart.format('dddd'); + + // This only works for sundays (where we can test if sunday is before saturday = something is wrong) + if (localTimeStart.isAfter(localTimeFinish)) { localTimeStart.subtract(1, 'week'); - } else if (localTimeFinish.isBefore(localTimeStart)) { + } + if (localTimeFinish.isBefore(localTimeStart)) { + localTimeFinish.add(1, 'week'); + } + + // During Saturday, if current weekday is the same but the start time is after the current time, we need to subtract a week + if (currentDay === localTimeStartDay && localTimeStart.diff(currentTime) > 1) { + localTimeStart.subtract(1, 'week'); + } + + // During Saturday, if current weekday is the same but the finish time is before the current time, we need to add a week + if (currentDay === localTimeStartDay && localTimeFinish.diff(currentTime) < 1) { localTimeFinish.add(1, 'week'); } From 928bb62f34859dc719304e73755e22958243b7c9 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 7 Aug 2025 00:16:13 -0300 Subject: [PATCH 05/10] do not use random states to test --- .../end-to-end/api/livechat/01-agents.ts | 119 +++++++++--------- 1 file changed, 62 insertions(+), 57 deletions(-) diff --git a/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts b/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts index c65345402b516..1f2c72b7ef920 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts @@ -624,69 +624,74 @@ describe('LIVECHAT - Agents', () => { expect(res.body).to.have.property('error', 'Agent not found'); }); }); - it('should change logged in users status', async () => { - const currentUser: ILivechatAgent = await getMe(agent2.credentials); - const currentStatus = currentUser.statusLivechat; - const newStatus = currentStatus === 'available' ? 'not-available' : 'available'; - await request - .post(api('livechat/agent.status')) - .set(agent2.credentials) - .send({ status: newStatus, agentId: currentUser._id }) - .expect(200) - .expect((res: Response) => { - expect(res.body).to.have.property('success', true); - expect(res.body).to.have.property('status', newStatus); - }); - }); - it('should allow managers to change other agents status', async () => { - const currentUser: ILivechatAgent = await getMe(agent2.credentials); - const currentStatus = currentUser.statusLivechat; - const newStatus = currentStatus === 'available' ? 'not-available' : 'available'; - - await request - .post(api('livechat/agent.status')) - .set(credentials) - .send({ status: newStatus, agentId: currentUser._id }) - .expect(200) - .expect((res: Response) => { - expect(res.body).to.have.property('success', true); - expect(res.body).to.have.property('status', newStatus); - }); - }); - it('should throw an error if agent tries to make themselves available outside of Business hour', async () => { - await makeDefaultBusinessHourActiveAndClosed(); + describe('cases for valid agents', () => { + let currentUser: ILivechatAgent; + before(async () => { + currentUser = await getMe(agent2.credentials); + }); - const currentUser: ILivechatAgent = await getMe(agent2.credentials); - const currentStatus = currentUser.statusLivechat; - const newStatus = currentStatus === 'available' ? 'not-available' : 'available'; + afterEach(async () => { + await request + .post(api('livechat/agent.status')) + .set(agent2.credentials) + .send({ status: 'not-available', agentId: currentUser._id }) + .expect(200); + }); - await request - .post(api('livechat/agent.status')) - .set(agent2.credentials) - .send({ status: newStatus, agentId: currentUser._id }) - .expect(400) - .expect((res: Response) => { - expect(res.body).to.have.property('success', false); - expect(res.body).to.have.property('error', 'error-business-hours-are-closed'); + it('should be able to set a logged in users status to available', async () => { + await request + .post(api('livechat/agent.status')) + .set(agent2.credentials) + .send({ status: 'available', agentId: currentUser._id }) + .expect(200) + .expect((res: Response) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('status', 'available'); + }); + }); + it('should allow managers to set other agents status to available', async () => { + await request + .post(api('livechat/agent.status')) + .set(credentials) + .send({ status: 'available', agentId: currentUser._id }) + .expect(200) + .expect((res: Response) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('status', 'available'); + }); + }); + describe('outside of business hours', () => { + before(async () => { + await makeDefaultBusinessHourActiveAndClosed(); }); - }); - it('should not allow managers to make other agents available outside business hour', async () => { - const currentUser: ILivechatAgent = await getMe(agent2.credentials); - const currentStatus = currentUser.statusLivechat; - const newStatus = currentStatus === 'available' ? 'not-available' : 'available'; - await request - .post(api('livechat/agent.status')) - .set(credentials) - .send({ status: newStatus, agentId: currentUser._id }) - .expect(200) - .expect((res: Response) => { - expect(res.body).to.have.property('success', true); - expect(res.body).to.have.property('status', currentStatus); + after(async () => { + await disableDefaultBusinessHour(); }); - - await disableDefaultBusinessHour(); + it('should throw an error if agent tries to make themselves available outside of Business hour', async () => { + await request + .post(api('livechat/agent.status')) + .set(agent2.credentials) + .send({ status: 'available', agentId: currentUser._id }) + .expect(400) + .expect((res: Response) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('error', 'error-business-hours-are-closed'); + }); + }); + it('should not allow managers to make other agents available outside business hour', async () => { + await request + .post(api('livechat/agent.status')) + .set(credentials) + .send({ status: 'available', agentId: currentUser._id }) + .expect(200) + .expect((res: Response) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('error', 'error-business-hours-are-closed'); + }); + }); + }); }); }); From 32594a2dd1987bd3c39b1dde00ab8eba4793c869 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 7 Aug 2025 17:07:49 -0300 Subject: [PATCH 06/10] test: Add agent status check for users without manage-agent permission --- apps/meteor/tests/end-to-end/api/livechat/01-agents.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts b/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts index 1f2c72b7ef920..158ffae6fdc61 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts @@ -570,8 +570,12 @@ describe('LIVECHAT - Agents', () => { }); describe('with no manage-agent permission', () => { before(async () => { + await request + .post(api('livechat/agent.status')) + .set(credentials) + .send({ status: 'not-available', agentId: agent2.user._id }) + .expect(200); await removePermissionFromAllRoles('manage-livechat-agents'); - console.log('Permissions removed'); }); after(async () => { await restorePermissionToRoles('manage-livechat-agents'); From 2926a9e9b64c97b6edb2a1a46fe2730226052b40 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 7 Aug 2025 17:45:57 -0300 Subject: [PATCH 07/10] test: Add agent status update for non-available agents during business hours --- apps/meteor/tests/end-to-end/api/livechat/01-agents.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts b/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts index 158ffae6fdc61..caf60434a73d3 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts @@ -668,6 +668,12 @@ describe('LIVECHAT - Agents', () => { describe('outside of business hours', () => { before(async () => { await makeDefaultBusinessHourActiveAndClosed(); + + await request + .post(api('livechat/agent.status')) + .set(agent2.credentials) + .send({ status: 'not-available', agentId: currentUser._id }) + .expect(200); }); after(async () => { From 21dc409c626999114eedeeb2e9123e929c990b5f Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 7 Aug 2025 22:55:28 -0300 Subject: [PATCH 08/10] adjust test for admins that should silent fail --- apps/meteor/tests/end-to-end/api/livechat/01-agents.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts b/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts index caf60434a73d3..3ccd19dd7d501 100644 --- a/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts +++ b/apps/meteor/tests/end-to-end/api/livechat/01-agents.ts @@ -690,15 +690,15 @@ describe('LIVECHAT - Agents', () => { expect(res.body).to.have.property('error', 'error-business-hours-are-closed'); }); }); - it('should not allow managers to make other agents available outside business hour', async () => { + it('should return success but not change the agent when admin make try other agents available outside business hour', async () => { await request .post(api('livechat/agent.status')) .set(credentials) .send({ status: 'available', agentId: currentUser._id }) .expect(200) .expect((res: Response) => { - expect(res.body).to.have.property('success', false); - expect(res.body).to.have.property('error', 'error-business-hours-are-closed'); + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('status', 'not-available'); }); }); }); From bd968048b1555770e78eb1f483a7dce0109de6f9 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 7 Aug 2025 22:55:54 -0300 Subject: [PATCH 09/10] add on extra test reproducing an real error em prod --- ...ilterBusinessHoursThatMustBeOpened.spec.ts | 213 ++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts index 38fb7128c1e22..b1d22cf6aa697 100644 --- a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts +++ b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts @@ -261,3 +261,216 @@ describe('different timezones between server and business hours', () => { expect(bh.length).toEqual(1); }); }); + +describe('regular business hours', () => { + beforeEach(() => jest.useFakeTimers().setSystemTime(new Date('2025-08-07T22:02:11Z'))); + afterEach(() => jest.useRealTimers()); + it('should return a bh when the finish time resolves to a different day on server', async () => { + const bh = await filterBusinessHoursThatMustBeOpened([ + { + _id: '68516f256ebb4bdceda2757e', + active: true, + type: LivechatBusinessHourTypes.DEFAULT, + ts: new Date(), + name: '', + workHours: [ + { + day: 'Sunday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Sunday', + time: '03:00', + }, + cron: { + dayOfWeek: 'Sunday', + time: '00:00', + }, + }, + finish: { + time: '00:01', + utc: { + dayOfWeek: 'Sunday', + time: '03:01', + }, + cron: { + dayOfWeek: 'Sunday', + time: '00:01', + }, + }, + open: true, + code: '', + }, + { + day: 'Monday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Monday', + time: '03:00', + }, + cron: { + dayOfWeek: 'Monday', + time: '00:00', + }, + }, + finish: { + time: '00:01', + utc: { + dayOfWeek: 'Monday', + time: '03:01', + }, + cron: { + dayOfWeek: 'Monday', + time: '00:01', + }, + }, + open: true, + code: '', + }, + { + day: 'Tuesday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Tuesday', + time: '03:00', + }, + cron: { + dayOfWeek: 'Tuesday', + time: '00:00', + }, + }, + finish: { + time: '00:01', + utc: { + dayOfWeek: 'Tuesday', + time: '03:01', + }, + cron: { + dayOfWeek: 'Tuesday', + time: '00:01', + }, + }, + open: true, + code: '', + }, + { + day: 'Wednesday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Wednesday', + time: '03:00', + }, + cron: { + dayOfWeek: 'Wednesday', + time: '00:00', + }, + }, + finish: { + time: '00:01', + utc: { + dayOfWeek: 'Wednesday', + time: '03:01', + }, + cron: { + dayOfWeek: 'Wednesday', + time: '00:01', + }, + }, + open: true, + code: '', + }, + { + day: 'Thursday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Thursday', + time: '03:00', + }, + cron: { + dayOfWeek: 'Thursday', + time: '00:00', + }, + }, + finish: { + time: '00:01', + utc: { + dayOfWeek: 'Thursday', + time: '03:01', + }, + cron: { + dayOfWeek: 'Thursday', + time: '00:01', + }, + }, + open: true, + code: '', + }, + { + day: 'Friday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Friday', + time: '03:00', + }, + cron: { + dayOfWeek: 'Friday', + time: '00:00', + }, + }, + finish: { + time: '00:01', + utc: { + dayOfWeek: 'Friday', + time: '03:01', + }, + cron: { + dayOfWeek: 'Friday', + time: '00:01', + }, + }, + open: true, + code: '', + }, + { + day: 'Saturday', + start: { + time: '00:00', + utc: { + dayOfWeek: 'Saturday', + time: '03:00', + }, + cron: { + dayOfWeek: 'Saturday', + time: '00:00', + }, + }, + finish: { + time: '00:01', + utc: { + dayOfWeek: 'Saturday', + time: '03:01', + }, + cron: { + dayOfWeek: 'Saturday', + time: '00:01', + }, + }, + open: true, + code: '', + }, + ], + timezone: { + name: 'America/Sao_Paulo', + utc: '-3', + }, + }, + ]); + + expect(bh.length).toEqual(0); + }); +}); From 663d1e4ed31599e421792c6f043d5740126d6a26 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 7 Aug 2025 23:16:48 -0300 Subject: [PATCH 10/10] test: Update timezone handling for business hours on Saturday and Sunday --- .../filterBusinessHoursThatMustBeOpened.spec.ts | 8 ++++++-- .../business-hour/filterBusinessHoursThatMustBeOpened.ts | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts index b1d22cf6aa697..6fe3c1e2c9bf7 100644 --- a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts +++ b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.spec.ts @@ -2,8 +2,8 @@ import { LivechatBusinessHourTypes } from '@rocket.chat/core-typings'; import { filterBusinessHoursThatMustBeOpened } from './filterBusinessHoursThatMustBeOpened'; -describe('different timezones between server and business hours', () => { - beforeEach(() => jest.useFakeTimers().setSystemTime(new Date('2025-07-27T11:02:11Z'))); +describe('different timezones between server and business hours saturday ', () => { + beforeEach(() => jest.useFakeTimers().setSystemTime(new Date('2024-04-20T20:10:11Z'))); afterEach(() => jest.useRealTimers()); it('should return a bh when the finish time resolves to a different day on server', async () => { const bh = await filterBusinessHoursThatMustBeOpened([ @@ -51,7 +51,11 @@ describe('different timezones between server and business hours', () => { expect(bh.length).toEqual(1); }); +}); +describe('different timezones between server and business hours sunday ', () => { + beforeEach(() => jest.useFakeTimers().setSystemTime(new Date('2025-07-27T11:02:11Z'))); + afterEach(() => jest.useRealTimers()); it('should return a bh when the finish time resolves to a different day on server', async () => { const bh = await filterBusinessHoursThatMustBeOpened([ { diff --git a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts index a13506a51778b..fb379eb9b6693 100644 --- a/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts +++ b/apps/meteor/app/livechat/server/business-hour/filterBusinessHoursThatMustBeOpened.ts @@ -33,12 +33,12 @@ export const filterBusinessHoursThatMustBeOpened = async ( } // During Saturday, if current weekday is the same but the start time is after the current time, we need to subtract a week - if (currentDay === localTimeStartDay && localTimeStart.diff(currentTime) > 1) { + if (currentDay === localTimeStartDay && localTimeStart.diff(currentTime, 'days') > 0) { localTimeStart.subtract(1, 'week'); } // During Saturday, if current weekday is the same but the finish time is before the current time, we need to add a week - if (currentDay === localTimeStartDay && localTimeFinish.diff(currentTime) < 1) { + if (currentDay === localTimeStartDay && localTimeFinish.diff(currentTime, 'days') < 0) { localTimeFinish.add(1, 'week'); }