Files
Remote-Terminal-for-MeshCore/tests/e2e/specs/hash-routing.spec.ts

96 lines
3.1 KiB
TypeScript

import { test, expect } from '@playwright/test';
import { randomBytes } from 'crypto';
import { createChannel, createContact, deleteChannel, deleteContact } from '../helpers/api';
function randomHex(bytes: number): string {
return randomBytes(bytes).toString('hex');
}
function makeKeyWithPrefix(prefix: string): string {
return `${prefix}${randomHex(26)}`;
}
function escapeRegex(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
test.describe('Hash routing and conversation identity', () => {
let channelName = '';
let channelKey = '';
let contactAKey = '';
let contactAName = '';
let contactBKey = '';
let contactBName = '';
test.beforeAll(async () => {
channelName = `#e2ehash${Date.now().toString().slice(-6)}`;
const createdChannel = await createChannel(channelName);
channelKey = createdChannel.key;
const sharedPrefix = randomHex(6);
contactAKey = makeKeyWithPrefix(sharedPrefix);
contactBKey = makeKeyWithPrefix(sharedPrefix);
contactAName = `E2E Hash A ${Date.now().toString().slice(-5)}`;
contactBName = `E2E Hash B ${Date.now().toString().slice(-5)}`;
await createContact(contactAKey, contactAName);
await createContact(contactBKey, contactBName);
});
test.afterAll(async () => {
try {
await deleteChannel(channelKey);
} catch {
// Best-effort cleanup
}
try {
await deleteContact(contactAKey);
} catch {
// Best-effort cleanup
}
try {
await deleteContact(contactBKey);
} catch {
// Best-effort cleanup
}
});
test('legacy channel-name hash resolves and rewrites to stable channel-key hash', async ({
page,
}) => {
const legacyToken = channelName.slice(1); // no leading '#'
await page.goto(`/#channel/${encodeURIComponent(legacyToken)}`);
await expect(page.getByText('Connected')).toBeVisible();
await expect(
page.getByPlaceholder(new RegExp(`message\\s+${escapeRegex(channelName)}`, 'i'))
).toBeVisible();
await expect.poll(() => page.url()).toContain(`#channel/${encodeURIComponent(channelKey)}/`);
});
test('full-key contact hash selects the exact contact even with shared prefixes', async ({ page }) => {
await page.goto(`/#contact/${contactBKey}`);
await expect(page.getByText('Connected')).toBeVisible();
await expect(
page.getByPlaceholder(new RegExp(`message\\s+${escapeRegex(contactBName)}`, 'i'))
).toBeVisible();
await expect(page.getByText(contactBKey, { exact: true })).toBeVisible();
await expect.poll(() => page.url()).toContain(`#contact/${encodeURIComponent(contactBKey)}/`);
});
test('legacy contact-name hash resolves and rewrites to stable full-key hash', async ({ page }) => {
await page.goto(`/#contact/${encodeURIComponent(contactAName)}`);
await expect(page.getByText('Connected')).toBeVisible();
await expect(
page.getByPlaceholder(new RegExp(`message\\s+${escapeRegex(contactAName)}`, 'i'))
).toBeVisible();
await expect(page.getByText(contactAKey, { exact: true })).toBeVisible();
await expect.poll(() => page.url()).toContain(`#contact/${encodeURIComponent(contactAKey)}/`);
});
});