diff --git a/static/js/managers/BannerService.js b/static/js/managers/BannerService.js index ce8022b7..f4461fdc 100644 --- a/static/js/managers/BannerService.js +++ b/static/js/managers/BannerService.js @@ -348,6 +348,13 @@ class BannerService { return; } + // Check if banner with this ID already exists in recent history + // Only record if it's not already in history (prevents duplicates on page refresh) + const existingEntry = this.recentHistory.find(entry => entry.id === banner.id); + if (existingEntry) { + return; // Banner already exists in history, don't add again + } + const sanitizedActions = Array.isArray(banner.actions) ? banner.actions.map(action => ({ text: action.text, diff --git a/tests/frontend/managers/BannerService.test.js b/tests/frontend/managers/BannerService.test.js index 94956dad..078f061e 100644 --- a/tests/frontend/managers/BannerService.test.js +++ b/tests/frontend/managers/BannerService.test.js @@ -35,6 +35,7 @@ describe('BannerService', () => { // Reset banner service state bannerService.banners.clear(); bannerService.initialized = false; + bannerService.recentHistory = []; // Clear history for each test // Clear DOM document.body.innerHTML = ''; @@ -216,4 +217,81 @@ describe('BannerService', () => { expect(storageHelpers.setStorageItem).not.toHaveBeenCalled(); }); }); + + describe('Banner History', () => { + const testBanner = { + id: 'test-banner', + title: 'Test Banner', + content: 'This is a test banner', + actions: [ + { + text: 'Action 1', + icon: 'fas fa-check', + url: 'https://example.com', + type: 'primary' + } + ] + }; + + it('should add banner to history when first recorded', () => { + // Mock storage to return empty array + storageHelpers.getStorageItem.mockImplementation((key, defaultValue) => { + if (key === 'banner_history') { + return []; + } + return defaultValue; + }); + + // Record the banner appearance + bannerService.recordBannerAppearance(testBanner); + + // Should have added the banner to history + expect(bannerService.recentHistory).toHaveLength(1); + expect(bannerService.recentHistory[0].id).toBe('test-banner'); + expect(bannerService.recentHistory[0].title).toBe('Test Banner'); + }); + + it('should not add duplicate banner to history when recorded multiple times', () => { + // Mock storage to return empty array + storageHelpers.getStorageItem.mockImplementation((key, defaultValue) => { + if (key === 'banner_history') { + return []; + } + return defaultValue; + }); + + // Record the same banner twice + bannerService.recordBannerAppearance(testBanner); + bannerService.recordBannerAppearance(testBanner); + + // Should only have one entry in history + expect(bannerService.recentHistory).toHaveLength(1); + expect(bannerService.recentHistory[0].id).toBe('test-banner'); + }); + + it('should add different banners to history', () => { + // Mock storage to return empty array + storageHelpers.getStorageItem.mockImplementation((key, defaultValue) => { + if (key === 'banner_history') { + return []; + } + return defaultValue; + }); + + const anotherBanner = { + id: 'another-banner', + title: 'Another Banner', + content: 'This is another test banner' + }; + + // Record two different banners + bannerService.recordBannerAppearance(testBanner); + bannerService.recordBannerAppearance(anotherBanner); + + // Should have two entries in history + expect(bannerService.recentHistory).toHaveLength(2); + expect(bannerService.recentHistory[0].id).toBe('another-banner'); + expect(bannerService.recentHistory[1].id).toBe('test-banner'); + }); + }); }); \ No newline at end of file