Frontend iframe renderer framework: 3D models, OpenAPI (#37233)
Introduces a frontend external-render framework that runs renderer plugins inside an `iframe` (loaded via `srcdoc` to keep the CSP `sandbox` directive working without origin-related console noise), and migrates the 3D viewer and OpenAPI/Swagger renderers onto it. PDF and asciicast paths are refactored to share the same `data-render-name` mechanism. Adds e2e coverage for 3D, PDF, asciicast and OpenAPI render paths, plus a regression for the `RefTypeNameSubURL` double-escape on non-ASCII branch names. Signed-off-by: silverwind <me@silverwind.io> Co-authored-by: Claude (Opus 4.6) <noreply@anthropic.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
+17
-1
@@ -1,6 +1,6 @@
|
||||
import {env} from 'node:process';
|
||||
import {expect} from '@playwright/test';
|
||||
import type {APIRequestContext, Page} from '@playwright/test';
|
||||
import type {APIRequestContext, Locator, Page} from '@playwright/test';
|
||||
|
||||
/** Generate a random alphanumeric string. */
|
||||
export function randomString(length: number): string {
|
||||
@@ -67,6 +67,13 @@ export async function apiCreateFile(requestContext: APIRequestContext, owner: st
|
||||
}), 'apiCreateFile');
|
||||
}
|
||||
|
||||
export async function apiCreateBranch(requestContext: APIRequestContext, owner: string, repo: string, newBranch: string) {
|
||||
await apiRetry(() => requestContext.post(`${baseUrl()}/api/v1/repos/${owner}/${repo}/branches`, {
|
||||
headers: apiHeaders(),
|
||||
data: {new_branch_name: newBranch},
|
||||
}), 'apiCreateBranch');
|
||||
}
|
||||
|
||||
export async function apiDeleteRepo(requestContext: APIRequestContext, owner: string, name: string) {
|
||||
await apiRetry(() => requestContext.delete(`${baseUrl()}/api/v1/repos/${owner}/${name}`, {
|
||||
headers: apiHeaders(),
|
||||
@@ -115,6 +122,15 @@ export async function assertNoJsError(page: Page) {
|
||||
await expect(page.locator('.js-global-error')).toHaveCount(0);
|
||||
}
|
||||
|
||||
/* asserts the child has no horizontal inset from its parent — catches padding/border anywhere
|
||||
* in between regardless of which element declares it */
|
||||
export async function assertFlushWithParent(child: Locator, parent: Locator) {
|
||||
const [childBox, parentBox] = await Promise.all([child.boundingBox(), parent.boundingBox()]);
|
||||
if (!childBox || !parentBox) throw new Error('boundingBox returned null');
|
||||
expect(childBox.x).toBe(parentBox.x);
|
||||
expect(childBox.width).toBe(parentBox.width);
|
||||
}
|
||||
|
||||
export async function logout(page: Page) {
|
||||
await page.context().clearCookies(); // workaround issues related to fomantic dropdown
|
||||
await page.goto('/');
|
||||
|
||||
Reference in New Issue
Block a user