Skip to content

Commit 2f56429

Browse files
authored
fix: Fetch notifications API isn't invoked upon successful token verification on retry
1 parent 7cda628 commit 2f56429

File tree

7 files changed

+53
-20
lines changed

7 files changed

+53
-20
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,6 @@
7171
},
7272
"dependencies": {
7373
"pubsub-js": "^1.9.4",
74-
"test_notification": "^1.0.20"
74+
"test_notification": "^1.0.25"
7575
}
7676
}

src/components/SirenPanel.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
mergeArrays,
2525
updateNotifications,
2626
} from "../utils/commonUtils";
27-
import { ERROR_TEXT, events, eventTypes } from "../utils/constants";
27+
import { ERROR_TEXT, events, eventTypes, VerificationStatus } from "../utils/constants";
2828
import useSiren from "../utils/sirenHook";
2929

3030
/**
@@ -94,7 +94,7 @@ const SirenPanel: FC<SirenPanelProps> = ({
9494
deleteNotificationsByDate,
9595
deleteNotification,
9696
} = useSiren();
97-
const { siren } = useSirenContext();
97+
const { siren, verificationStatus } = useSirenContext();
9898
const [notifications, setNotifications] = useState<NotificationDataType[]>(
9999
[]
100100
);
@@ -136,11 +136,12 @@ const SirenPanel: FC<SirenPanelProps> = ({
136136
}, [eventListenerData]);
137137

138138
useEffect(() => {
139-
if (siren) {
139+
if (siren && verificationStatus !== VerificationStatus.PENDING) {
140140
siren.stopRealTimeUnviewedCountFetch();
141141
fetchNotifications(true);
142142
}
143-
}, [siren]);
143+
}, [siren, verificationStatus]);
144+
144145

145146
const restartNotificationCountFetch = () => {
146147
try {

src/components/SirenProvider.tsx

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ import type {
1111

1212
import type { SirenProviderConfigProps } from '../types';
1313
import { logger } from '../utils/commonUtils';
14-
import { events, eventTypes, TOKEN_VERIFICATION_FAILED } from '../utils/constants';
14+
import { events, eventTypes,
15+
IN_APP_RECIPIENT_UNAUTHENTICATED,
16+
MAXIMUM_RETRY_COUNT,
17+
VerificationStatus } from '../utils/constants';
1518

1619

1720
type SirenContextProp = {
1821
siren: Siren | null;
22+
verificationStatus: VerificationStatus;
1923
};
2024

2125
interface SirenProvider {
@@ -24,7 +28,8 @@ interface SirenProvider {
2428
}
2529

2630
export const SirenContext = createContext<SirenContextProp>({
27-
siren: null
31+
siren: null,
32+
verificationStatus: VerificationStatus.PENDING
2833
});
2934

3035
/**
@@ -33,6 +38,7 @@ export const SirenContext = createContext<SirenContextProp>({
3338
* @example
3439
* const {
3540
* siren,
41+
* verificationStatus
3642
* } = useSirenContext();
3743
*
3844
* @returns {SirenContextProp} The Siren notifications context.
@@ -43,9 +49,7 @@ export const useSirenContext = (): SirenContextProp => useContext(SirenContext);
4349
* Provides a React context for Siren notifications, making Siren SDK functionality
4450
* available throughout your React application.
4551
*
46-
* `SirenProvider` initializes the Siren SDK with given configuration and manages the state for
47-
* notifications, including fetching new notifications, handling errors, and tracking the count
48-
* of unviewed notifications.
52+
* `SirenProvider` initializes the Siren SDK with given configuration and manages the state for siren and verificationStatus.
4953
*
5054
* @component
5155
* @example
@@ -64,6 +68,7 @@ export const useSirenContext = (): SirenContextProp => useContext(SirenContext);
6468
*/
6569
const SirenProvider: React.FC<SirenProvider> = ({ config, children }) => {
6670
const [siren, setSiren] = useState<Siren | null>(null);
71+
const [verificationStatus, setVerificationStatus] = useState<VerificationStatus>(VerificationStatus.PENDING);
6772
let retryCount = 0;
6873

6974
useEffect(() => {
@@ -72,6 +77,9 @@ const SirenProvider: React.FC<SirenProvider> = ({ config, children }) => {
7277
sendResetDataEvents();
7378
initialize();
7479
}
80+
if(retryCount > MAXIMUM_RETRY_COUNT)
81+
stopRealTimeFetch();
82+
7583
}, [config]);
7684

7785
const stopRealTimeFetch = (): void => {
@@ -113,7 +121,11 @@ const SirenProvider: React.FC<SirenProvider> = ({ config, children }) => {
113121
}
114122
};
115123

116-
const actionCallbacks = { onUnViewedCountReceived, onNotificationReceived };
124+
const onStatusChange = (status: VerificationStatus) => {
125+
setVerificationStatus(status);
126+
};
127+
128+
const actionCallbacks = { onUnViewedCountReceived, onNotificationReceived, onStatusChange };
117129

118130
const getDataParams = () => {
119131
return {
@@ -125,7 +137,7 @@ const SirenProvider: React.FC<SirenProvider> = ({ config, children }) => {
125137
};
126138

127139
const retryVerification = (error: SirenErrorType) => {
128-
if (error.Code === TOKEN_VERIFICATION_FAILED && retryCount < 3)
140+
if (error.Code === IN_APP_RECIPIENT_UNAUTHENTICATED && retryCount < MAXIMUM_RETRY_COUNT)
129141
setTimeout(() => {
130142
initialize();
131143
retryCount++;
@@ -143,7 +155,8 @@ const SirenProvider: React.FC<SirenProvider> = ({ config, children }) => {
143155
return (
144156
<SirenContext.Provider
145157
value={{
146-
siren
158+
siren,
159+
verificationStatus
147160
}}
148161
>
149162
{children}

src/utils/constants.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ export const ERROR_SUB_TEXT =
100100
export const DEFAULT_WINDOW_TITLE = "Notifications";
101101
export const RETRY_BUTTON_LABEL = "Retry";
102102
export const CLEAR_ALL_LABEL = "Clear All";
103-
export const TOKEN_VERIFICATION_FAILED = 'TOKEN_VERIFICATION_FAILED';
103+
export const IN_APP_RECIPIENT_UNAUTHENTICATED = 'IN_APP_RECIPIENT_UNAUTHENTICATED';
104+
export const TOKEN_VERIFICATION_PENDING ='TOKEN_VERIFICATION_PENDING';
105+
export const MAXIMUM_RETRY_COUNT = 3;
104106
export const MAXIMUM_ITEMS_PER_FETCH = 50;
105107

106108
export const errorMap = {
@@ -115,3 +117,9 @@ export const errorMap = {
115117
Message: "Missing Parameter",
116118
},
117119
};
120+
121+
export enum VerificationStatus {
122+
PENDING = "PENDING",
123+
SUCCESS = "SUCCESS",
124+
FAILED = "FAILED"
125+
}

tests/components/sirenNotificationIcon.spec.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ import { fireEvent, render } from "@testing-library/react";
55
import SirenNotificationIcon from "../../src/components/SirenNotificationIcon";
66
import { SirenContext } from "../../src/components/SirenProvider"; // Assuming SirenProvider exports SirenContext
77
import { applyTheme } from "../../src/utils/commonUtils";
8+
import { VerificationStatus } from "../../src/utils/constants";
89

910
const mockClickFn = jest.fn();
1011

1112
// Mock the CSS file to avoid Jest error
1213
jest.mock("../../src/styles/sirenNotificationIcon.css", () => ({}));
1314

1415
const mockSirenContextValue = {
15-
siren: null
16+
siren: null,
17+
verificationStatus: VerificationStatus.SUCCESS
1618
};
1719

1820
const style = applyTheme();

tests/utils/sirenHook.spec.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { Siren } from "test_notification";
22

33
import { useSiren } from "../../src";
44
import * as sirenProvider from "../../src/components/SirenProvider";
5-
import { errorMap } from "../../src/utils/constants";
5+
import { errorMap, VerificationStatus } from "../../src/utils/constants";
66

77

88
// Mock the CSS files to avoid Jest error
@@ -102,6 +102,7 @@ describe("useSiren hook", () => {
102102
it("should call siren.markNotificationAsReadById and return error", async () => {
103103
jest.spyOn(sirenProvider, "useSirenContext").mockReturnValue({
104104
siren: mockSirenCore as Siren,
105+
verificationStatus: VerificationStatus.SUCCESS
105106
});
106107

107108
const { markAsRead } = useSiren();
@@ -126,6 +127,7 @@ describe("useSiren hook", () => {
126127
// Mock useSirenContext
127128
jest.spyOn(sirenProvider, "useSirenContext").mockReturnValue({
128129
siren: mockCore as Siren,
130+
verificationStatus: VerificationStatus.SUCCESS
129131
});
130132

131133
const { markAsRead } = useSiren();
@@ -144,6 +146,7 @@ describe("useSiren hook", () => {
144146
// Mock useSirenContext
145147
jest.spyOn(sirenProvider, "useSirenContext").mockReturnValue({
146148
siren: mockSirenCore as Siren,
149+
verificationStatus: VerificationStatus.SUCCESS
147150
});
148151

149152
const { markAsRead } = useSiren();
@@ -158,6 +161,7 @@ describe("useSiren hook", () => {
158161

159162
jest.spyOn(sirenProvider, "useSirenContext").mockReturnValue({
160163
siren: mockSirenCore as Siren,
164+
verificationStatus: VerificationStatus.SUCCESS
161165
});
162166

163167
const { markNotificationsAsReadByDate } = useSiren();
@@ -176,6 +180,7 @@ describe("useSiren hook", () => {
176180
// Mock useSirenContext
177181
jest.spyOn(sirenProvider, "useSirenContext").mockReturnValue({
178182
siren: mockSirenCore as Siren,
183+
verificationStatus: VerificationStatus.SUCCESS
179184
});
180185

181186
const { markNotificationsAsReadByDate } = useSiren();
@@ -192,6 +197,7 @@ describe("useSiren hook", () => {
192197

193198
jest.spyOn(sirenProvider, "useSirenContext").mockReturnValue({
194199
siren: mockSirenCore as Siren,
200+
verificationStatus: VerificationStatus.SUCCESS
195201
});
196202

197203
const { deleteNotification } = useSiren();
@@ -206,6 +212,7 @@ describe("useSiren hook", () => {
206212
// Mock useSirenContext
207213
jest.spyOn(sirenProvider, "useSirenContext").mockReturnValue({
208214
siren: mockSirenCore as Siren,
215+
verificationStatus: VerificationStatus.SUCCESS
209216
});
210217

211218
const { deleteNotification } = useSiren();
@@ -220,6 +227,7 @@ describe("useSiren hook", () => {
220227

221228
jest.spyOn(sirenProvider, "useSirenContext").mockReturnValue({
222229
siren: mockSirenCore as Siren,
230+
verificationStatus: VerificationStatus.SUCCESS
223231
});
224232

225233
const { deleteNotificationsByDate } = useSiren();
@@ -237,6 +245,7 @@ describe("useSiren hook", () => {
237245

238246
jest.spyOn(sirenProvider, "useSirenContext").mockReturnValue({
239247
siren: mockSirenCore as Siren,
248+
verificationStatus: VerificationStatus.SUCCESS
240249
});
241250

242251
const { markNotificationsAsViewed } = useSiren();

0 commit comments

Comments
 (0)