You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

253 lines
7.5 KiB

/**
* Tests for the Daily Notification plugin
*
* @author Matthew Raymer
*/
import { DailyNotification } from '../src/daily-notification';
import { DailyNotificationPlugin, NotificationOptions, NotificationStatus, NotificationResponse, NotificationSettings } from '../src/definitions';
import { describe, it, expect, beforeEach, jest } from '@jest/globals';
describe('DailyNotification Plugin', () => {
let plugin: DailyNotification;
let mockPlugin: jest.Mocked<DailyNotificationPlugin>;
const mockOptions: NotificationOptions = {
url: 'https://api.example.com/daily-content',
time: '08:00',
title: 'Test Notification',
body: 'This is a test notification'
};
beforeEach(() => {
// Create mock plugin with all required methods
mockPlugin = {
scheduleDailyNotification: jest.fn(),
getLastNotification: jest.fn(),
cancelAllNotifications: jest.fn(),
getNotificationStatus: jest.fn(),
updateSettings: jest.fn(),
getBatteryStatus: jest.fn(),
requestBatteryOptimizationExemption: jest.fn(),
setAdaptiveScheduling: jest.fn(),
getPowerState: jest.fn(),
checkPermissions: jest.fn(),
requestPermissions: jest.fn(),
};
// Create plugin instance with mock
plugin = new DailyNotification(mockPlugin);
// Reset mocks before each test
jest.clearAllMocks();
});
describe('scheduleDailyNotification', () => {
it('should schedule a basic notification', async () => {
await plugin.scheduleDailyNotification(mockOptions);
// Verify the mock was called with correct parameters
expect(mockPlugin.scheduleDailyNotification).toHaveBeenCalledWith(mockOptions);
});
it('should handle network errors gracefully', async () => {
mockPlugin.scheduleDailyNotification.mockRejectedValueOnce(
new Error('Network error')
);
const errorOptions: NotificationOptions = {
...mockOptions,
url: 'https://invalid-url.com'
};
await expect(plugin.scheduleDailyNotification(errorOptions))
.rejects
.toThrow('Network error');
});
it('should validate required parameters', async () => {
const invalidOptions = {
time: '08:00'
} as NotificationOptions;
await expect(plugin.scheduleDailyNotification(invalidOptions))
.rejects
.toThrow('URL is required');
});
});
describe('getLastNotification', () => {
it('should return the last notification', async () => {
const mockResponse: NotificationResponse = {
id: 'test-notification',
title: 'Last Notification',
body: 'This was the last notification',
timestamp: Date.now()
};
mockPlugin.getLastNotification.mockResolvedValueOnce(mockResponse);
const result = await plugin.getLastNotification();
expect(result).toEqual(mockResponse);
});
it('should return null when no notifications exist', async () => {
mockPlugin.getLastNotification.mockResolvedValueOnce(null);
const result = await plugin.getLastNotification();
expect(result).toBeNull();
});
});
describe('cancelAllNotifications', () => {
it('should cancel all scheduled notifications', async () => {
await plugin.cancelAllNotifications();
// Verify the mock was called
expect(mockPlugin.cancelAllNotifications).toHaveBeenCalled();
});
});
describe('getNotificationStatus', () => {
it('should return current notification status', async () => {
const mockStatus: NotificationStatus = {
isScheduled: true,
nextNotificationTime: Date.now() + 86400000, // 24 hours from now
lastNotificationTime: Date.now(),
settings: {}
};
mockPlugin.getNotificationStatus.mockResolvedValueOnce(mockStatus);
const result = await plugin.getNotificationStatus();
expect(result).toEqual(mockStatus);
});
it('should handle error status', async () => {
const mockErrorStatus: NotificationStatus = {
isScheduled: false,
error: 'Failed to schedule notification',
lastNotificationTime: 0,
nextNotificationTime: 0,
settings: {}
};
mockPlugin.getNotificationStatus.mockResolvedValueOnce(mockErrorStatus);
const result = await plugin.getNotificationStatus();
expect(result).toEqual(mockErrorStatus);
});
});
describe('updateSettings', () => {
it('should update notification settings', async () => {
const settings: NotificationSettings = {
sound: false,
priority: 'high',
timezone: 'UTC'
};
await plugin.updateSettings(settings);
expect(mockPlugin.updateSettings).toHaveBeenCalledWith(settings);
});
});
describe('getBatteryStatus', () => {
it('should return battery status', async () => {
const mockBatteryStatus = {
level: 85,
isCharging: false,
powerState: 1,
isOptimizationExempt: false
};
mockPlugin.getBatteryStatus.mockResolvedValueOnce(mockBatteryStatus);
const result = await plugin.getBatteryStatus();
expect(result).toEqual(mockBatteryStatus);
});
});
describe('requestBatteryOptimizationExemption', () => {
it('should request battery optimization exemption', async () => {
await plugin.requestBatteryOptimizationExemption();
expect(mockPlugin.requestBatteryOptimizationExemption).toHaveBeenCalled();
});
});
describe('setAdaptiveScheduling', () => {
it('should set adaptive scheduling', async () => {
await plugin.setAdaptiveScheduling({ enabled: true });
expect(mockPlugin.setAdaptiveScheduling).toHaveBeenCalledWith({ enabled: true });
});
});
describe('getPowerState', () => {
it('should return power state', async () => {
const mockPowerState = {
powerState: 1,
isOptimizationExempt: false
};
mockPlugin.getPowerState.mockResolvedValueOnce(mockPowerState);
const result = await plugin.getPowerState();
expect(result).toEqual(mockPowerState);
});
});
describe('validation', () => {
it('should validate URL format', async () => {
const invalidOptions = {
...mockOptions,
url: 'invalid-url'
};
await expect(plugin.scheduleDailyNotification(invalidOptions))
.rejects
.toThrow('Invalid URL format');
});
it('should validate time format', async () => {
const invalidOptions = {
...mockOptions,
time: '25:00'
};
await expect(plugin.scheduleDailyNotification(invalidOptions))
.rejects
.toThrow('Invalid time format');
});
it('should validate timezone format', async () => {
const invalidOptions = {
...mockOptions,
timezone: 'Invalid/Timezone'
};
await expect(plugin.scheduleDailyNotification(invalidOptions))
.rejects
.toThrow('Invalid timezone');
});
it('should validate retry count range', async () => {
const invalidOptions = {
...mockOptions,
retryCount: 15
};
await expect(plugin.scheduleDailyNotification(invalidOptions))
.rejects
.toThrow('Retry count must be between 0 and 10');
});
it('should validate retry interval range', async () => {
const invalidOptions = {
...mockOptions,
retryInterval: 50
};
await expect(plugin.scheduleDailyNotification(invalidOptions))
.rejects
.toThrow('Retry interval must be between 100ms and 60s');
});
});
});