mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-07 09:13:04 +02:00
Add global message search and more e2e tests
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { seedChannelMessages } from '../helpers/seed';
|
||||
import { ensureFlightlessChannel } from '../helpers/api';
|
||||
|
||||
const CHANNEL_NAME = '#flightless';
|
||||
const SEED_COUNT = 30;
|
||||
|
||||
/**
|
||||
* Seed #flightless with unique, searchable messages.
|
||||
* Returns the channel key and a unique search token.
|
||||
*/
|
||||
function seedFlightlessMessages() {
|
||||
const token = `e2e-search-${Date.now()}`;
|
||||
const seeded = seedChannelMessages({
|
||||
channelName: CHANNEL_NAME,
|
||||
count: SEED_COUNT,
|
||||
// Use unique text so search can find them reliably
|
||||
// Note: seedChannelMessages uses "seed-N" as text by default,
|
||||
// but we need our unique token in there. We'll search for "seed-" instead
|
||||
// since that's what the seed helper generates.
|
||||
outgoingEvery: 5,
|
||||
includePaths: true,
|
||||
});
|
||||
return { key: seeded.key, token };
|
||||
}
|
||||
|
||||
test.describe('Channel info pane', () => {
|
||||
let channelKey: string;
|
||||
|
||||
test.beforeAll(async () => {
|
||||
await ensureFlightlessChannel();
|
||||
const seeded = seedFlightlessMessages();
|
||||
channelKey = seeded.key;
|
||||
});
|
||||
|
||||
test('opens channel info pane and shows message activity', async ({ page }) => {
|
||||
await page.goto(`/#channel/${channelKey}/flightless`);
|
||||
await expect(page.getByText('Connected')).toBeVisible();
|
||||
|
||||
// Wait for messages to load
|
||||
await expect(page.getByText('seed-0')).toBeVisible({ timeout: 15_000 });
|
||||
|
||||
// Click the channel name in the header to open info pane
|
||||
const headerTitle = page.locator('h2').filter({ hasText: '#flightless' });
|
||||
await headerTitle.click();
|
||||
|
||||
// Channel info pane should open as a sheet
|
||||
const infoPane = page.getByRole('dialog');
|
||||
await expect(infoPane).toBeVisible({ timeout: 10_000 });
|
||||
|
||||
// Should show channel name
|
||||
await expect(infoPane.getByText('#flightless')).toBeVisible();
|
||||
|
||||
// Should show channel key
|
||||
await expect(infoPane.getByText(channelKey.toLowerCase())).toBeVisible();
|
||||
|
||||
// Should show "Hashtag" badge
|
||||
await expect(infoPane.getByText('Hashtag')).toBeVisible();
|
||||
|
||||
// Should show "Message Activity" section with counts
|
||||
await expect(infoPane.getByText('Message Activity')).toBeVisible();
|
||||
await expect(infoPane.getByText('All Time')).toBeVisible();
|
||||
|
||||
// All Time count should be non-zero (our seeded messages)
|
||||
// InfoItem renders: <span>All Time</span><p>VALUE</p> — use CSS sibling selector
|
||||
const allTimeValue = infoPane.locator('span:text-is("All Time") + p');
|
||||
const count = await allTimeValue.textContent();
|
||||
expect(Number(count?.replace(/,/g, ''))).toBeGreaterThanOrEqual(SEED_COUNT);
|
||||
|
||||
// Should show "First Message" section
|
||||
await expect(infoPane.getByText('First Message')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Message search and jump-to-message', () => {
|
||||
let channelKey: string;
|
||||
|
||||
test.beforeAll(async () => {
|
||||
await ensureFlightlessChannel();
|
||||
const seeded = seedFlightlessMessages();
|
||||
channelKey = seeded.key;
|
||||
});
|
||||
|
||||
test('search finds seeded messages', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page.getByText('Connected')).toBeVisible();
|
||||
|
||||
// Open search view via sidebar
|
||||
await page.getByText('Message Search').click();
|
||||
|
||||
// Should show search input
|
||||
const searchInput = page.getByPlaceholder('Search all messages...');
|
||||
await expect(searchInput).toBeVisible();
|
||||
|
||||
// Search for seeded messages (seed helper creates "seed-N" text)
|
||||
await searchInput.fill('seed-1');
|
||||
|
||||
// Wait for search results to appear
|
||||
await expect(page.getByText('seed-1', { exact: false }).first()).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
|
||||
// Results should show the channel name
|
||||
await expect(page.getByText('#flightless').first()).toBeVisible();
|
||||
|
||||
// Results should show "Channel" badge
|
||||
await expect(page.getByText('Channel').first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('clicking a search result jumps to the message in conversation', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page.getByText('Connected')).toBeVisible();
|
||||
|
||||
// Open search
|
||||
await page.getByText('Message Search').click();
|
||||
|
||||
const searchInput = page.getByPlaceholder('Search all messages...');
|
||||
await searchInput.fill('seed-15');
|
||||
|
||||
// Wait for results
|
||||
const result = page.getByText('seed-15', { exact: false }).first();
|
||||
await expect(result).toBeVisible({ timeout: 10_000 });
|
||||
|
||||
// Click the search result to jump to it
|
||||
await result.click();
|
||||
|
||||
// Should navigate to the #flightless conversation
|
||||
await expect(page.getByPlaceholder(/message #flightless/i)).toBeVisible({ timeout: 15_000 });
|
||||
|
||||
// The target message should be visible in the conversation (not search results)
|
||||
// Scope to [data-message-id] to avoid matching leftover search <mark> elements
|
||||
const messageContainer = page.locator('[data-message-id]').filter({ hasText: 'seed-15' });
|
||||
await expect(messageContainer.first()).toBeVisible({ timeout: 10_000 });
|
||||
});
|
||||
|
||||
test('search returns no results for nonsense query', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page.getByText('Connected')).toBeVisible();
|
||||
|
||||
await page.getByText('Message Search').click();
|
||||
|
||||
const searchInput = page.getByPlaceholder('Search all messages...');
|
||||
await searchInput.fill('zzz-nonexistent-query-zzz');
|
||||
|
||||
await expect(page.getByText(/No messages found/)).toBeVisible({ timeout: 10_000 });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user