@theaiplatform/miniapp-sdk 0.2.4 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -5
- package/config-schema.json +1 -26
- package/dist/index.d.ts +72 -0
- package/dist/rspack/index.js +497 -10
- package/dist/sdk.d.ts +72 -0
- package/dist/testing/rstest.d.ts +131 -0
- package/dist/testing/rstest.js +241 -0
- package/dist/ui/wasm.js +5 -3
- package/dist/ui.js +5 -3
- package/dist/web.d.ts +72 -0
- package/package.json +32 -5
package/dist/sdk.d.ts
CHANGED
|
@@ -326,6 +326,8 @@ export declare type MiniAppPlatformApi = {
|
|
|
326
326
|
credentials?: MiniAppCredentialsApi;
|
|
327
327
|
/** Desktop host capability; feature-detect before use on portable targets. */
|
|
328
328
|
printing?: MiniAppReceiptPrintingApi;
|
|
329
|
+
/** Desktop host capability; feature-detect before opening a terminal. */
|
|
330
|
+
terminal?: MiniAppTerminalApi;
|
|
329
331
|
/** Browser capabilities appear only when the selected target supports them. */
|
|
330
332
|
auth?: MiniAppAuthApi;
|
|
331
333
|
vfs?: MiniAppVfsApi;
|
|
@@ -591,6 +593,76 @@ export declare type MiniAppStorageSetOptions = MiniAppStorageAddress & {
|
|
|
591
593
|
expectedRevision: number | null;
|
|
592
594
|
};
|
|
593
595
|
|
|
596
|
+
export declare type MiniAppTerminalApi = {
|
|
597
|
+
readonly v1: MiniAppTerminalV1Api;
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
/** Versioned, desktop-only host terminal capability. */
|
|
601
|
+
export declare type MiniAppTerminalV1Api = {
|
|
602
|
+
getCapabilities(): Promise<MiniAppTerminalV1Capabilities>;
|
|
603
|
+
open(options: MiniAppTerminalV1OpenOptions): Promise<MiniAppTerminalV1Session>;
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
export declare type MiniAppTerminalV1Capabilities = {
|
|
607
|
+
profiles: MiniAppTerminalV1Profile[];
|
|
608
|
+
limits: MiniAppTerminalV1Limits;
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
export declare type MiniAppTerminalV1DataEvent = {
|
|
612
|
+
type: 'data';
|
|
613
|
+
sequence: number;
|
|
614
|
+
data: Uint8Array;
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
export declare type MiniAppTerminalV1Event = MiniAppTerminalV1DataEvent | MiniAppTerminalV1ExitEvent;
|
|
618
|
+
|
|
619
|
+
export declare type MiniAppTerminalV1ExitEvent = {
|
|
620
|
+
type: 'exit';
|
|
621
|
+
sequence: number;
|
|
622
|
+
code: number | null;
|
|
623
|
+
signal: string | null;
|
|
624
|
+
reason: 'exited' | 'closed' | 'revoked' | 'error';
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
export declare type MiniAppTerminalV1Limits = {
|
|
628
|
+
maxSessionsPerDocument: number;
|
|
629
|
+
maxWriteBytes: number;
|
|
630
|
+
maxOutputBytesInFlight: number;
|
|
631
|
+
maxCols: number;
|
|
632
|
+
maxRows: number;
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
export declare type MiniAppTerminalV1OpenOptions = {
|
|
636
|
+
profile: MiniAppTerminalV1ProfileId;
|
|
637
|
+
cols: number;
|
|
638
|
+
rows: number;
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
export declare type MiniAppTerminalV1Profile = {
|
|
642
|
+
id: MiniAppTerminalV1ProfileId;
|
|
643
|
+
available: boolean;
|
|
644
|
+
unavailableReason: string | null;
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
/** Host-owned terminal runtime profiles exposed by `sdk.terminal.v1`. */
|
|
648
|
+
export declare type MiniAppTerminalV1ProfileId = 'workspace-shell' | 'neovim';
|
|
649
|
+
|
|
650
|
+
export declare type MiniAppTerminalV1ResizeOptions = {
|
|
651
|
+
cols: number;
|
|
652
|
+
rows: number;
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
export declare type MiniAppTerminalV1Session = {
|
|
656
|
+
/** Opaque host-minted session identity; it carries no ambient authority. */
|
|
657
|
+
readonly id: string;
|
|
658
|
+
readonly profile: MiniAppTerminalV1ProfileId;
|
|
659
|
+
/** Ordered output with byte-sized backpressure owned by the host session. */
|
|
660
|
+
readonly events: ReadableStream<MiniAppTerminalV1Event>;
|
|
661
|
+
write(data: Uint8Array): Promise<void>;
|
|
662
|
+
resize(options: MiniAppTerminalV1ResizeOptions): Promise<void>;
|
|
663
|
+
close(): Promise<void>;
|
|
664
|
+
};
|
|
665
|
+
|
|
594
666
|
export declare type MiniAppUserProfile = {
|
|
595
667
|
sub: string;
|
|
596
668
|
name?: string | null;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { afterAll } from '@rstest/playwright';
|
|
2
|
+
import { afterEach } from '@rstest/playwright';
|
|
3
|
+
import { APIRequestContext } from 'playwright';
|
|
4
|
+
import { beforeAll } from '@rstest/playwright';
|
|
5
|
+
import { beforeEach } from '@rstest/playwright';
|
|
6
|
+
import type { Browser } from 'playwright';
|
|
7
|
+
import type { BrowserContext } from 'playwright';
|
|
8
|
+
import { describe } from '@rstest/playwright';
|
|
9
|
+
import { expect } from '@rstest/playwright';
|
|
10
|
+
import type { FrameLocator } from 'playwright';
|
|
11
|
+
import type { Page } from 'playwright';
|
|
12
|
+
import { PlaywrightOptions } from '@rstest/playwright';
|
|
13
|
+
import { PlaywrightServe } from '@rstest/playwright';
|
|
14
|
+
import { PlaywrightTest } from '@rstest/playwright';
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
|
|
17
|
+
export { afterAll }
|
|
18
|
+
|
|
19
|
+
export { afterEach }
|
|
20
|
+
|
|
21
|
+
export { beforeAll }
|
|
22
|
+
|
|
23
|
+
export { beforeEach }
|
|
24
|
+
|
|
25
|
+
export { describe }
|
|
26
|
+
|
|
27
|
+
export { expect }
|
|
28
|
+
|
|
29
|
+
/** Validate a driver session before any endpoint or provenance field is used. */
|
|
30
|
+
export declare function parseTapMiniappTestSession(value: unknown): TapMiniappTestSession;
|
|
31
|
+
|
|
32
|
+
declare const sessionSchema: z.ZodObject<{
|
|
33
|
+
schemaVersion: z.ZodLiteral<1>;
|
|
34
|
+
runId: z.ZodString;
|
|
35
|
+
workspaceId: z.ZodString;
|
|
36
|
+
channelId: z.ZodString;
|
|
37
|
+
packageId: z.ZodString;
|
|
38
|
+
installationId: z.ZodString;
|
|
39
|
+
mode: z.ZodEnum<{
|
|
40
|
+
surface: "surface";
|
|
41
|
+
"live-tap": "live-tap";
|
|
42
|
+
}>;
|
|
43
|
+
dataScope: z.ZodEnum<{
|
|
44
|
+
fixture: "fixture";
|
|
45
|
+
"selected-channel": "selected-channel";
|
|
46
|
+
}>;
|
|
47
|
+
permissionScenario: z.ZodString;
|
|
48
|
+
surfaceId: z.ZodString;
|
|
49
|
+
surfaceSelector: z.ZodString;
|
|
50
|
+
surfaceAssetOrigin: z.ZodString;
|
|
51
|
+
pageUrlPrefix: z.ZodString;
|
|
52
|
+
cdpEndpoint: z.ZodString;
|
|
53
|
+
cdpAuthorization: z.ZodString;
|
|
54
|
+
artifactDirectory: z.ZodString;
|
|
55
|
+
allowedNetworkOrigins: z.ZodArray<z.ZodString>;
|
|
56
|
+
credentialAliases: z.ZodArray<z.ZodString>;
|
|
57
|
+
releaseDigest: z.ZodOptional<z.ZodString>;
|
|
58
|
+
localGeneration: z.ZodOptional<z.ZodNumber>;
|
|
59
|
+
sourceDigest: z.ZodString;
|
|
60
|
+
testBundleDigest: z.ZodString;
|
|
61
|
+
}, z.core.$strip>;
|
|
62
|
+
|
|
63
|
+
export declare type TapMiniappTestControl = {
|
|
64
|
+
/** Restore the run's declared fixture and permission scenario. */
|
|
65
|
+
reset: () => Promise<void>;
|
|
66
|
+
/** Ask the TAP host to emit one versioned platform event through the normal frame bridge. */
|
|
67
|
+
emitHostEvent: (event: string, payload?: unknown) => Promise<void>;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export declare type TapMiniappTestFixture = Readonly<Pick<TapMiniappTestSession, 'channelId' | 'dataScope' | 'installationId' | 'localGeneration' | 'mode' | 'packageId' | 'permissionScenario' | 'releaseDigest' | 'runId' | 'sourceDigest' | 'surfaceId' | 'surfaceAssetOrigin' | 'testBundleDigest' | 'workspaceId'> & {
|
|
71
|
+
readonly allowedNetworkOrigins: readonly string[];
|
|
72
|
+
readonly credentialAliases: readonly string[];
|
|
73
|
+
control: TapMiniappTestControl;
|
|
74
|
+
}>;
|
|
75
|
+
|
|
76
|
+
export declare type TapMiniappTestSession = z.infer<typeof sessionSchema>;
|
|
77
|
+
|
|
78
|
+
export declare type TapRstestFixtures = {
|
|
79
|
+
browser: Browser;
|
|
80
|
+
context: BrowserContext;
|
|
81
|
+
page: Page;
|
|
82
|
+
/** Locator for the authorized miniapp iframe mounted by TAP's real frame host. */
|
|
83
|
+
surface: FrameLocator;
|
|
84
|
+
/** Provenance and scoped host controls for this exact test run. */
|
|
85
|
+
tap: TapMiniappTestFixture;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Rstest's Playwright test API with TAP-owned browser, page, iframe, and run
|
|
90
|
+
* fixtures. The upstream runner still owns scheduling, assertions, hooks, and
|
|
91
|
+
* reporting; TAP owns the privileged browser/session boundary.
|
|
92
|
+
*/
|
|
93
|
+
export declare const test: PlaywrightTest< {
|
|
94
|
+
browser: Browser;
|
|
95
|
+
context: BrowserContext;
|
|
96
|
+
request: APIRequestContext;
|
|
97
|
+
surface: FrameLocator;
|
|
98
|
+
page: Page;
|
|
99
|
+
tap: Readonly<Pick<{
|
|
100
|
+
schemaVersion: 1;
|
|
101
|
+
runId: string;
|
|
102
|
+
workspaceId: string;
|
|
103
|
+
channelId: string;
|
|
104
|
+
packageId: string;
|
|
105
|
+
installationId: string;
|
|
106
|
+
mode: "surface" | "live-tap";
|
|
107
|
+
dataScope: "fixture" | "selected-channel";
|
|
108
|
+
permissionScenario: string;
|
|
109
|
+
surfaceId: string;
|
|
110
|
+
surfaceSelector: string;
|
|
111
|
+
surfaceAssetOrigin: string;
|
|
112
|
+
pageUrlPrefix: string;
|
|
113
|
+
cdpEndpoint: string;
|
|
114
|
+
cdpAuthorization: string;
|
|
115
|
+
artifactDirectory: string;
|
|
116
|
+
allowedNetworkOrigins: string[];
|
|
117
|
+
credentialAliases: string[];
|
|
118
|
+
sourceDigest: string;
|
|
119
|
+
testBundleDigest: string;
|
|
120
|
+
releaseDigest?: string | undefined;
|
|
121
|
+
localGeneration?: number | undefined;
|
|
122
|
+
}, "packageId" | "installationId" | "workspaceId" | "channelId" | "mode" | "runId" | "dataScope" | "permissionScenario" | "surfaceId" | "surfaceAssetOrigin" | "releaseDigest" | "localGeneration" | "sourceDigest" | "testBundleDigest"> & {
|
|
123
|
+
readonly allowedNetworkOrigins: readonly string[];
|
|
124
|
+
readonly credentialAliases: readonly string[];
|
|
125
|
+
control: TapMiniappTestControl;
|
|
126
|
+
}>;
|
|
127
|
+
playwright: PlaywrightOptions;
|
|
128
|
+
serve: PlaywrightServe;
|
|
129
|
+
}>;
|
|
130
|
+
|
|
131
|
+
export { }
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import * as __rspack_external__rstest_playwright_5734ff29 from "@rstest/playwright";
|
|
2
|
+
import * as __rspack_external_node_fs_promises_3b710708 from "node:fs/promises";
|
|
3
|
+
import * as __rspack_external_node_path_806ed179 from "node:path";
|
|
4
|
+
import * as __rspack_external_playwright from "playwright";
|
|
5
|
+
import * as __rspack_external_zod from "zod";
|
|
6
|
+
const SESSION_ENV = 'TAP_MINIAPP_TEST_SESSION_FILE';
|
|
7
|
+
const sessionSchema = __rspack_external_zod.z.object({
|
|
8
|
+
schemaVersion: __rspack_external_zod.z.literal(1),
|
|
9
|
+
runId: __rspack_external_zod.z.string().min(1),
|
|
10
|
+
workspaceId: __rspack_external_zod.z.string().min(1),
|
|
11
|
+
channelId: __rspack_external_zod.z.string().min(1),
|
|
12
|
+
packageId: __rspack_external_zod.z.string().min(1),
|
|
13
|
+
installationId: __rspack_external_zod.z.string().min(1),
|
|
14
|
+
mode: __rspack_external_zod.z["enum"]([
|
|
15
|
+
'surface',
|
|
16
|
+
'live-tap'
|
|
17
|
+
]),
|
|
18
|
+
dataScope: __rspack_external_zod.z["enum"]([
|
|
19
|
+
'fixture',
|
|
20
|
+
'selected-channel'
|
|
21
|
+
]),
|
|
22
|
+
permissionScenario: __rspack_external_zod.z.string().min(1),
|
|
23
|
+
surfaceId: __rspack_external_zod.z.string().min(1),
|
|
24
|
+
surfaceSelector: __rspack_external_zod.z.string().min(1),
|
|
25
|
+
surfaceAssetOrigin: __rspack_external_zod.z.string().url(),
|
|
26
|
+
pageUrlPrefix: __rspack_external_zod.z.string().url(),
|
|
27
|
+
cdpEndpoint: __rspack_external_zod.z.string().url(),
|
|
28
|
+
cdpAuthorization: __rspack_external_zod.z.string().min(1),
|
|
29
|
+
artifactDirectory: __rspack_external_zod.z.string().min(1),
|
|
30
|
+
allowedNetworkOrigins: __rspack_external_zod.z.array(__rspack_external_zod.z.string().url()).max(128),
|
|
31
|
+
credentialAliases: __rspack_external_zod.z.array(__rspack_external_zod.z.string().min(1).max(256)).max(64),
|
|
32
|
+
releaseDigest: __rspack_external_zod.z.string().min(1).optional(),
|
|
33
|
+
localGeneration: __rspack_external_zod.z.number().int().nonnegative().optional(),
|
|
34
|
+
sourceDigest: __rspack_external_zod.z.string().min(1),
|
|
35
|
+
testBundleDigest: __rspack_external_zod.z.string().min(1)
|
|
36
|
+
});
|
|
37
|
+
let sessionPromise;
|
|
38
|
+
let browserPromise;
|
|
39
|
+
function parseTapMiniappTestSession(value) {
|
|
40
|
+
return sessionSchema.parse(value);
|
|
41
|
+
}
|
|
42
|
+
async function loadSession() {
|
|
43
|
+
sessionPromise ??= (async ()=>{
|
|
44
|
+
const sessionPath = process.env[SESSION_ENV]?.trim();
|
|
45
|
+
if (!sessionPath) throw new Error(`${SESSION_ENV} is missing. Start this suite from The AI Platform Miniapp Test Lab.`);
|
|
46
|
+
const raw = await (0, __rspack_external_node_fs_promises_3b710708.readFile)(sessionPath, 'utf8');
|
|
47
|
+
return parseTapMiniappTestSession(JSON.parse(raw));
|
|
48
|
+
})();
|
|
49
|
+
return sessionPromise;
|
|
50
|
+
}
|
|
51
|
+
function selectPage(context, session) {
|
|
52
|
+
const candidates = context.pages().filter((candidate)=>candidate.url().startsWith(session.pageUrlPrefix));
|
|
53
|
+
if (1 !== candidates.length) throw new Error(`TAP Browser Driver exposed ${candidates.length} matching pages for run ${session.runId}; expected exactly one.`);
|
|
54
|
+
const page = candidates[0];
|
|
55
|
+
if (!page) throw new Error('TAP Browser Driver page selection failed');
|
|
56
|
+
return page;
|
|
57
|
+
}
|
|
58
|
+
async function emitHostEvent(page, session, event, payload) {
|
|
59
|
+
if (!event.startsWith('tap.') || event.length > 160 || event.trim() !== event) throw new Error('TAP host events must be bounded, trimmed tap.* event names.');
|
|
60
|
+
await page.evaluate(({ controlEvent, event, payload, runId })=>{
|
|
61
|
+
const response = {};
|
|
62
|
+
globalThis.dispatchEvent(new CustomEvent(controlEvent, {
|
|
63
|
+
detail: {
|
|
64
|
+
event,
|
|
65
|
+
payload,
|
|
66
|
+
response,
|
|
67
|
+
runId
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
if (response.error) throw new Error(response.error);
|
|
71
|
+
if (!response.delivered) throw new Error(`The TAP frame host has no active subscriber for ${event}. Declare the event on the miniapp surface before using it in a test.`);
|
|
72
|
+
}, {
|
|
73
|
+
controlEvent: 'tap:miniapp-test-control',
|
|
74
|
+
event,
|
|
75
|
+
payload,
|
|
76
|
+
runId: session.runId
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function fixtureMetadata(session, page) {
|
|
80
|
+
return Object.freeze({
|
|
81
|
+
allowedNetworkOrigins: Object.freeze([
|
|
82
|
+
...session.allowedNetworkOrigins
|
|
83
|
+
]),
|
|
84
|
+
channelId: session.channelId,
|
|
85
|
+
credentialAliases: Object.freeze([
|
|
86
|
+
...session.credentialAliases
|
|
87
|
+
]),
|
|
88
|
+
control: Object.freeze({
|
|
89
|
+
emitHostEvent: (event, payload)=>emitHostEvent(page, session, event, payload),
|
|
90
|
+
reset: async ()=>{
|
|
91
|
+
await page.reload({
|
|
92
|
+
waitUntil: 'domcontentloaded'
|
|
93
|
+
});
|
|
94
|
+
await page.locator(session.surfaceSelector).waitFor({
|
|
95
|
+
state: 'attached'
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}),
|
|
99
|
+
dataScope: session.dataScope,
|
|
100
|
+
installationId: session.installationId,
|
|
101
|
+
localGeneration: session.localGeneration,
|
|
102
|
+
mode: session.mode,
|
|
103
|
+
packageId: session.packageId,
|
|
104
|
+
permissionScenario: session.permissionScenario,
|
|
105
|
+
releaseDigest: session.releaseDigest,
|
|
106
|
+
runId: session.runId,
|
|
107
|
+
sourceDigest: session.sourceDigest,
|
|
108
|
+
surfaceAssetOrigin: session.surfaceAssetOrigin,
|
|
109
|
+
surfaceId: session.surfaceId,
|
|
110
|
+
testBundleDigest: session.testBundleDigest,
|
|
111
|
+
workspaceId: session.workspaceId
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function safeArtifactSegment(value) {
|
|
115
|
+
return value.replaceAll(/[^a-zA-Z0-9._-]/g, '-').slice(0, 160);
|
|
116
|
+
}
|
|
117
|
+
const test = __rspack_external__rstest_playwright_5734ff29.test.extend({
|
|
118
|
+
browser: async (_context, use)=>{
|
|
119
|
+
const session = await loadSession();
|
|
120
|
+
browserPromise ??= __rspack_external_playwright.chromium.connectOverCDP(session.cdpEndpoint, {
|
|
121
|
+
headers: {
|
|
122
|
+
authorization: `Bearer ${session.cdpAuthorization}`,
|
|
123
|
+
'x-tap-miniapp-test-run': session.runId
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
await use(await browserPromise);
|
|
127
|
+
},
|
|
128
|
+
context: async ({ browser, task }, use)=>{
|
|
129
|
+
const session = await loadSession();
|
|
130
|
+
const contexts = browser.contexts().filter((candidate)=>candidate.pages().some((page)=>page.url().startsWith(session.pageUrlPrefix)));
|
|
131
|
+
if (1 !== contexts.length) throw new Error(`TAP Browser Driver exposed ${contexts.length} matching contexts for run ${session.runId}; expected exactly one.`);
|
|
132
|
+
const context = contexts[0];
|
|
133
|
+
if (!context) throw new Error('TAP Browser Driver context selection failed');
|
|
134
|
+
const hostPage = selectPage(context, session);
|
|
135
|
+
const runtimeOrigins = new Set(hostPage.frames().map((frame)=>originOf(frame.url())).filter((origin)=>void 0 !== origin));
|
|
136
|
+
const allowedOrigins = new Set([
|
|
137
|
+
...runtimeOrigins,
|
|
138
|
+
new URL(session.surfaceAssetOrigin).origin,
|
|
139
|
+
...session.allowedNetworkOrigins.map((value)=>new URL(value).origin)
|
|
140
|
+
]);
|
|
141
|
+
const enforceNetworkPolicy = async (route)=>{
|
|
142
|
+
const url = route.request().url();
|
|
143
|
+
const origin = originOf(url);
|
|
144
|
+
if (void 0 === origin || allowedOrigins.has(origin)) return void await route.continue();
|
|
145
|
+
await route.abort('blockedbyclient');
|
|
146
|
+
};
|
|
147
|
+
await context.route('**/*', enforceNetworkPolicy);
|
|
148
|
+
const traceDirectory = (0, __rspack_external_node_path_806ed179.join)(session.artifactDirectory, 'traces', safeArtifactSegment(task.id));
|
|
149
|
+
await (0, __rspack_external_node_fs_promises_3b710708.mkdir)(traceDirectory, {
|
|
150
|
+
recursive: true
|
|
151
|
+
});
|
|
152
|
+
await context.tracing.start({
|
|
153
|
+
screenshots: true,
|
|
154
|
+
snapshots: true,
|
|
155
|
+
sources: true
|
|
156
|
+
});
|
|
157
|
+
try {
|
|
158
|
+
await use(context);
|
|
159
|
+
} finally{
|
|
160
|
+
await context.tracing.stop({
|
|
161
|
+
path: (0, __rspack_external_node_path_806ed179.join)(traceDirectory, 'trace.zip')
|
|
162
|
+
});
|
|
163
|
+
const traceSummary = {
|
|
164
|
+
schemaVersion: 1,
|
|
165
|
+
runId: session.runId,
|
|
166
|
+
taskId: task.id,
|
|
167
|
+
mode: session.mode,
|
|
168
|
+
dataScope: session.dataScope,
|
|
169
|
+
packageId: session.packageId,
|
|
170
|
+
surfaceId: session.surfaceId,
|
|
171
|
+
sourceDigest: session.sourceDigest,
|
|
172
|
+
testBundleDigest: session.testBundleDigest,
|
|
173
|
+
tracePath: 'trace.zip',
|
|
174
|
+
redactions: [
|
|
175
|
+
'authorization headers',
|
|
176
|
+
'cookies',
|
|
177
|
+
'credential values',
|
|
178
|
+
'network bodies'
|
|
179
|
+
]
|
|
180
|
+
};
|
|
181
|
+
await Promise.all([
|
|
182
|
+
(0, __rspack_external_node_fs_promises_3b710708.writeFile)((0, __rspack_external_node_path_806ed179.join)(traceDirectory, 'trace-summary.json'), `${JSON.stringify(traceSummary, void 0, 2)}\n`, 'utf8'),
|
|
183
|
+
(0, __rspack_external_node_fs_promises_3b710708.writeFile)((0, __rspack_external_node_path_806ed179.join)(traceDirectory, 'debug.md'), [
|
|
184
|
+
'# Miniapp test trace',
|
|
185
|
+
'',
|
|
186
|
+
`- Run: \`${session.runId}\``,
|
|
187
|
+
`- Rstest task: \`${task.id}\``,
|
|
188
|
+
`- Mode: \`${session.mode}\``,
|
|
189
|
+
`- Data scope: \`${session.dataScope}\``,
|
|
190
|
+
`- Surface: \`${session.surfaceId}\``,
|
|
191
|
+
`- Source digest: \`${session.sourceDigest}\``,
|
|
192
|
+
`- Test bundle digest: \`${session.testBundleDigest}\``,
|
|
193
|
+
'',
|
|
194
|
+
'Open `trace.zip` from The AI Platform Test Lab for the DOM, screenshots, console, and network timeline. The final assertion outcome is authoritative in `report.json` and `report.md`.',
|
|
195
|
+
''
|
|
196
|
+
].join('\n'), 'utf8')
|
|
197
|
+
]);
|
|
198
|
+
await context.unroute('**/*', enforceNetworkPolicy);
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
page: async ({ context }, use)=>{
|
|
202
|
+
const session = await loadSession();
|
|
203
|
+
const page = selectPage(context, session);
|
|
204
|
+
await page.locator(session.surfaceSelector).waitFor({
|
|
205
|
+
state: 'attached'
|
|
206
|
+
});
|
|
207
|
+
await use(page);
|
|
208
|
+
},
|
|
209
|
+
surface: async ({ page }, use)=>{
|
|
210
|
+
const session = await loadSession();
|
|
211
|
+
await use(page.frameLocator(session.surfaceSelector));
|
|
212
|
+
},
|
|
213
|
+
tap: async ({ page }, use)=>{
|
|
214
|
+
await use(fixtureMetadata(await loadSession(), page));
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
function originOf(value) {
|
|
218
|
+
try {
|
|
219
|
+
const url = new URL(value);
|
|
220
|
+
if (matchesNonNetworkScheme(url.protocol)) return;
|
|
221
|
+
return url.origin;
|
|
222
|
+
} catch {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function matchesNonNetworkScheme(protocol) {
|
|
227
|
+
return NON_NETWORK_PROTOCOLS.has(protocol);
|
|
228
|
+
}
|
|
229
|
+
const NON_NETWORK_PROTOCOLS = new Set([
|
|
230
|
+
'about:',
|
|
231
|
+
'blob:',
|
|
232
|
+
'data:',
|
|
233
|
+
'file:'
|
|
234
|
+
]);
|
|
235
|
+
var afterAll = __rspack_external__rstest_playwright_5734ff29.afterAll;
|
|
236
|
+
var afterEach = __rspack_external__rstest_playwright_5734ff29.afterEach;
|
|
237
|
+
var beforeAll = __rspack_external__rstest_playwright_5734ff29.beforeAll;
|
|
238
|
+
var beforeEach = __rspack_external__rstest_playwright_5734ff29.beforeEach;
|
|
239
|
+
var describe = __rspack_external__rstest_playwright_5734ff29.describe;
|
|
240
|
+
var expect = __rspack_external__rstest_playwright_5734ff29.expect;
|
|
241
|
+
export { afterAll, afterEach, beforeAll, beforeEach, describe, expect, parseTapMiniappTestSession, test };
|
package/dist/ui/wasm.js
CHANGED
|
@@ -6,7 +6,7 @@ import { clsx } from "clsx";
|
|
|
6
6
|
import { twMerge } from "tailwind-merge";
|
|
7
7
|
import { Slot as react_slot_Slot } from "@radix-ui/react-slot";
|
|
8
8
|
import "prism-react-renderer";
|
|
9
|
-
import {
|
|
9
|
+
import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
|
10
10
|
import { useCallback as external_react_useCallback, useEffect, useRef } from "react";
|
|
11
11
|
import "react-resizable-panels";
|
|
12
12
|
import "@radix-ui/react-scroll-area";
|
|
@@ -626,6 +626,7 @@ DialogContentPrimitive.displayName = __rspack_external__radix_ui_react_dialog_da
|
|
|
626
626
|
function DialogContent({ className, children, ref, container, hideCloseButton, onOpenAutoFocus, onEscapeKeyDown, ...props }) {
|
|
627
627
|
const { ref: occlusionRef, ready } = native_view_occlusion_useNativeViewOcclusion();
|
|
628
628
|
const contentRef = __rspack_external_react.useRef(null);
|
|
629
|
+
const composedContentRef = useComposedRefs(ref, contentRef);
|
|
629
630
|
const closeButtonRef = __rspack_external_react.useRef(null);
|
|
630
631
|
const shouldFocusWhenReadyRef = __rspack_external_react.useRef(false);
|
|
631
632
|
const handleOpenAutoFocus = __rspack_external_react.useCallback((event)=>{
|
|
@@ -670,7 +671,7 @@ function DialogContent({ className, children, ref, container, hideCloseButton, o
|
|
|
670
671
|
bottom: 'var(--chat-input-offset, 0px)'
|
|
671
672
|
} : void 0
|
|
672
673
|
}, /*#__PURE__*/ __rspack_external_react.createElement(DialogContentPrimitive, {
|
|
673
|
-
ref:
|
|
674
|
+
ref: composedContentRef,
|
|
674
675
|
className: utils_cn('bg-surface-level-1 pointer-events-auto relative grid max-h-full w-full max-w-lg min-w-0 gap-4 overflow-auto rounded-3xl border p-8 break-words shadow-lg', className),
|
|
675
676
|
...container ? {
|
|
676
677
|
onInteractOutside: (e)=>{
|
|
@@ -1348,8 +1349,9 @@ function SelectScrollDownButton({ className, ref, ...props }) {
|
|
|
1348
1349
|
SelectScrollDownButton.displayName = __rspack_external__radix_ui_react_select_4606f4d3.ScrollDownButton.displayName;
|
|
1349
1350
|
function SelectContent({ className, children, position = 'popper', ref, ...props }) {
|
|
1350
1351
|
const { ref: occlusionRef, ready } = native_view_occlusion_useNativeViewOcclusion();
|
|
1352
|
+
const composedRef = useComposedRefs(ref, occlusionRef);
|
|
1351
1353
|
return /*#__PURE__*/ __rspack_external_react.createElement(__rspack_external__radix_ui_react_select_4606f4d3.Portal, null, /*#__PURE__*/ __rspack_external_react.createElement(__rspack_external__radix_ui_react_select_4606f4d3.Content, {
|
|
1352
|
-
ref:
|
|
1354
|
+
ref: composedRef,
|
|
1353
1355
|
className: utils_cn('bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-(--z-popover) max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-x-hidden overflow-y-auto rounded-lg shadow-sm data-[side=bottom]:origin-top data-[side=left]:origin-right data-[side=right]:origin-left data-[side=top]:origin-bottom', 'popper' === position && 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', !ready && 'invisible', className),
|
|
1354
1356
|
position: position,
|
|
1355
1357
|
...props
|
package/dist/ui.js
CHANGED
|
@@ -4,7 +4,7 @@ import { twMerge } from "tailwind-merge";
|
|
|
4
4
|
import { Slot } from "@radix-ui/react-slot";
|
|
5
5
|
import { Check, CheckIcon, ChevronDown, ChevronUp, Circle, CopyIcon, GripVertical, X, XIcon } from "lucide-react";
|
|
6
6
|
import { Highlight, themes } from "prism-react-renderer";
|
|
7
|
-
import {
|
|
7
|
+
import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
|
8
8
|
import { useCallback, useEffect, useRef } from "react";
|
|
9
9
|
import { Group, Panel, Separator as external_react_resizable_panels_Separator } from "react-resizable-panels";
|
|
10
10
|
import * as __rspack_external_react from "react";
|
|
@@ -808,6 +808,7 @@ DialogContentPrimitive.displayName = __rspack_external__radix_ui_react_dialog_da
|
|
|
808
808
|
function DialogContent({ className, children, ref, container, hideCloseButton, onOpenAutoFocus, onEscapeKeyDown, ...props }) {
|
|
809
809
|
const { ref: occlusionRef, ready } = useNativeViewOcclusion();
|
|
810
810
|
const contentRef = __rspack_external_react.useRef(null);
|
|
811
|
+
const composedContentRef = useComposedRefs(ref, contentRef);
|
|
811
812
|
const closeButtonRef = __rspack_external_react.useRef(null);
|
|
812
813
|
const shouldFocusWhenReadyRef = __rspack_external_react.useRef(false);
|
|
813
814
|
const handleOpenAutoFocus = __rspack_external_react.useCallback((event)=>{
|
|
@@ -852,7 +853,7 @@ function DialogContent({ className, children, ref, container, hideCloseButton, o
|
|
|
852
853
|
bottom: 'var(--chat-input-offset, 0px)'
|
|
853
854
|
} : void 0
|
|
854
855
|
}, /*#__PURE__*/ __rspack_external_react.createElement(DialogContentPrimitive, {
|
|
855
|
-
ref:
|
|
856
|
+
ref: composedContentRef,
|
|
856
857
|
className: cn('bg-surface-level-1 pointer-events-auto relative grid max-h-full w-full max-w-lg min-w-0 gap-4 overflow-auto rounded-3xl border p-8 break-words shadow-lg', className),
|
|
857
858
|
...container ? {
|
|
858
859
|
onInteractOutside: (e)=>{
|
|
@@ -1725,8 +1726,9 @@ function SelectScrollDownButton({ className, ref, ...props }) {
|
|
|
1725
1726
|
SelectScrollDownButton.displayName = __rspack_external__radix_ui_react_select_4606f4d3.ScrollDownButton.displayName;
|
|
1726
1727
|
function SelectContent({ className, children, position = 'popper', ref, ...props }) {
|
|
1727
1728
|
const { ref: occlusionRef, ready } = useNativeViewOcclusion();
|
|
1729
|
+
const composedRef = useComposedRefs(ref, occlusionRef);
|
|
1728
1730
|
return /*#__PURE__*/ __rspack_external_react.createElement(__rspack_external__radix_ui_react_select_4606f4d3.Portal, null, /*#__PURE__*/ __rspack_external_react.createElement(__rspack_external__radix_ui_react_select_4606f4d3.Content, {
|
|
1729
|
-
ref:
|
|
1731
|
+
ref: composedRef,
|
|
1730
1732
|
className: cn('bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-(--z-popover) max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-x-hidden overflow-y-auto rounded-lg shadow-sm data-[side=bottom]:origin-top data-[side=left]:origin-right data-[side=right]:origin-left data-[side=top]:origin-bottom', 'popper' === position && 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', !ready && 'invisible', className),
|
|
1731
1733
|
position: position,
|
|
1732
1734
|
...props
|
package/dist/web.d.ts
CHANGED
|
@@ -367,6 +367,8 @@ export declare type MiniAppPlatformApi = {
|
|
|
367
367
|
credentials?: MiniAppCredentialsApi;
|
|
368
368
|
/** Desktop host capability; feature-detect before use on portable targets. */
|
|
369
369
|
printing?: MiniAppReceiptPrintingApi;
|
|
370
|
+
/** Desktop host capability; feature-detect before opening a terminal. */
|
|
371
|
+
terminal?: MiniAppTerminalApi;
|
|
370
372
|
/** Browser capabilities appear only when the selected target supports them. */
|
|
371
373
|
auth?: MiniAppAuthApi;
|
|
372
374
|
vfs?: MiniAppVfsApi;
|
|
@@ -632,6 +634,76 @@ declare type MiniAppStorageSetOptions = MiniAppStorageAddress & {
|
|
|
632
634
|
expectedRevision: number | null;
|
|
633
635
|
};
|
|
634
636
|
|
|
637
|
+
declare type MiniAppTerminalApi = {
|
|
638
|
+
readonly v1: MiniAppTerminalV1Api;
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
/** Versioned, desktop-only host terminal capability. */
|
|
642
|
+
declare type MiniAppTerminalV1Api = {
|
|
643
|
+
getCapabilities(): Promise<MiniAppTerminalV1Capabilities>;
|
|
644
|
+
open(options: MiniAppTerminalV1OpenOptions): Promise<MiniAppTerminalV1Session>;
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
declare type MiniAppTerminalV1Capabilities = {
|
|
648
|
+
profiles: MiniAppTerminalV1Profile[];
|
|
649
|
+
limits: MiniAppTerminalV1Limits;
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
declare type MiniAppTerminalV1DataEvent = {
|
|
653
|
+
type: 'data';
|
|
654
|
+
sequence: number;
|
|
655
|
+
data: Uint8Array;
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
declare type MiniAppTerminalV1Event = MiniAppTerminalV1DataEvent | MiniAppTerminalV1ExitEvent;
|
|
659
|
+
|
|
660
|
+
declare type MiniAppTerminalV1ExitEvent = {
|
|
661
|
+
type: 'exit';
|
|
662
|
+
sequence: number;
|
|
663
|
+
code: number | null;
|
|
664
|
+
signal: string | null;
|
|
665
|
+
reason: 'exited' | 'closed' | 'revoked' | 'error';
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
declare type MiniAppTerminalV1Limits = {
|
|
669
|
+
maxSessionsPerDocument: number;
|
|
670
|
+
maxWriteBytes: number;
|
|
671
|
+
maxOutputBytesInFlight: number;
|
|
672
|
+
maxCols: number;
|
|
673
|
+
maxRows: number;
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
declare type MiniAppTerminalV1OpenOptions = {
|
|
677
|
+
profile: MiniAppTerminalV1ProfileId;
|
|
678
|
+
cols: number;
|
|
679
|
+
rows: number;
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
declare type MiniAppTerminalV1Profile = {
|
|
683
|
+
id: MiniAppTerminalV1ProfileId;
|
|
684
|
+
available: boolean;
|
|
685
|
+
unavailableReason: string | null;
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
/** Host-owned terminal runtime profiles exposed by `sdk.terminal.v1`. */
|
|
689
|
+
declare type MiniAppTerminalV1ProfileId = 'workspace-shell' | 'neovim';
|
|
690
|
+
|
|
691
|
+
declare type MiniAppTerminalV1ResizeOptions = {
|
|
692
|
+
cols: number;
|
|
693
|
+
rows: number;
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
declare type MiniAppTerminalV1Session = {
|
|
697
|
+
/** Opaque host-minted session identity; it carries no ambient authority. */
|
|
698
|
+
readonly id: string;
|
|
699
|
+
readonly profile: MiniAppTerminalV1ProfileId;
|
|
700
|
+
/** Ordered output with byte-sized backpressure owned by the host session. */
|
|
701
|
+
readonly events: ReadableStream<MiniAppTerminalV1Event>;
|
|
702
|
+
write(data: Uint8Array): Promise<void>;
|
|
703
|
+
resize(options: MiniAppTerminalV1ResizeOptions): Promise<void>;
|
|
704
|
+
close(): Promise<void>;
|
|
705
|
+
};
|
|
706
|
+
|
|
635
707
|
export declare type MiniAppTheme = 'light' | 'dark';
|
|
636
708
|
|
|
637
709
|
export declare type MiniAppUiScale = number;
|