Skip to content

Commit 68b035f

Browse files
feat(frontend): Utils to check dismissed notifications
1 parent 9b31ff7 commit 68b035f

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const NOTIFICATION_VERSIONS = {
2+
BtcActivityInfo: 1,
3+
NoIndexCanister: 1,
4+
UnavailableIndexCanister: 1
5+
} as const;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type { DismissedNotification } from '$declarations/backend/backend.did';
2+
import { NOTIFICATION_VERSIONS } from '$lib/constants/notification.constants';
3+
4+
type NotificationKind = keyof typeof NOTIFICATION_VERSIONS;
5+
6+
export const isSimpleNotificationDismissed = ({
7+
kind,
8+
dismissedNotifications
9+
}: {
10+
kind: NotificationKind;
11+
dismissedNotifications: DismissedNotification[];
12+
}): boolean =>
13+
dismissedNotifications.some(
14+
(n) =>
15+
'Simple' in n && kind in n.Simple.kind && n.Simple.version === NOTIFICATION_VERSIONS[kind]
16+
);
17+
18+
export const filterUndismissedNotificationQualifiers = ({
19+
kind,
20+
qualifiers,
21+
dismissedNotifications
22+
}: {
23+
kind: NotificationKind;
24+
qualifiers: string[];
25+
dismissedNotifications: DismissedNotification[];
26+
}): string[] =>
27+
qualifiers.filter(
28+
(qualifier) =>
29+
!dismissedNotifications.some(
30+
(n) =>
31+
'Qualified' in n &&
32+
kind in n.Qualified.kind &&
33+
n.Qualified.qualifier === qualifier &&
34+
n.Qualified.version === NOTIFICATION_VERSIONS[kind]
35+
)
36+
);
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import type { DismissedNotification } from '$declarations/backend/backend.did';
2+
import { NOTIFICATION_VERSIONS } from '$lib/constants/notification.constants';
3+
import {
4+
filterUndismissedNotificationQualifiers,
5+
isSimpleNotificationDismissed
6+
} from '$lib/utils/notification.utils';
7+
8+
describe('notification.utils', () => {
9+
const simple = (
10+
kind: 'BtcActivityInfo',
11+
version = NOTIFICATION_VERSIONS[kind]
12+
): DismissedNotification => ({
13+
Simple: { kind: { [kind]: null } as { BtcActivityInfo: null }, version }
14+
});
15+
16+
const qualified = (
17+
kind: 'NoIndexCanister' | 'UnavailableIndexCanister',
18+
qualifier: string,
19+
version = NOTIFICATION_VERSIONS[kind]
20+
): DismissedNotification => ({
21+
Qualified: {
22+
kind: { [kind]: null } as { NoIndexCanister: null } | { UnavailableIndexCanister: null },
23+
qualifier,
24+
version
25+
}
26+
});
27+
28+
describe('isSimpleNotificationDismissed', () => {
29+
it('should return true when the kind is in the list with current version', () => {
30+
const dismissed: DismissedNotification[] = [
31+
simple('BtcActivityInfo'),
32+
qualified('NoIndexCanister', 'ETH')
33+
];
34+
35+
expect(
36+
isSimpleNotificationDismissed({
37+
kind: 'BtcActivityInfo',
38+
dismissedNotifications: dismissed
39+
})
40+
).toBeTruthy();
41+
});
42+
43+
it('should return false when the kind has an old version', () => {
44+
// @ts-expect-error we test this on purpose
45+
const dismissed: DismissedNotification[] = [simple('BtcActivityInfo', 0)];
46+
47+
expect(
48+
isSimpleNotificationDismissed({
49+
kind: 'BtcActivityInfo',
50+
dismissedNotifications: dismissed
51+
})
52+
).toBeFalsy();
53+
});
54+
55+
it('should return false when the kind is not in the list', () => {
56+
const dismissed: DismissedNotification[] = [qualified('NoIndexCanister', 'ETH')];
57+
58+
expect(
59+
isSimpleNotificationDismissed({
60+
kind: 'BtcActivityInfo',
61+
dismissedNotifications: dismissed
62+
})
63+
).toBeFalsy();
64+
});
65+
66+
it('should return false for empty list', () => {
67+
expect(
68+
isSimpleNotificationDismissed({ kind: 'BtcActivityInfo', dismissedNotifications: [] })
69+
).toBeFalsy();
70+
});
71+
});
72+
73+
describe('filterUndismissedNotificationQualifiers', () => {
74+
describe('NoIndexCanister kind', () => {
75+
it('should return all qualifiers when none are dismissed', () => {
76+
const result = filterUndismissedNotificationQualifiers({
77+
kind: 'NoIndexCanister',
78+
qualifiers: ['BTC', 'ETH', 'ICP'],
79+
dismissedNotifications: []
80+
});
81+
82+
expect(result).toEqual(['BTC', 'ETH', 'ICP']);
83+
});
84+
85+
it('should filter out dismissed qualifiers', () => {
86+
const result = filterUndismissedNotificationQualifiers({
87+
kind: 'NoIndexCanister',
88+
qualifiers: ['BTC', 'ETH', 'ICP'],
89+
dismissedNotifications: [
90+
qualified('NoIndexCanister', 'BTC'),
91+
qualified('NoIndexCanister', 'ICP')
92+
]
93+
});
94+
95+
expect(result).toEqual(['ETH']);
96+
});
97+
98+
it('should return empty array when all qualifiers are dismissed', () => {
99+
const result = filterUndismissedNotificationQualifiers({
100+
kind: 'NoIndexCanister',
101+
qualifiers: ['BTC', 'ETH'],
102+
dismissedNotifications: [
103+
qualified('NoIndexCanister', 'BTC'),
104+
qualified('NoIndexCanister', 'ETH')
105+
]
106+
});
107+
108+
expect(result).toEqual([]);
109+
});
110+
111+
it('should not filter qualifiers dismissed under a different kind', () => {
112+
const result = filterUndismissedNotificationQualifiers({
113+
kind: 'NoIndexCanister',
114+
qualifiers: ['BTC', 'ETH'],
115+
dismissedNotifications: [
116+
qualified('UnavailableIndexCanister', 'BTC'),
117+
simple('BtcActivityInfo')
118+
]
119+
});
120+
121+
expect(result).toEqual(['BTC', 'ETH']);
122+
});
123+
124+
it('should not filter qualifiers dismissed with an old version', () => {
125+
const result = filterUndismissedNotificationQualifiers({
126+
kind: 'NoIndexCanister',
127+
qualifiers: ['BTC'],
128+
// @ts-expect-error we test this on purpose
129+
dismissedNotifications: [qualified('NoIndexCanister', 'BTC', 0)]
130+
});
131+
132+
expect(result).toEqual(['BTC']);
133+
});
134+
});
135+
136+
describe('UnavailableIndexCanister kind', () => {
137+
it('should filter dismissed UnavailableIndexCanister qualifiers', () => {
138+
const result = filterUndismissedNotificationQualifiers({
139+
kind: 'UnavailableIndexCanister',
140+
qualifiers: ['BTC', 'ETH', 'ICP'],
141+
dismissedNotifications: [qualified('UnavailableIndexCanister', 'ETH')]
142+
});
143+
144+
expect(result).toEqual(['BTC', 'ICP']);
145+
});
146+
147+
it('should not filter qualifiers dismissed under NoIndexCanister', () => {
148+
const result = filterUndismissedNotificationQualifiers({
149+
kind: 'UnavailableIndexCanister',
150+
qualifiers: ['BTC'],
151+
dismissedNotifications: [qualified('NoIndexCanister', 'BTC')]
152+
});
153+
154+
expect(result).toEqual(['BTC']);
155+
});
156+
});
157+
158+
it('should return empty array when qualifiers is empty', () => {
159+
const result = filterUndismissedNotificationQualifiers({
160+
kind: 'NoIndexCanister',
161+
qualifiers: [],
162+
dismissedNotifications: [qualified('NoIndexCanister', 'BTC')]
163+
});
164+
165+
expect(result).toEqual([]);
166+
});
167+
});
168+
});

0 commit comments

Comments
 (0)