mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
192 lines
7.5 KiB
TypeScript
192 lines
7.5 KiB
TypeScript
import type { Page } from '@playwright/test'
|
|
|
|
import {
|
|
expect,
|
|
mockSollinhaChat,
|
|
test,
|
|
waitForRouterSettled,
|
|
} from './fixtures/campaignE2EFixtures.js'
|
|
|
|
const MESSAGE = 'Mensagem que migra entre as superficies'
|
|
|
|
const openDesktopChat = async (page: Page) => {
|
|
// B203 — fresh desktop sessions start closed; open explicitly via the header button.
|
|
await waitForRouterSettled(page)
|
|
await page
|
|
.getByRole('button', { name: 'Sollinha — Assistente virtual' })
|
|
.filter({ visible: true })
|
|
.click()
|
|
await expect(page.getByText('Olá! Eu sou o Sollinha')).toBeVisible({ timeout: 20_000 })
|
|
}
|
|
|
|
const openChatAndSend = async (page: Page) => {
|
|
await openDesktopChat(page)
|
|
// OPS42 — dev-only settle before interacting (see `waitForRouterSettled`).
|
|
await waitForRouterSettled(page)
|
|
const input = page.getByRole('textbox', { name: 'Pergunte para o Sollinha...' })
|
|
await input.fill(MESSAGE)
|
|
await input.press('Enter')
|
|
await expect(page.getByText(MESSAGE)).toBeVisible({ timeout: 20_000 })
|
|
}
|
|
|
|
/**
|
|
* Widths of the resizable panels in order: [main, chat]. Indexed defensively —
|
|
* under a cold dev compile only one panel may exist transiently; callers poll
|
|
* with `expect.poll` so a missing panel just means "keep waiting".
|
|
*/
|
|
const chatPanelWidth = (page: Page) =>
|
|
page.evaluate(() =>
|
|
[...document.querySelectorAll<HTMLElement>('[data-panel]')].map((panel) =>
|
|
Math.round(panel.getBoundingClientRect().width),
|
|
),
|
|
)
|
|
|
|
const chatPanelWidthAt = (page: Page, index: number) =>
|
|
chatPanelWidth(page).then((widths) => widths[index] ?? 0)
|
|
|
|
test.describe('B167 — chat Sollinha migra entre painel e drawer ao redimensionar', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
test.slow()
|
|
await mockSollinhaChat(page, 'Resposta mockada da Sollinha.')
|
|
await page.setViewportSize({ width: 1280, height: 800 })
|
|
})
|
|
|
|
test('desktop aberto -> mobile: drawer abre com a conversa e sem coluna fantasma', async ({
|
|
page,
|
|
campaign,
|
|
}) => {
|
|
const user = await campaign.fixtures.createCampaignUser('coordinator', {
|
|
name: campaign.fixtures.value('Chat Resize Coordenador'),
|
|
})
|
|
await campaign.login(page, user.email!, user.password)
|
|
await page.goto('/campanha')
|
|
|
|
await openChatAndSend(page)
|
|
|
|
await page.setViewportSize({ width: 500, height: 800 })
|
|
|
|
const drawer = page.getByRole('dialog', { name: 'Sollinha — Assistente virtual' })
|
|
await expect(drawer).toBeVisible({ timeout: 20_000 })
|
|
await expect(drawer.getByText(MESSAGE)).toBeVisible({ timeout: 20_000 })
|
|
// The drawer must STAY open past RRP's own re-layout on the crossing.
|
|
await expect(drawer).toBeVisible({ timeout: 20_000 })
|
|
|
|
// The chat Panel is hidden on mobile: no ghost column stealing space.
|
|
await expect
|
|
.poll(() => chatPanelWidthAt(page, 0))
|
|
.toBeGreaterThanOrEqual(Math.round(500 * 0.95))
|
|
})
|
|
|
|
test('mobile aberto -> desktop: painel abre com a conversa, sem reload', async ({
|
|
page,
|
|
campaign,
|
|
}) => {
|
|
const user = await campaign.fixtures.createCampaignUser('coordinator', {
|
|
name: campaign.fixtures.value('Chat Resize Coordenador'),
|
|
})
|
|
await campaign.login(page, user.email!, user.password)
|
|
await page.goto('/campanha')
|
|
|
|
await openChatAndSend(page)
|
|
|
|
await page.setViewportSize({ width: 500, height: 800 })
|
|
await expect(page.getByRole('dialog', { name: 'Sollinha — Assistente virtual' })).toBeVisible({
|
|
timeout: 20_000,
|
|
})
|
|
|
|
await page.setViewportSize({ width: 1280, height: 800 })
|
|
|
|
await expect(page.getByRole('dialog')).toHaveCount(0)
|
|
await expect(page.getByText(MESSAGE)).toBeVisible({ timeout: 20_000 })
|
|
// The welcome state must be gone — the conversation followed, not a fresh chat.
|
|
await expect(page.getByText('Olá! Eu sou o Sollinha')).not.toBeVisible()
|
|
// The panel is visibly expanded, not a 0-width sliver.
|
|
await expect.poll(() => chatPanelWidthAt(page, 1)).toBeGreaterThan(200)
|
|
})
|
|
|
|
test('chat fechado permanece fechado ao cruzar a borda nas duas direções', async ({
|
|
page,
|
|
campaign,
|
|
}) => {
|
|
const user = await campaign.fixtures.createCampaignUser('coordinator', {
|
|
name: campaign.fixtures.value('Chat Resize Coordenador'),
|
|
})
|
|
await campaign.login(page, user.email!, user.password)
|
|
await page.goto('/campanha')
|
|
|
|
// B203 — fresh desktop sessions start closed; no close click needed.
|
|
// OPS42 — dev-only settle before asserting (see `waitForRouterSettled`).
|
|
await waitForRouterSettled(page)
|
|
// Closing hides the desktop panel's footprint.
|
|
await expect.poll(() => chatPanelWidthAt(page, 1)).toBeLessThan(2)
|
|
|
|
await page.setViewportSize({ width: 500, height: 800 })
|
|
await expect(page.getByRole('dialog')).toHaveCount(0)
|
|
|
|
await page.setViewportSize({ width: 1280, height: 800 })
|
|
await expect(page.getByRole('dialog')).toHaveCount(0)
|
|
// Still closed on desktop: no conversation surface, panel still hidden.
|
|
await expect.poll(() => chatPanelWidthAt(page, 1)).toBeLessThan(2)
|
|
})
|
|
|
|
test('visita mobile nova começa com o chat fechado (FAB é o convite)', async ({
|
|
page,
|
|
campaign,
|
|
}) => {
|
|
const user = await campaign.fixtures.createCampaignUser('coordinator', {
|
|
name: campaign.fixtures.value('Chat Resize Coordenador'),
|
|
})
|
|
// Mobile from the start (B188): B203 starts every fresh session closed,
|
|
// so no `open: true` is ever persisted here — no drawer, only the FAB.
|
|
await page.setViewportSize({ width: 500, height: 800 })
|
|
await campaign.login(page, user.email!, user.password)
|
|
|
|
// Carga direto em mobile: sem drawer espontâneo, só o FAB.
|
|
await page.goto('/campanha')
|
|
await expect(page.getByRole('dialog', { name: 'Sollinha — Assistente virtual' })).toHaveCount(0)
|
|
await expect(page.getByRole('button', { name: 'Sollinha — Assistente virtual' })).toBeVisible({
|
|
timeout: 20_000,
|
|
})
|
|
|
|
// Crescer para desktop continua fechado (o painel não “renasce”).
|
|
await page.setViewportSize({ width: 1280, height: 800 })
|
|
await expect(page.getByRole('dialog')).toHaveCount(0)
|
|
await expect.poll(() => chatPanelWidthAt(page, 1)).toBeLessThan(2)
|
|
})
|
|
|
|
test('conversa sobrevive à navegação interna de /campanha', async ({ page, campaign }) => {
|
|
const user = await campaign.fixtures.createCampaignUser('coordinator', {
|
|
name: campaign.fixtures.value('Chat Resize Coordenador'),
|
|
})
|
|
await campaign.login(page, user.email!, user.password)
|
|
await page.goto('/campanha')
|
|
|
|
await openChatAndSend(page)
|
|
|
|
await page.getByRole('link', { name: 'Municípios' }).click()
|
|
await expect(page).toHaveURL(/\/campanha\/municipios/)
|
|
|
|
await expect(page.getByText(MESSAGE)).toBeVisible({ timeout: 20_000 })
|
|
await expect(page.getByText('Olá! Eu sou o Sollinha')).not.toBeVisible()
|
|
})
|
|
|
|
test('nova aba recomeça a conversa vazia', async ({ page, context, campaign }) => {
|
|
const user = await campaign.fixtures.createCampaignUser('coordinator', {
|
|
name: campaign.fixtures.value('Chat Resize Coordenador'),
|
|
})
|
|
await campaign.login(page, user.email!, user.password)
|
|
await page.goto('/campanha')
|
|
|
|
await openChatAndSend(page)
|
|
|
|
const secondTab = await context.newPage()
|
|
await secondTab.setViewportSize({ width: 1280, height: 800 })
|
|
await secondTab.goto('/campanha')
|
|
|
|
// B203 — the new tab is a fresh session, so it starts closed; open it
|
|
// explicitly before asserting the empty greeting state.
|
|
await openDesktopChat(secondTab)
|
|
await expect(secondTab.getByText(MESSAGE)).toHaveCount(0)
|
|
await secondTab.close()
|
|
})
|
|
})
|