mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-03-28 17:43:05 +01:00
96 lines
3.1 KiB
TypeScript
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)}/`);
|
|
});
|
|
});
|