mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-07-06 01:42:11 +02:00
Make a better integration/fanout selector
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
import type { Locator, Page } from '@playwright/test';
|
||||
import http from 'http';
|
||||
|
||||
function escapeRegex(text: string): string {
|
||||
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
export function createCaptureServer(urlFactory: (port: number) => string) {
|
||||
const requests: { body: string; headers: http.IncomingHttpHeaders }[] = [];
|
||||
const server = http.createServer((req, res) => {
|
||||
@@ -38,6 +42,15 @@ export async function openFanoutSettings(page: Page): Promise<void> {
|
||||
await page.getByRole('button', { name: /MQTT.*Automation/ }).click();
|
||||
}
|
||||
|
||||
export async function startIntegrationDraft(page: Page, integrationName: string): Promise<void> {
|
||||
await page.getByRole('button', { name: 'Add Integration' }).click();
|
||||
const dialog = page.getByRole('dialog', { name: 'Create Integration' });
|
||||
await dialog
|
||||
.getByRole('button', { name: new RegExp(`^${escapeRegex(integrationName)}(?:\\s|$)`) })
|
||||
.click();
|
||||
await dialog.getByRole('button', { name: 'Create' }).click();
|
||||
}
|
||||
|
||||
export function fanoutHeader(page: Page, name: string): Locator {
|
||||
const nameButton = page.getByRole('button', { name, exact: true });
|
||||
return page
|
||||
|
||||
@@ -4,7 +4,12 @@ import {
|
||||
deleteFanoutConfig,
|
||||
getFanoutConfigs,
|
||||
} from '../helpers/api';
|
||||
import { createCaptureServer, fanoutHeader, openFanoutSettings } from '../helpers/fanout';
|
||||
import {
|
||||
createCaptureServer,
|
||||
fanoutHeader,
|
||||
openFanoutSettings,
|
||||
startIntegrationDraft,
|
||||
} from '../helpers/fanout';
|
||||
|
||||
test.describe('Apprise integration settings', () => {
|
||||
let createdAppriseId: string | null = null;
|
||||
@@ -35,9 +40,7 @@ test.describe('Apprise integration settings', () => {
|
||||
await openFanoutSettings(page);
|
||||
await expect(page.getByRole('status', { name: 'Radio OK' })).toBeVisible();
|
||||
|
||||
// Open add menu and pick Apprise
|
||||
await page.getByRole('button', { name: 'Add Integration' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Apprise' }).click();
|
||||
await startIntegrationDraft(page, 'Apprise');
|
||||
|
||||
// Should navigate to the detail/edit view with a numbered default name
|
||||
await expect(page.locator('#fanout-edit-name')).toHaveValue(/Apprise #\d+/);
|
||||
|
||||
+22
-20
@@ -1,9 +1,10 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import {
|
||||
ensureFlightlessChannel,
|
||||
createFanoutConfig,
|
||||
deleteFanoutConfig,
|
||||
getFanoutConfigs,
|
||||
} from '../helpers/api';
|
||||
import { openFanoutSettings, startIntegrationDraft } from '../helpers/fanout';
|
||||
|
||||
const BOT_CODE = `def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path):
|
||||
if channel_name == "#flightless" and "!e2etest" in message_text.lower():
|
||||
@@ -28,32 +29,35 @@ test.describe('Bot functionality', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('create a bot via API, verify it in UI, trigger it, and verify response', async ({
|
||||
test('create a bot via UI, trigger it, and verify response', async ({
|
||||
page,
|
||||
}) => {
|
||||
// --- Step 1: Create and enable bot via fanout API ---
|
||||
const bot = await createFanoutConfig({
|
||||
type: 'bot',
|
||||
name: 'E2E Test Bot',
|
||||
config: { code: BOT_CODE },
|
||||
enabled: true,
|
||||
});
|
||||
createdBotId = bot.id;
|
||||
|
||||
// --- Step 2: Verify bot appears in settings UI ---
|
||||
await page.goto('/');
|
||||
await openFanoutSettings(page);
|
||||
await expect(page.getByRole('status', { name: 'Radio OK' })).toBeVisible();
|
||||
|
||||
await page.getByText('Settings').click();
|
||||
await page.getByRole('button', { name: /MQTT.*Automation/ }).click();
|
||||
await startIntegrationDraft(page, 'Python Bot');
|
||||
await expect(page.locator('#fanout-edit-name')).toHaveValue(/Python Bot #\d+/);
|
||||
|
||||
await page.locator('#fanout-edit-name').fill('E2E Test Bot');
|
||||
|
||||
const codeEditor = page.getByLabel('Bot code editor');
|
||||
await codeEditor.click();
|
||||
await codeEditor.press(process.platform === 'darwin' ? 'Meta+A' : 'Control+A');
|
||||
await codeEditor.fill(BOT_CODE);
|
||||
|
||||
await page.getByRole('button', { name: /Save as Enabled/i }).click();
|
||||
await expect(page.getByText('Integration saved and enabled')).toBeVisible();
|
||||
|
||||
// The bot name should be visible in the integration list
|
||||
await expect(page.getByText('E2E Test Bot')).toBeVisible();
|
||||
|
||||
// Exit settings page mode
|
||||
const configs = await getFanoutConfigs();
|
||||
const createdBot = configs.find((config) => config.name === 'E2E Test Bot');
|
||||
if (createdBot) {
|
||||
createdBotId = createdBot.id;
|
||||
}
|
||||
|
||||
await page.getByRole('button', { name: /Back to Chat/i }).click();
|
||||
|
||||
// --- Step 3: Trigger the bot ---
|
||||
await page.getByText('#flightless', { exact: true }).first().click();
|
||||
|
||||
const triggerMessage = `!e2etest ${Date.now()}`;
|
||||
@@ -61,8 +65,6 @@ test.describe('Bot functionality', () => {
|
||||
await input.fill(triggerMessage);
|
||||
await page.getByRole('button', { name: 'Send', exact: true }).click();
|
||||
|
||||
// --- Step 4: Verify bot response appears ---
|
||||
// Bot has ~2s delay before responding, plus radio send time
|
||||
await expect(page.getByText('[BOT] e2e-ok')).toBeVisible({ timeout: 30_000 });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,12 @@ import {
|
||||
deleteFanoutConfig,
|
||||
getFanoutConfigs,
|
||||
} from '../helpers/api';
|
||||
import { createCaptureServer, fanoutHeader, openFanoutSettings } from '../helpers/fanout';
|
||||
import {
|
||||
createCaptureServer,
|
||||
fanoutHeader,
|
||||
openFanoutSettings,
|
||||
startIntegrationDraft,
|
||||
} from '../helpers/fanout';
|
||||
|
||||
test.describe('Webhook integration settings', () => {
|
||||
let createdWebhookId: string | null = null;
|
||||
@@ -35,9 +40,7 @@ test.describe('Webhook integration settings', () => {
|
||||
await openFanoutSettings(page);
|
||||
await expect(page.getByRole('status', { name: 'Radio OK' })).toBeVisible();
|
||||
|
||||
// Open add menu and pick Webhook
|
||||
await page.getByRole('button', { name: 'Add Integration' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Webhook' }).click();
|
||||
await startIntegrationDraft(page, 'Webhook');
|
||||
|
||||
// Should navigate to the detail/edit view with a numbered default name
|
||||
await expect(page.locator('#fanout-edit-name')).toHaveValue(/Webhook #\d+/);
|
||||
@@ -77,8 +80,7 @@ test.describe('Webhook integration settings', () => {
|
||||
await openFanoutSettings(page);
|
||||
await expect(page.getByRole('status', { name: 'Radio OK' })).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Add Integration' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Webhook' }).click();
|
||||
await startIntegrationDraft(page, 'Webhook');
|
||||
await expect(page.locator('#fanout-edit-name')).toHaveValue(/Webhook #\d+/);
|
||||
|
||||
await page.locator('#fanout-edit-name').fill('Unsaved Webhook Draft');
|
||||
|
||||
Reference in New Issue
Block a user