Skip to content

Commit 6fb93b0

Browse files
authored
test: add remaining tests (#1857)
1 parent d4e8c7c commit 6fb93b0

File tree

5 files changed

+175
-1
lines changed

5 files changed

+175
-1
lines changed

__mocks__/react-native.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ const mockRNOneSignal = {
8585
addUniqueOutcome: vi.fn(),
8686
addOutcomeWithValue: vi.fn(),
8787
displayNotification: vi.fn(),
88+
preventDefault: vi.fn(),
8889
};
8990

9091
const mockPlatform = {
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import { NativeModules } from 'react-native';
2+
import OSNotification, { type BaseNotificationData } from '../OSNotification';
3+
import NotificationWillDisplayEvent from './NotificationWillDisplayEvent';
4+
5+
const mockRNOneSignal = NativeModules.OneSignal;
6+
7+
describe('NotificationWillDisplayEvent', () => {
8+
const notificationId = 'test-notification-id';
9+
const baseNotificationData: BaseNotificationData = {
10+
body: 'Test notification body',
11+
sound: 'default',
12+
title: 'Test Title',
13+
launchURL: 'https://example.com',
14+
rawPayload: { key: 'value' },
15+
actionButtons: [{ id: 'btn1', text: 'Button 1' }],
16+
additionalData: { custom: 'data' },
17+
notificationId,
18+
};
19+
20+
describe('constructor', () => {
21+
test('should initialize with OSNotification instance', () => {
22+
const notification = new OSNotification(baseNotificationData);
23+
const event = new NotificationWillDisplayEvent(notification);
24+
25+
expect(event.notification).toBeInstanceOf(OSNotification);
26+
expect(event.notification.notificationId).toBe(notificationId);
27+
expect(event.notification.body).toBe('Test notification body');
28+
expect(event.notification.title).toBe('Test Title');
29+
});
30+
31+
test('should create a new OSNotification instance from the provided notification', () => {
32+
const notification = new OSNotification(baseNotificationData);
33+
const event = new NotificationWillDisplayEvent(notification);
34+
35+
expect(event.notification).not.toBe(notification);
36+
expect(event.notification.notificationId).toBe(notificationId);
37+
expect(event.notification.body).toBe(notification.body);
38+
});
39+
40+
test('should initialize with notification containing all optional fields', () => {
41+
const fullData = {
42+
...baseNotificationData,
43+
sound: 'custom-sound',
44+
launchURL: 'https://example.com/launch',
45+
actionButtons: [
46+
{ id: 'btn1', text: 'Button 1' },
47+
{ id: 'btn2', text: 'Button 2' },
48+
],
49+
additionalData: { key1: 'value1', key2: 'value2' },
50+
};
51+
const notification = new OSNotification(fullData);
52+
const event = new NotificationWillDisplayEvent(notification);
53+
54+
expect(event.notification.sound).toBe('custom-sound');
55+
expect(event.notification.launchURL).toBe('https://example.com/launch');
56+
expect(event.notification.actionButtons).toHaveLength(2);
57+
expect(event.notification.additionalData).toEqual({
58+
key1: 'value1',
59+
key2: 'value2',
60+
});
61+
});
62+
});
63+
64+
describe('preventDefault', () => {
65+
test('should call native preventDefault with notificationId', () => {
66+
const notification = new OSNotification(baseNotificationData);
67+
const event = new NotificationWillDisplayEvent(notification);
68+
const result = event.preventDefault();
69+
70+
expect(mockRNOneSignal.preventDefault).toHaveBeenCalledWith(
71+
notificationId,
72+
);
73+
expect(result).toBeUndefined();
74+
});
75+
76+
test('should allow multiple calls to preventDefault', () => {
77+
const notification = new OSNotification(baseNotificationData);
78+
const event = new NotificationWillDisplayEvent(notification);
79+
80+
event.preventDefault();
81+
event.preventDefault();
82+
event.preventDefault();
83+
84+
expect(mockRNOneSignal.preventDefault).toHaveBeenCalledTimes(3);
85+
expect(mockRNOneSignal.preventDefault).toHaveBeenCalledWith(
86+
'test-notification-id',
87+
);
88+
});
89+
});
90+
91+
describe('getNotification', () => {
92+
test('should return the notification instance', () => {
93+
const notification = new OSNotification(baseNotificationData);
94+
const event = new NotificationWillDisplayEvent(notification);
95+
const returnedNotification = event.getNotification();
96+
97+
expect(returnedNotification).toBe(event.notification);
98+
expect(returnedNotification).toBeInstanceOf(OSNotification);
99+
100+
expect(returnedNotification.notificationId).toBe('test-notification-id');
101+
expect(returnedNotification.body).toBe('Test notification body');
102+
expect(returnedNotification.title).toBe('Test Title');
103+
expect(returnedNotification.sound).toBe('default');
104+
expect(returnedNotification.rawPayload).toEqual({ key: 'value' });
105+
});
106+
});
107+
});

src/events/NotificationWillDisplayEvent.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export default class NotificationWillDisplayEvent {
1111

1212
preventDefault(): void {
1313
RNOneSignal.preventDefault(this.notification.notificationId);
14-
return;
1514
}
1615

1716
getNotification(): OSNotification {

src/helpers.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import type { NativeModule } from 'react-native';
2+
import type { MockInstance } from 'vitest';
3+
import { isNativeModuleLoaded, isValidCallback } from './helpers';
4+
5+
describe('helpers', () => {
6+
let errorSpy: MockInstance;
7+
8+
beforeEach(() => {
9+
errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
10+
});
11+
12+
describe('isValidCallback', () => {
13+
test('should not throw when handler is a function', () => {
14+
const handler = () => {};
15+
expect(() => isValidCallback(handler)).not.toThrow();
16+
});
17+
18+
test.each([
19+
{ description: 'null', value: null },
20+
{ description: 'undefined', value: undefined },
21+
{ description: 'a string', value: 'not a function' },
22+
{ description: 'a number', value: 123 },
23+
{ description: 'an object', value: {} },
24+
{ description: 'an array', value: [] },
25+
{ description: 'a boolean', value: true },
26+
])(
27+
'should throw invariant error when handler is $description',
28+
({ value }) => {
29+
expect(() => isValidCallback(value as unknown as Function)).toThrow(
30+
'Must provide a valid callback',
31+
);
32+
},
33+
);
34+
});
35+
36+
describe('isNativeModuleLoaded', () => {
37+
test.each([
38+
{ description: 'null', value: null as unknown as NativeModule },
39+
{
40+
description: 'undefined',
41+
value: undefined as unknown as NativeModule,
42+
},
43+
])(
44+
'should return false and log error when module is $description',
45+
({ value }) => {
46+
const result = isNativeModuleLoaded(value);
47+
48+
expect(result).toBe(false);
49+
expect(errorSpy).toHaveBeenCalledTimes(1);
50+
expect(errorSpy).toHaveBeenCalledWith(
51+
'Could not load RNOneSignal native module. Make sure native dependencies are properly linked.',
52+
);
53+
},
54+
);
55+
56+
test('should return true when module is loaded', () => {
57+
const result = isNativeModuleLoaded({} as NativeModule);
58+
expect(result).toBe(true);
59+
});
60+
});
61+
});

vitest.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ export default defineConfig({
1313
reporter: ['text-summary', 'lcov'],
1414
reportOnFailure: true,
1515
reportsDirectory: 'coverage',
16+
thresholds: {
17+
statements: 95,
18+
branches: 95,
19+
functions: 95,
20+
lines: 95,
21+
},
1622
},
1723
},
1824
resolve: {

0 commit comments

Comments
 (0)