diff --git a/apps/api/src/app/subscribers/subscribers.controller.ts b/apps/api/src/app/subscribers/subscribers.controller.ts index db053dd0d15..85f0b987bb1 100644 --- a/apps/api/src/app/subscribers/subscribers.controller.ts +++ b/apps/api/src/app/subscribers/subscribers.controller.ts @@ -416,10 +416,15 @@ export class SubscribersController { @Query('limit', new DefaultValuePipe(100)) limit: number ): Promise { let feedsQuery: string[] | undefined; + if (feedId) { feedsQuery = Array.isArray(feedId) ? feedId : [feedId]; } + if (seen === undefined) { + seen = false; + } + const command = GetFeedCountCommand.create({ organizationId: user.organizationId, subscriberId: subscriberId, diff --git a/apps/api/src/app/widgets/e2e/get-count.e2e.ts b/apps/api/src/app/widgets/e2e/get-count.e2e.ts index 7748ad5eb7d..138f69d950b 100644 --- a/apps/api/src/app/widgets/e2e/get-count.e2e.ts +++ b/apps/api/src/app/widgets/e2e/get-count.e2e.ts @@ -239,6 +239,114 @@ describe('Count - GET /widget/notifications/count', function () { } }); + it('should return unseen count with a seen filter', async function () { + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + + await session.awaitRunningJobs(template._id); + + const messages = await messageRepository.findBySubscriberChannel( + session.environment._id, + subscriberProfile!._id, + ChannelTypeEnum.IN_APP + ); + const messageId = messages[0]._id; + expect(messages[0].seen).to.equal(false); + + await axios.post( + `http://localhost:${process.env.PORT}/v1/widgets/messages/markAs`, + { messageId, mark: { seen: true } }, + { + headers: { + Authorization: `Bearer ${subscriberToken}`, + }, + } + ); + + const unseenFeed = await getFeedCount({ seen: false }); + expect(unseenFeed.data.count).to.equal(2); + }); + + it('should return unread count with a read filter', async function () { + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + + await session.awaitRunningJobs(template._id); + if (!subscriberProfile) throw new Error('Subscriber profile is null'); + + const messages = await messageRepository.findBySubscriberChannel( + session.environment._id, + subscriberProfile._id, + ChannelTypeEnum.IN_APP + ); + + const messageId = messages[0]._id; + expect(messages[0].read).to.equal(false); + + await axios.post( + `http://localhost:${process.env.PORT}/v1/widgets/messages/markAs`, + { messageId, mark: { seen: true, read: true } }, + { + headers: { + Authorization: `Bearer ${subscriberToken}`, + }, + } + ); + + const readFeed = await getFeedCount({ read: true }); + expect(readFeed.data.count).to.equal(1); + + const unreadFeed = await getFeedCount({ read: false }); + expect(unreadFeed.data.count).to.equal(2); + }); + + it('should return unseen count after mark as request', async function () { + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + + await session.awaitRunningJobs(template._id); + + const messages = await messageRepository.findBySubscriberChannel( + session.environment._id, + subscriberProfile!._id, + ChannelTypeEnum.IN_APP + ); + const messageId = messages[0]._id; + + let seenCount = (await getFeedCount({ seen: false })).data.count; + expect(seenCount).to.equal(3); + + await invalidateCache.invalidateQuery({ + key: buildFeedKey().invalidate({ + subscriberId: subscriberId, + _environmentId: session.environment._id, + }), + }); + + await invalidateCache.invalidateQuery({ + key: buildMessageCountKey().invalidate({ + subscriberId: subscriberId, + _environmentId: session.environment._id, + }), + }); + + await axios.post( + `http://localhost:${process.env.PORT}/v1/widgets/messages/markAs`, + { messageId, mark: { seen: true } }, + { + headers: { + Authorization: `Bearer ${subscriberToken}`, + }, + } + ); + + seenCount = (await getFeedCount({ seen: false })).data.count; + expect(seenCount).to.equal(2); + }); + async function getFeedCount(query = {}) { const response = await axios.get(`http://localhost:${process.env.PORT}/v1/widgets/notifications/count`, { params: { diff --git a/apps/api/src/app/widgets/e2e/get-unseen-count.e2e.ts b/apps/api/src/app/widgets/e2e/get-unseen-count.e2e.ts index b1009908212..5ea0000481b 100644 --- a/apps/api/src/app/widgets/e2e/get-unseen-count.e2e.ts +++ b/apps/api/src/app/widgets/e2e/get-unseen-count.e2e.ts @@ -51,7 +51,7 @@ describe('Unseen Count - GET /widget/notifications/unseen', function () { subscriberProfile = profile; }); - it('should return unseen count with a seen filter', async function () { + it('should return unseen count with no query', async function () { await session.triggerEvent(template.triggers[0].identifier, subscriberId); await session.triggerEvent(template.triggers[0].identifier, subscriberId); await session.triggerEvent(template.triggers[0].identifier, subscriberId); @@ -76,30 +76,28 @@ describe('Unseen Count - GET /widget/notifications/unseen', function () { } ); - const unseenFeed = await getFeedCount({ seen: false }); + const unseenFeed = await getUnseenCount(); expect(unseenFeed.data.count).to.equal(2); }); - it('should return unread count with a read filter', async function () { + it('should return unseen count with query seen false', async function () { await session.triggerEvent(template.triggers[0].identifier, subscriberId); await session.triggerEvent(template.triggers[0].identifier, subscriberId); await session.triggerEvent(template.triggers[0].identifier, subscriberId); await session.awaitRunningJobs(template._id); - if (!subscriberProfile) throw new Error('Subscriber profile is null'); const messages = await messageRepository.findBySubscriberChannel( session.environment._id, - subscriberProfile._id, + subscriberProfile!._id, ChannelTypeEnum.IN_APP ); - const messageId = messages[0]._id; - expect(messages[0].read).to.equal(false); + expect(messages[0].seen).to.equal(false); await axios.post( `http://localhost:${process.env.PORT}/v1/widgets/messages/markAs`, - { messageId, mark: { seen: true, read: true } }, + { messageId, mark: { seen: true } }, { headers: { Authorization: `Bearer ${subscriberToken}`, @@ -107,11 +105,37 @@ describe('Unseen Count - GET /widget/notifications/unseen', function () { } ); - const readFeed = await getFeedCount({ read: true }); - expect(readFeed.data.count).to.equal(1); + const unseenFeed = await getUnseenCount({ seen: false }); + expect(unseenFeed.data.count).to.equal(2); + }); + + it('should return unseen count with query seen true', async function () { + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + await session.triggerEvent(template.triggers[0].identifier, subscriberId); + + await session.awaitRunningJobs(template._id); + + const messages = await messageRepository.findBySubscriberChannel( + session.environment._id, + subscriberProfile!._id, + ChannelTypeEnum.IN_APP + ); + const messageId = messages[0]._id; + expect(messages[0].seen).to.equal(false); + + await axios.post( + `http://localhost:${process.env.PORT}/v1/widgets/messages/markAs`, + { messageId, mark: { seen: true } }, + { + headers: { + Authorization: `Bearer ${subscriberToken}`, + }, + } + ); - const unreadFeed = await getFeedCount({ read: false }); - expect(unreadFeed.data.count).to.equal(2); + const seenFeed = await getUnseenCount({ seen: true }); + expect(seenFeed.data.count).to.equal(1); }); it('should return unseen count after mark as request', async function () { @@ -128,7 +152,7 @@ describe('Unseen Count - GET /widget/notifications/unseen', function () { ); const messageId = messages[0]._id; - let seenCount = (await getFeedCount({ seen: false })).data.count; + let seenCount = (await getUnseenCount({ seen: false })).data.count; expect(seenCount).to.equal(3); await invalidateCache.invalidateQuery({ @@ -155,12 +179,12 @@ describe('Unseen Count - GET /widget/notifications/unseen', function () { } ); - seenCount = (await getFeedCount({ seen: false })).data.count; + seenCount = (await getUnseenCount({ seen: false })).data.count; expect(seenCount).to.equal(2); }); - async function getFeedCount(query = {}) { - const response = await axios.get(`http://localhost:${process.env.PORT}/v1/widgets/notifications/count`, { + async function getUnseenCount(query = {}) { + const response = await axios.get(`http://localhost:${process.env.PORT}/v1/widgets/notifications/unseen`, { params: { ...query, }, diff --git a/apps/api/src/app/widgets/widgets.controller.ts b/apps/api/src/app/widgets/widgets.controller.ts index 6f8face63ee..f1dff06ba80 100644 --- a/apps/api/src/app/widgets/widgets.controller.ts +++ b/apps/api/src/app/widgets/widgets.controller.ts @@ -128,6 +128,10 @@ export class WidgetsController { ): Promise { const feedsQuery = this.toArray(feedId); + if (seen === undefined) { + seen = false; + } + const command = GetFeedCountCommand.create({ organizationId: subscriberSession._organizationId, subscriberId: subscriberSession.subscriberId,