diff --git a/package.json b/package.json
index 214c45c..497174f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "recycle-study-extension",
- "version": "1.1.0",
+ "version": "1.1.1",
"description": "복습 URL 저장 크롬 익스텐션",
"type": "module",
"scripts": {
diff --git a/public/manifest.json b/public/manifest.json
index f443b7a..016f2e6 100644
--- a/public/manifest.json
+++ b/public/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Recycle Study",
- "version": "1.1.0",
+ "version": "1.1.1",
"description": "복습 URL을 저장하고 스케줄에 따라 알림을 받는 익스텐션",
"permissions": [
"storage",
diff --git a/public/popup.html b/public/popup.html
index ad77867..e5b1515 100644
--- a/public/popup.html
+++ b/public/popup.html
@@ -70,6 +70,17 @@
나의 복습 주기
+
+
+
+
알림 시간
+
+
+
+
+
+
+
diff --git a/src/__tests__/api.test.js b/src/__tests__/api.test.js
index b9f6e55..6b6a0eb 100644
--- a/src/__tests__/api.test.js
+++ b/src/__tests__/api.test.js
@@ -7,7 +7,9 @@ import {
getCycleOptions,
createCustomCycle,
updateCustomCycle,
- deleteCustomCycle
+ deleteCustomCycle,
+ getNotificationTime,
+ updateNotificationTime
} from '../api.js';
import { ERROR_CODES } from '../constants.js';
@@ -222,6 +224,55 @@ describe('api.js', () => {
});
});
+ describe('getNotificationTime', () => {
+ it('식별자를 헤더에 포함하여 알림 시간을 조회한다', async () => {
+ const identifier = 'my-device-id';
+ const mockResponse = { success: true, data: { notificationTime: '09:00:00' } };
+ sendMessageMock.mockResolvedValue(mockResponse);
+
+ const result = await getNotificationTime(identifier);
+
+ expect(sendMessageMock).toHaveBeenCalledWith({
+ type: 'API_REQUEST',
+ request: {
+ endpoint: '/api/v1/members/notification-time',
+ method: 'GET',
+ headers: { 'X-Device-Id': identifier }
+ }
+ });
+ expect(result).toEqual(mockResponse.data);
+ });
+
+ it('알림 시간이 설정되지 않은 경우 null을 반환한다', async () => {
+ const mockResponse = { success: true, data: { notificationTime: null } };
+ sendMessageMock.mockResolvedValue(mockResponse);
+
+ const result = await getNotificationTime('my-device-id');
+
+ expect(result.notificationTime).toBeNull();
+ });
+ });
+
+ describe('updateNotificationTime', () => {
+ it('[hour, minute] 배열로 알림 시간을 업데이트한다', async () => {
+ const identifier = 'my-device-id';
+ const mockResponse = { success: true, data: null };
+ sendMessageMock.mockResolvedValue(mockResponse);
+
+ await updateNotificationTime(identifier, 9, 0);
+
+ expect(sendMessageMock).toHaveBeenCalledWith({
+ type: 'API_REQUEST',
+ request: {
+ endpoint: '/api/v1/members/notification-time',
+ method: 'PATCH',
+ headers: { 'X-Device-Id': identifier },
+ body: { notificationTime: [9, 0] }
+ }
+ });
+ });
+ });
+
describe('Error Handling', () => {
it('API 실패 시 에러를 던진다', async () => {
sendMessageMock.mockResolvedValue({
diff --git a/src/api.js b/src/api.js
index 5660700..ecd7784 100644
--- a/src/api.js
+++ b/src/api.js
@@ -148,3 +148,31 @@ export async function deleteCustomCycle(identifier, id) {
headers: { 'X-Device-Id': identifier }
});
}
+
+/**
+ * 알림 시간 조회
+ * @param {string} identifier - 디바이스 식별자
+ * @returns {Promise