From 9fd506695d005a073ccfae771dc6cc45596e392d Mon Sep 17 00:00:00 2001 From: Nuwan Date: Tue, 27 Jan 2026 14:20:52 +0530 Subject: [PATCH] test(08-03): add integration tests for chat button - Test button visibility in session navigation - Test badge hidden when unread count = 0 - Test badge shows correct count (1-99) - Test badge shows "99+" for counts >= 100 - Test button opens chat window - Test duplicate window prevention - Test badge resets when window opens - 7 comprehensive test cases --- jam-ui/test/chat/chat-button.spec.ts | 138 +++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 jam-ui/test/chat/chat-button.spec.ts diff --git a/jam-ui/test/chat/chat-button.spec.ts b/jam-ui/test/chat/chat-button.spec.ts new file mode 100644 index 000000000..cfbed9121 --- /dev/null +++ b/jam-ui/test/chat/chat-button.spec.ts @@ -0,0 +1,138 @@ +import { test, expect } from '@playwright/test'; +import { loginToJamUI, createAndJoinSession } from '../utils/test-helpers'; + +test.describe('Chat Button', () => { + test.beforeEach(async ({ page }) => { + await loginToJamUI(page); + await createAndJoinSession(page); + }); + + test('shows chat button in session screen navigation', async ({ page }) => { + // Verify chat button is visible + const chatButton = page.locator('img[alt="Chat"]'); + await expect(chatButton).toBeVisible(); + }); + + test('hides badge when unread count is 0', async ({ page }) => { + // Ensure unread count is 0 in Redux state + const unreadCounts = await page.evaluate(() => { + const store = (window as any).__REDUX_STORE__; + const state = store.getState().sessionChat; + return state.unreadCounts; + }); + expect(unreadCounts).toEqual({}); + + // Badge should not be visible (look for any div with numeric text near chat button) + const chatButton = page.locator('img[alt="Chat"]'); + const parent = chatButton.locator('..'); + const badge = parent.locator('div').filter({ hasText: /^\d+$|^99\+$/ }); + await expect(badge).not.toBeVisible(); + }); + + test('shows badge with correct count when messages arrive', async ({ page }) => { + // Simulate receiving a message (increment unread count via Redux) + await page.evaluate(() => { + const store = (window as any).__REDUX_STORE__; + store.dispatch({ + type: 'sessionChat/incrementUnreadCount', + payload: { channel: 'test-session-id' } + }); + }); + + // Badge should be visible with "1" + const chatButton = page.locator('img[alt="Chat"]'); + const parent = chatButton.locator('..'); + const badge = parent.locator('div:has-text("1")'); + await expect(badge).toBeVisible(); + }); + + test('shows "99+" for counts >= 100', async ({ page }) => { + // Set unread count to 150 + await page.evaluate(() => { + const store = (window as any).__REDUX_STORE__; + for (let i = 0; i < 150; i++) { + store.dispatch({ + type: 'sessionChat/incrementUnreadCount', + payload: { channel: 'test-session-id' } + }); + } + }); + + // Badge should show "99+" + const chatButton = page.locator('img[alt="Chat"]'); + const parent = chatButton.locator('..'); + const badge = parent.locator('div:has-text("99+")'); + await expect(badge).toBeVisible(); + }); + + test('opens chat window when button clicked', async ({ page, context }) => { + // Click chat button + const chatButton = page.locator('img[alt="Chat"]'); + await chatButton.click(); + + // Wait for popup window + const popupPromise = context.waitForEvent('page', { timeout: 5000 }); + const popup = await popupPromise; + + // Verify popup opened + expect(popup).toBeTruthy(); + await expect(popup).toHaveTitle('JamKazam Chat'); + + // Verify Redux state updated + const isWindowOpen = await page.evaluate(() => { + const store = (window as any).__REDUX_STORE__; + return store.getState().sessionChat.isWindowOpen; + }); + expect(isWindowOpen).toBe(true); + }); + + test('does not open duplicate window when button clicked again', async ({ page, context }) => { + // Click chat button + const chatButton = page.locator('img[alt="Chat"]'); + await chatButton.click(); + + // Wait for popup + const popupPromise = context.waitForEvent('page'); + const popup = await popupPromise; + expect(popup).toBeTruthy(); + + // Click button again + await chatButton.click(); + + // No new popup should open (timeout after 2 seconds) + await expect(async () => { + await context.waitForEvent('page', { timeout: 2000 }); + }).rejects.toThrow(); + }); + + test('resets badge count when chat window opened', async ({ page, context }) => { + // Add unread messages + await page.evaluate(() => { + const store = (window as any).__REDUX_STORE__; + for (let i = 0; i < 5; i++) { + store.dispatch({ + type: 'sessionChat/incrementUnreadCount', + payload: { channel: 'test-session-id' } + }); + } + }); + + // Verify badge shows "5" + const chatButton = page.locator('img[alt="Chat"]'); + const parent = chatButton.locator('..'); + let badge = parent.locator('div:has-text("5")'); + await expect(badge).toBeVisible(); + + // Open chat window + await chatButton.click(); + const popupPromise = context.waitForEvent('page'); + await popupPromise; + + // Wait for Redux state to update + await page.waitForTimeout(500); + + // Badge should be hidden (count reset to 0) + badge = parent.locator('div:has-text("5")'); + await expect(badge).not.toBeVisible(); + }); +});