From c03eda8425e88f96053e592841d73469f3d660e1 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Fri, 17 Nov 2023 16:19:58 +0100 Subject: [PATCH 1/2] Fix filtering of active broadcasts Admin users get all the broadcasts notifications regardless of their "activation" status so we need to apply the filtering also in the client. Regular users are not affected because they can only get active broadcasts. --- client/src/stores/broadcastsStore.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/client/src/stores/broadcastsStore.ts b/client/src/stores/broadcastsStore.ts index 8395b5915218..d465aeb81f8f 100644 --- a/client/src/stores/broadcastsStore.ts +++ b/client/src/stores/broadcastsStore.ts @@ -16,7 +16,7 @@ export const useBroadcastsStore = defineStore( const dismissedBroadcasts = ref<{ [key: string]: Expirable }>({}); const activeBroadcasts = computed(() => { - return broadcasts.value.filter((b) => !dismissedBroadcasts.value[b.id]); + return broadcasts.value.filter(isActive); }); async function loadBroadcasts() { @@ -40,6 +40,14 @@ export const useBroadcastsStore = defineStore( Vue.set(dismissedBroadcasts.value, broadcast.id, { expiration_time: broadcast.expiration_time }); } + function isActive(broadcast: BroadcastNotification) { + return ( + !dismissedBroadcasts.value[broadcast.id] && + !hasExpired(broadcast.expiration_time) && + hasBeenPublished(broadcast) + ); + } + function hasExpired(expirationTimeStr?: string) { if (!expirationTimeStr) { return false; @@ -49,6 +57,12 @@ export const useBroadcastsStore = defineStore( return now > expirationTime; } + function hasBeenPublished(broadcast: BroadcastNotification) { + const publicationTime = new Date(`${broadcast.publication_time}Z`); + const now = new Date(); + return now >= publicationTime; + } + function clearExpiredDismissedBroadcasts() { for (const key in dismissedBroadcasts.value) { if (hasExpired(dismissedBroadcasts.value[key]?.expiration_time)) { From 8d514b1c3bcd798e4e461dd87d1ef112c4a3c431 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Fri, 17 Nov 2023 17:52:53 +0100 Subject: [PATCH 2/2] Add tests for expired and unpublished broadcasts --- .../Broadcasts/BroadcastsOverlay.test.ts | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/client/src/components/Notifications/Broadcasts/BroadcastsOverlay.test.ts b/client/src/components/Notifications/Broadcasts/BroadcastsOverlay.test.ts index 9c423edb6dda..c13a1d896741 100644 --- a/client/src/components/Notifications/Broadcasts/BroadcastsOverlay.test.ts +++ b/client/src/components/Notifications/Broadcasts/BroadcastsOverlay.test.ts @@ -9,15 +9,26 @@ import { type BroadcastNotification, useBroadcastsStore } from "@/stores/broadca const localVue = getLocalVue(true); const now = new Date(); -const inTwoMonths = new Date(now.setMonth(now.getMonth() + 2)); +const inTwoMonths = new Date(new Date(now).setMonth(now.getMonth() + 2)); -function generateBroadcastNotification(id: string): BroadcastNotification { +/** API date-time does not have timezone indicator and it's always UTC. */ +function toApiDate(date: Date): string { + return date.toISOString().replace("Z", ""); +} + +function generateBroadcastNotification( + id: string, + publicationTime?: Date, + expirationTime?: Date +): BroadcastNotification { + const publication_time = publicationTime ? toApiDate(publicationTime) : toApiDate(now); + const expiration_time = expirationTime ? toApiDate(expirationTime) : toApiDate(inTwoMonths); return { id: id, - create_time: now.toISOString(), - update_time: now.toISOString(), - publication_time: now.toISOString(), - expiration_time: inTwoMonths.toISOString(), + create_time: toApiDate(now), + update_time: toApiDate(now), + publication_time, + expiration_time, source: "testing", variant: "info", content: { @@ -78,4 +89,20 @@ describe("BroadcastsOverlay.vue", () => { expect(wrapper.findAll(".broadcast-message")).toHaveLength(1); expect(wrapper.find(".broadcast-message").text()).toContain("Test message 2"); }); + + it("should not render the broadcast when it has expired", async () => { + const expiredBroadcast = generateBroadcastNotification("expired", undefined, new Date(now)); + const wrapper = await mountBroadcastsOverlayWith([expiredBroadcast]); + + expect(wrapper.exists()).toBe(true); + expect(wrapper.html()).toBe(""); + }); + + it("should not render the broadcast when it has not been published yet", async () => { + const unpublishedBroadcast = generateBroadcastNotification("unpublished", new Date(inTwoMonths)); + const wrapper = await mountBroadcastsOverlayWith([unpublishedBroadcast]); + + expect(wrapper.exists()).toBe(true); + expect(wrapper.html()).toBe(""); + }); });