From 338833c5bd433dfcda00f2fe4b9188e7e600db4b Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 1 Jun 2026 15:09:44 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20test:=20add=20error=20path=20tes?= =?UTF-8?q?t=20for=20getRecentAppIds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Export RECENT_APP_STORAGE_KEY and MAX_RECENT_APP_COUNT for testing. - Add comprehensive unit tests for getRecentAppIds and rememberRecentApp. - Cover error paths including invalid JSON, non-array data, and non-integer values in localStorage. Co-authored-by: sunnylqm <615282+sunnylqm@users.noreply.github.com> --- src/utils/helper.test.ts | 119 ++++++++++++++++++++++++++++++++++++++- src/utils/helper.ts | 4 +- 2 files changed, 119 insertions(+), 4 deletions(-) diff --git a/src/utils/helper.test.ts b/src/utils/helper.test.ts index 99d5ad3..c5b5d7a 100644 --- a/src/utils/helper.test.ts +++ b/src/utils/helper.test.ts @@ -1,5 +1,12 @@ -import { describe, expect, test } from 'bun:test'; -import { isExpVersion, isPasswordValid } from './helper'; +import { describe, expect, test, mock } from 'bun:test'; +import { + MAX_RECENT_APP_COUNT, + RECENT_APP_STORAGE_KEY, + getRecentAppIds, + isExpVersion, + isPasswordValid, + rememberRecentApp, +} from './helper'; describe('isPasswordValid', () => { test('should return true for valid passwords', () => { @@ -100,3 +107,111 @@ describe('isValidExternalUrl', () => { expect(isValidExternalUrl('javascript:alert(1)')).toBe(false); }); }); + +describe('RecentAppIds', () => { + const originalWindow = (global as any).window; + + test('getRecentAppIds should return empty array when window is undefined', () => { + (global as any).window = undefined; + expect(getRecentAppIds()).toEqual([]); + (global as any).window = originalWindow; + }); + + test('getRecentAppIds should return parsed array from localStorage', () => { + const mockStorage = { + getItem: mock(() => JSON.stringify([1, 2, 3])), + }; + (global as any).window = { localStorage: mockStorage }; + + expect(getRecentAppIds()).toEqual([1, 2, 3]); + expect(mockStorage.getItem).toHaveBeenCalledWith(RECENT_APP_STORAGE_KEY); + + (global as any).window = originalWindow; + }); + + test('getRecentAppIds should return empty array on invalid JSON', () => { + const mockStorage = { + getItem: mock(() => 'invalid json'), + }; + (global as any).window = { localStorage: mockStorage }; + + expect(getRecentAppIds()).toEqual([]); + + (global as any).window = originalWindow; + }); + + test('getRecentAppIds should return empty array when parsed value is not an array', () => { + const mockStorage = { + getItem: mock(() => JSON.stringify({ a: 1 })), + }; + (global as any).window = { localStorage: mockStorage }; + + expect(getRecentAppIds()).toEqual([]); + + (global as any).window = originalWindow; + }); + + test('getRecentAppIds should filter out non-integer values', () => { + const mockStorage = { + getItem: mock(() => JSON.stringify([1, '2', 3.5, 4])), + }; + (global as any).window = { localStorage: mockStorage }; + + expect(getRecentAppIds()).toEqual([1, 4]); + + (global as any).window = originalWindow; + }); + + test('rememberRecentApp should add appId to the front and limit count', () => { + let storage: Record = { + [RECENT_APP_STORAGE_KEY]: JSON.stringify([2, 1]), + }; + const mockStorage = { + getItem: mock((key: string) => storage[key] ?? null), + setItem: mock((key: string, value: string) => { + storage[key] = value; + }), + }; + (global as any).window = { + localStorage: mockStorage, + }; + + const result = rememberRecentApp(3); + expect(result).toEqual([3, 2, 1]); + expect(mockStorage.setItem).toHaveBeenCalledWith( + RECENT_APP_STORAGE_KEY, + JSON.stringify([3, 2, 1]), + ); + + // Test deduplication + const result2 = rememberRecentApp(2); + expect(result2).toEqual([2, 3, 1]); + + // Test limit + storage[RECENT_APP_STORAGE_KEY] = JSON.stringify([1, 2, 3, 4, 5, 6]); + const result3 = rememberRecentApp(7); + expect(result3.length).toBe(MAX_RECENT_APP_COUNT); + expect(result3).toEqual([7, 1, 2, 3, 4, 5]); + + (global as any).window = originalWindow; + }); + + test('rememberRecentApp should return empty array when window is undefined', () => { + (global as any).window = undefined; + expect(rememberRecentApp(1)).toEqual([]); + (global as any).window = originalWindow; + }); + + test('rememberRecentApp should return empty array when appId is not an integer', () => { + const mockStorage = { + getItem: mock(() => JSON.stringify([])), + setItem: mock(() => {}), + }; + (global as any).window = { localStorage: mockStorage }; + + expect(rememberRecentApp(1.5)).toEqual([]); + expect(mockStorage.setItem).not.toHaveBeenCalled(); + + (global as any).window = originalWindow; + }); +}); diff --git a/src/utils/helper.ts b/src/utils/helper.ts index df3f2f4..475bd34 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -90,8 +90,8 @@ export const patchSearchParams = ( }, navigateOptions); }; -const RECENT_APP_STORAGE_KEY = 'pushy_recent_app_ids'; -const MAX_RECENT_APP_COUNT = 6; +export const RECENT_APP_STORAGE_KEY = 'pushy_recent_app_ids'; +export const MAX_RECENT_APP_COUNT = 6; const MANAGE_APP_DRAWER_PLACEMENT_STORAGE_KEY = 'pushy_manage_app_drawer_placement'; const MANAGE_APP_DRAWER_COLLAPSED_STORAGE_KEY =