feat: publish av-tools 0.1.0
This commit is contained in:
256
tests/browser/application.spec.ts
Normal file
256
tests/browser/application.spec.ts
Normal file
@@ -0,0 +1,256 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
import {
|
||||
observeRuntime,
|
||||
startNestedStaticServer,
|
||||
type NestedStaticServer,
|
||||
} from './browser-helpers';
|
||||
|
||||
test.describe('static application and Toolbox shell', () => {
|
||||
test('runs standalone, stays lazy and supports keyboard-operated shell controls', async ({
|
||||
page,
|
||||
}) => {
|
||||
const runtime = observeRuntime(page);
|
||||
|
||||
await page.goto('/');
|
||||
|
||||
await expect(page).toHaveTitle('Audio & Video Tools');
|
||||
await expect(
|
||||
page.getByRole('heading', {
|
||||
level: 1,
|
||||
name: 'Audio & Video Tools',
|
||||
})
|
||||
).toBeVisible();
|
||||
await expect(page.locator('[data-toolbox-context]')).toHaveAttribute(
|
||||
'data-toolbox-context',
|
||||
'standalone'
|
||||
);
|
||||
await expect(page.getByRole('main')).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole('tab', { name: 'Quick Convert' })
|
||||
).toHaveAttribute('aria-selected', 'true');
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Choose files' })
|
||||
).toBeEnabled();
|
||||
|
||||
expect(
|
||||
runtime.requests.some((url) => url.includes('/vendor/ffmpeg/'))
|
||||
).toBe(false);
|
||||
expect(
|
||||
runtime.requests.some((url) => /\/assets\/worker-[^/]+\.js$/u.test(url))
|
||||
).toBe(false);
|
||||
|
||||
const helpButton = page.getByRole('button', { name: 'Help' });
|
||||
await helpButton.focus();
|
||||
await page.keyboard.press('Enter');
|
||||
const helpDialog = page.getByRole('dialog', {
|
||||
name: 'Audio & Video Tools',
|
||||
});
|
||||
await expect(helpDialog).toBeVisible();
|
||||
await expect(
|
||||
helpDialog.getByRole('heading', {
|
||||
level: 2,
|
||||
name: 'Audio & Video Tools',
|
||||
})
|
||||
).toBeVisible();
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(helpDialog).toBeHidden();
|
||||
|
||||
const personalizeButton = page.getByRole('button', {
|
||||
name: 'Personalize',
|
||||
});
|
||||
await personalizeButton.focus();
|
||||
await page.keyboard.press('Enter');
|
||||
await expect(
|
||||
page.getByRole('heading', {
|
||||
level: 2,
|
||||
name: 'Personalize your toolbox',
|
||||
})
|
||||
).toBeVisible();
|
||||
await page.getByRole('button', { name: 'Dark' }).click();
|
||||
await expect(page.locator('.toolbox-shell').first()).toHaveAttribute(
|
||||
'data-toolbox-theme',
|
||||
'dark'
|
||||
);
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(personalizeButton).toBeFocused();
|
||||
|
||||
const networkUrls = runtime.requests.filter((url) => /^https?:/u.test(url));
|
||||
expect(
|
||||
networkUrls.every(
|
||||
(url) => new URL(url).origin === 'http://127.0.0.1:4173'
|
||||
)
|
||||
).toBe(true);
|
||||
expect(runtime.failedRequests).toEqual([]);
|
||||
expect(runtime.pageErrors).toEqual([]);
|
||||
expect(runtime.consoleErrors).toEqual([]);
|
||||
});
|
||||
|
||||
test('keeps preview primary and exposes accessible Edit drawers on narrow screens', async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.setViewportSize({ width: 390, height: 844 });
|
||||
await page.goto('/');
|
||||
await page.getByRole('tab', { name: 'Edit' }).click();
|
||||
|
||||
await expect(page.getByRole('heading', { name: 'Preview' })).toBeVisible();
|
||||
const mediaDrawer = page.locator('#edit-media-drawer');
|
||||
const inspectorDrawer = page.locator('#edit-inspector-drawer');
|
||||
await expect(mediaDrawer).toBeHidden();
|
||||
await expect(inspectorDrawer).toBeHidden();
|
||||
|
||||
const sources = page.getByRole('button', { name: 'Sources' });
|
||||
await sources.click();
|
||||
await expect(mediaDrawer).toBeVisible();
|
||||
await expect(
|
||||
mediaDrawer.getByRole('button', { name: 'Close media bin' })
|
||||
).toBeFocused();
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(mediaDrawer).toBeHidden();
|
||||
await expect(sources).toBeFocused();
|
||||
|
||||
const inspector = page.getByRole('button', { name: 'Inspector' });
|
||||
await inspector.click();
|
||||
await expect(inspectorDrawer).toBeVisible();
|
||||
const closeInspector = inspectorDrawer.getByRole('button', {
|
||||
name: 'Close inspector',
|
||||
});
|
||||
await expect(closeInspector).toBeFocused();
|
||||
await closeInspector.click();
|
||||
await expect(inspectorDrawer).toBeHidden();
|
||||
await expect(inspector).toBeFocused();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('nested static deployment and Toolbox context', () => {
|
||||
let nestedServer: NestedStaticServer;
|
||||
|
||||
test.beforeAll(async () => {
|
||||
nestedServer = await startNestedStaticServer();
|
||||
});
|
||||
|
||||
test.afterAll(async () => {
|
||||
await nestedServer.close();
|
||||
});
|
||||
|
||||
test('loads a valid same-origin catalog and all runtime assets below the nested path', async ({
|
||||
page,
|
||||
}) => {
|
||||
const runtime = observeRuntime(page);
|
||||
await page.goto(`${nestedServer.appUrl}?toolbox=../toolbox.catalog.json`);
|
||||
|
||||
await expect(page.locator('[data-toolbox-context]')).toHaveAttribute(
|
||||
'data-toolbox-context',
|
||||
'connected'
|
||||
);
|
||||
await expect(
|
||||
page.getByRole('link', { name: 'add·ideas Toolbox' })
|
||||
).toHaveAttribute('href', `${nestedServer.origin}/deep/nested/`);
|
||||
|
||||
await page.getByRole('button', { name: 'Apps' }).click();
|
||||
const appSwitcher = page.getByRole('navigation', {
|
||||
name: 'Toolbox applications',
|
||||
});
|
||||
await expect(
|
||||
appSwitcher.getByRole('link', { name: 'Browser Test Tool' })
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
appSwitcher.getByRole('link', { name: 'Audio & Video Tools' })
|
||||
).toBeVisible();
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
expect(
|
||||
runtime.requests.some((url) =>
|
||||
/\/deep\/nested\/av\/assets\/index-[^/]+\.js$/u.test(url)
|
||||
)
|
||||
).toBe(true);
|
||||
expect(
|
||||
runtime.requests.some((url) =>
|
||||
/\/deep\/nested\/av\/assets\/index-[^/]+\.css$/u.test(url)
|
||||
)
|
||||
).toBe(true);
|
||||
expect(
|
||||
runtime.requests.some((url) => url.includes('/vendor/ffmpeg/'))
|
||||
).toBe(false);
|
||||
|
||||
await page.getByText('Engine & browser').click();
|
||||
await page.getByLabel('Engine mode').selectOption('force-single-thread');
|
||||
await page.getByRole('button', { name: 'Initialize engine' }).click();
|
||||
|
||||
await expect(
|
||||
page
|
||||
.locator('.engine-pill')
|
||||
.filter({ hasText: 'Single-threaded compatibility mode' })
|
||||
).toBeVisible({ timeout: 120_000 });
|
||||
await expect(page.getByText('0.12.15 / 0.12.10')).toBeVisible();
|
||||
await expect(
|
||||
page.getByText('Encoders').locator('..').locator('dd')
|
||||
).not.toHaveText('0');
|
||||
await expect(
|
||||
page.getByText('Filters').locator('..').locator('dd')
|
||||
).not.toHaveText('0');
|
||||
|
||||
const coreScript = runtime.responses.find((response) =>
|
||||
response.url.endsWith(
|
||||
'/deep/nested/av/vendor/ffmpeg/0.12.10/st/ffmpeg-core.js'
|
||||
)
|
||||
);
|
||||
const coreWasm = runtime.responses.find((response) =>
|
||||
response.url.endsWith(
|
||||
'/deep/nested/av/vendor/ffmpeg/0.12.10/st/ffmpeg-core.wasm'
|
||||
)
|
||||
);
|
||||
expect(coreScript).toMatchObject({
|
||||
status: 200,
|
||||
contentType: 'text/javascript; charset=utf-8',
|
||||
});
|
||||
expect(coreWasm).toMatchObject({
|
||||
status: 200,
|
||||
contentType: 'application/wasm',
|
||||
});
|
||||
expect(
|
||||
runtime.responses.some((response) =>
|
||||
/\/deep\/nested\/av\/assets\/worker-[^/]+\.js$/u.test(response.url)
|
||||
)
|
||||
).toBe(true);
|
||||
|
||||
const networkUrls = runtime.requests.filter((url) => /^https?:/u.test(url));
|
||||
expect(
|
||||
networkUrls.every((url) => new URL(url).origin === nestedServer.origin)
|
||||
).toBe(true);
|
||||
expect(runtime.failedRequests).toEqual([]);
|
||||
expect(runtime.pageErrors).toEqual([]);
|
||||
expect(runtime.consoleErrors).toEqual([]);
|
||||
});
|
||||
|
||||
test('rejects an invalid same-origin catalog and remains usable standalone', async ({
|
||||
page,
|
||||
}) => {
|
||||
const runtime = observeRuntime(page);
|
||||
await page.goto(`${nestedServer.appUrl}?toolbox=../invalid-catalog.json`);
|
||||
|
||||
await expect
|
||||
.poll(() => runtime.consoleWarnings.length, { timeout: 10_000 })
|
||||
.toBeGreaterThan(0);
|
||||
await expect(page.locator('[data-toolbox-context]')).toHaveAttribute(
|
||||
'data-toolbox-context',
|
||||
'standalone'
|
||||
);
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Choose files' })
|
||||
).toBeEnabled();
|
||||
expect(
|
||||
runtime.consoleWarnings.some((warning) =>
|
||||
warning.includes('Toolbox context unavailable; continuing standalone.')
|
||||
)
|
||||
).toBe(true);
|
||||
expect(
|
||||
runtime.requests.some(
|
||||
(url) =>
|
||||
url === `${nestedServer.origin}/deep/nested/invalid-catalog.json`
|
||||
)
|
||||
).toBe(true);
|
||||
expect(runtime.failedRequests).toEqual([]);
|
||||
expect(runtime.pageErrors).toEqual([]);
|
||||
expect(runtime.consoleErrors).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user