67 lines
2.6 KiB
TypeScript
67 lines
2.6 KiB
TypeScript
|
|
import type { Page } from '@playwright/test';
|
||
|
|
import { expect } from '@playwright/test';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Navigate to a chat conversation ready for message input.
|
||
|
|
*
|
||
|
|
* Minimal signature by design — a helper that starts growing options
|
||
|
|
* becomes a second API surface. If a test needs a specific conversation
|
||
|
|
* id, a specific room type, or pre-seeded messages, that test should
|
||
|
|
* fetch via the API + set store state directly rather than extending
|
||
|
|
* this helper. Keep it boring.
|
||
|
|
*
|
||
|
|
* Flow:
|
||
|
|
* 1. /chat must already be loaded and the sidebar rendered.
|
||
|
|
* 2. If at least one conversation row exists: click the first one.
|
||
|
|
* 3. Otherwise: click "New Channel", create a disposable room.
|
||
|
|
* 4. Wait for the message input to become enabled — that's the
|
||
|
|
* observable signal that `currentConversationId` is set in the
|
||
|
|
* chat store (ChatInput.tsx disables on `!currentConversationId`).
|
||
|
|
*
|
||
|
|
* Returns the conversation id chosen (via data-conversation-id attr)
|
||
|
|
* when an existing one is selected, or null when a new one was
|
||
|
|
* created (the id is assigned by the backend after dialog submit).
|
||
|
|
*
|
||
|
|
* Target selectors use testids added in v1.0.7-rc1-day2:
|
||
|
|
* - chat-conversation-item (on ConversationItem button)
|
||
|
|
* - chat-new-channel-cta (on the "New Channel" footer button)
|
||
|
|
* The pre-rc1 tests used `button[type="button"]` which ambiguously
|
||
|
|
* matched the "New Channel" CTA itself, producing the 22-failure
|
||
|
|
* cascade.
|
||
|
|
*/
|
||
|
|
export async function navigateToConversation(
|
||
|
|
page: Page,
|
||
|
|
): Promise<string | null> {
|
||
|
|
const existing = page.getByTestId('chat-conversation-item').first();
|
||
|
|
const existingCount = await page.getByTestId('chat-conversation-item').count();
|
||
|
|
|
||
|
|
if (existingCount > 0) {
|
||
|
|
const id = await existing.getAttribute('data-conversation-id');
|
||
|
|
await existing.click();
|
||
|
|
await expectInputReady(page);
|
||
|
|
return id;
|
||
|
|
}
|
||
|
|
|
||
|
|
// No conversation exists — create a disposable one. Room name is
|
||
|
|
// timestamped to avoid collisions across concurrent test workers.
|
||
|
|
const roomName = `e2e-helper-${Date.now()}`;
|
||
|
|
await page.getByTestId('chat-new-channel-cta').click();
|
||
|
|
|
||
|
|
const nameInput = page.locator('#room-name');
|
||
|
|
await expect(nameInput).toBeVisible({ timeout: 5_000 });
|
||
|
|
await nameInput.fill(roomName);
|
||
|
|
|
||
|
|
await page.getByRole('button', { name: /^create room$/i }).click();
|
||
|
|
|
||
|
|
// Dialog closes, new conversation becomes current.
|
||
|
|
await expect(nameInput).toBeHidden({ timeout: 5_000 });
|
||
|
|
await expectInputReady(page);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
async function expectInputReady(page: Page): Promise<void> {
|
||
|
|
const input = page.getByLabel('Type a message');
|
||
|
|
await expect(input).toBeVisible({ timeout: 8_000 });
|
||
|
|
await expect(input).toBeEnabled({ timeout: 8_000 });
|
||
|
|
}
|