| author | |
| committer | |
| log | 2fbe313096b54a3422e101ed1bcc3589f6cf371c |
| tree | 16fea27b34e8b57301819e0bb0158a05e769cc1e |
| parent | 850e4582e4c828b1533a400bf56a532721239198 |
| signature | Signed by PGP key B5690EEEBB952194 |
4 files changed, 54 insertions(+), 5 deletions(-)
apps/desktop/src/ipc/methods/preview.test.ts+43| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | import { it as effectIt } from "@effect/vitest"; | 1 | import { it as effectIt } from "@effect/vitest"; |
| 2 | import { PreviewAutomationStatus } from "@t3tools/contracts"; | ||
| 2 | import * as Cause from "effect/Cause"; | 3 | import * as Cause from "effect/Cause"; |
| 3 | import * as Effect from "effect/Effect"; | 4 | import * as Effect from "effect/Effect"; |
| 4 | import * as Exit from "effect/Exit"; | 5 | import * as Exit from "effect/Exit"; |
| ... | @@ -51,4 +52,46 @@ describe("preview IPC methods", () => { | ... | @@ -51,4 +52,46 @@ describe("preview IPC methods", () => { |
| 51 | }, | 52 | }, |
| 52 | ), | 53 | ), |
| 53 | ); | 54 | ); |
| 55 | |||
| 56 | effectIt.effect("returns automation status for long runtime tab ids", () => | ||
| 57 | Effect.gen(function* () { | ||
| 58 | const tabId = | ||
| 59 | `["environment-1","thread:delegated-task:${"a".repeat(120)}",` + | ||
| 60 | `"server-epoch-1","preview-1"]`; | ||
| 61 | const status = { | ||
| 62 | available: false, | ||
| 63 | visible: true, | ||
| 64 | tabId, | ||
| 65 | url: null, | ||
| 66 | title: null, | ||
| 67 | loading: false, | ||
| 68 | }; | ||
| 69 | const manager = PreviewManager.PreviewManager.of({ | ||
| 70 | automationStatus: () => Effect.succeed(status), | ||
| 71 | } as unknown as PreviewManager.PreviewManager["Service"]); | ||
| 72 | |||
| 73 | expect(tabId.length).toBeGreaterThan(128); | ||
| 74 | expect( | ||
| 75 | yield* PreviewIpc.automationStatus | ||
| 76 | .handler({ tabId }) | ||
| 77 | .pipe(Effect.provideService(PreviewManager.PreviewManager, manager)), | ||
| 78 | ).toEqual(status); | ||
| 79 | }), | ||
| 80 | ); | ||
| 81 | |||
| 82 | it("keeps the public automation status tab id limit", () => { | ||
| 83 | const encode = Schema.encodeUnknownSync(PreviewAutomationStatus); | ||
| 84 | const tabId = "t".repeat(129); | ||
| 85 | |||
| 86 | expect(() => | ||
| 87 | encode({ | ||
| 88 | available: false, | ||
| 89 | visible: true, | ||
| 90 | tabId, | ||
| 91 | url: null, | ||
| 92 | title: null, | ||
| 93 | loading: false, | ||
| 94 | }), | ||
| 95 | ).toThrow(); | ||
| 96 | }); | ||
| 54 | }); | 97 | }); |
apps/desktop/src/ipc/methods/preview.ts+2-2| ... | @@ -5,6 +5,7 @@ import { | ... | @@ -5,6 +5,7 @@ import { |
| 5 | DesktopPreviewAutomationEvaluateInputSchema, | 5 | DesktopPreviewAutomationEvaluateInputSchema, |
| 6 | DesktopPreviewAutomationPressInputSchema, | 6 | DesktopPreviewAutomationPressInputSchema, |
| 7 | DesktopPreviewAutomationScrollInputSchema, | 7 | DesktopPreviewAutomationScrollInputSchema, |
| 8 | DesktopPreviewAutomationStatusSchema, | ||
| 8 | DesktopPreviewAutomationTypeInputSchema, | 9 | DesktopPreviewAutomationTypeInputSchema, |
| 9 | DesktopPreviewAutomationWaitForInputSchema, | 10 | DesktopPreviewAutomationWaitForInputSchema, |
| 10 | DesktopPreviewConfigInputSchema, | 11 | DesktopPreviewConfigInputSchema, |
| ... | @@ -20,7 +21,6 @@ import { | ... | @@ -20,7 +21,6 @@ import { |
| 20 | DesktopPreviewWebviewConfigSchema, | 21 | DesktopPreviewWebviewConfigSchema, |
| 21 | PreviewAnnotationSubmissionResultSchema, | 22 | PreviewAnnotationSubmissionResultSchema, |
| 22 | PreviewAutomationSnapshot, | 23 | PreviewAutomationSnapshot, |
| 23 | PreviewAutomationStatus, | ||
| 24 | } from "@t3tools/contracts"; | 24 | } from "@t3tools/contracts"; |
| 25 | import * as Effect from "effect/Effect"; | 25 | import * as Effect from "effect/Effect"; |
| 26 | import * as Schema from "effect/Schema"; | 26 | import * as Schema from "effect/Schema"; |
| ... | @@ -282,7 +282,7 @@ export const copyArtifactToClipboard = DesktopIpc.makeIpcMethod({ | ... | @@ -282,7 +282,7 @@ export const copyArtifactToClipboard = DesktopIpc.makeIpcMethod({ |
| 282 | export const automationStatus = DesktopIpc.makeIpcMethod({ | 282 | export const automationStatus = DesktopIpc.makeIpcMethod({ |
| 283 | channel: IpcChannels.PREVIEW_AUTOMATION_STATUS_CHANNEL, | 283 | channel: IpcChannels.PREVIEW_AUTOMATION_STATUS_CHANNEL, |
| 284 | payload: DesktopPreviewTabInputSchema, | 284 | payload: DesktopPreviewTabInputSchema, |
| 285 | result: PreviewAutomationStatus, | 285 | result: DesktopPreviewAutomationStatusSchema, |
| 286 | handler: Effect.fn("desktop.ipc.preview.automationStatus")(function* ({ tabId }) { | 286 | handler: Effect.fn("desktop.ipc.preview.automationStatus")(function* ({ tabId }) { |
| 287 | const manager = yield* PreviewManager.PreviewManager; | 287 | const manager = yield* PreviewManager.PreviewManager; |
| 288 | return yield* manager.automationStatus(tabId); | 288 | return yield* manager.automationStatus(tabId); |
apps/desktop/src/preview/Manager.ts+2-2| ... | @@ -7,6 +7,7 @@ | ... | @@ -7,6 +7,7 @@ |
| 7 | */ | 7 | */ |
| 8 | import type { | 8 | import type { |
| 9 | DesktopPreviewAnnotationTheme, | 9 | DesktopPreviewAnnotationTheme, |
| 10 | DesktopPreviewAutomationStatus, | ||
| 10 | DesktopPreviewColorScheme, | 11 | DesktopPreviewColorScheme, |
| 11 | DesktopPreviewFavicon, | 12 | DesktopPreviewFavicon, |
| 12 | DesktopPreviewPointerEvent, | 13 | DesktopPreviewPointerEvent, |
| ... | @@ -25,7 +26,6 @@ import type { | ... | @@ -25,7 +26,6 @@ import type { |
| 25 | PreviewAutomationNetworkEntry, | 26 | PreviewAutomationNetworkEntry, |
| 26 | PreviewAutomationScrollInput, | 27 | PreviewAutomationScrollInput, |
| 27 | PreviewAutomationSnapshot, | 28 | PreviewAutomationSnapshot, |
| 28 | PreviewAutomationStatus, | ||
| 29 | PreviewAutomationTypeInput, | 29 | PreviewAutomationTypeInput, |
| 30 | PreviewAutomationWaitForInput, | 30 | PreviewAutomationWaitForInput, |
| 31 | } from "@t3tools/contracts"; | 31 | } from "@t3tools/contracts"; |
| ... | @@ -4089,7 +4089,7 @@ export class PreviewManager extends Context.Service< | ... | @@ -4089,7 +4089,7 @@ export class PreviewManager extends Context.Service< |
| 4089 | ) => Effect.Effect<DesktopPreviewRecordingArtifact, PreviewManagerError>; | 4089 | ) => Effect.Effect<DesktopPreviewRecordingArtifact, PreviewManagerError>; |
| 4090 | readonly automationStatus: ( | 4090 | readonly automationStatus: ( |
| 4091 | tabId: string, | 4091 | tabId: string, |
| 4092 | ) => Effect.Effect<PreviewAutomationStatus, PreviewManagerError>; | 4092 | ) => Effect.Effect<DesktopPreviewAutomationStatus, PreviewManagerError>; |
| 4093 | readonly automationSnapshot: ( | 4093 | readonly automationSnapshot: ( |
| 4094 | tabId: string, | 4094 | tabId: string, |
| 4095 | ) => Effect.Effect<PreviewAutomationSnapshot, PreviewManagerError>; | 4095 | ) => Effect.Effect<PreviewAutomationSnapshot, PreviewManagerError>; |
packages/contracts/src/ipc.ts+7-1| ... | @@ -584,6 +584,12 @@ export const DesktopPreviewTabIdSchema = Schema.String.check(Schema.isTrimmed()) | ... | @@ -584,6 +584,12 @@ export const DesktopPreviewTabIdSchema = Schema.String.check(Schema.isTrimmed()) |
| 584 | Schema.isNonEmpty(), | 584 | Schema.isNonEmpty(), |
| 585 | ); | 585 | ); |
| 586 | 586 | ||
| 587 | export const DesktopPreviewAutomationStatusSchema = Schema.Struct({ | ||
| 588 | ...PreviewAutomationStatus.fields, | ||
| 589 | tabId: Schema.NullOr(DesktopPreviewTabIdSchema), | ||
| 590 | }); | ||
| 591 | export type DesktopPreviewAutomationStatus = typeof DesktopPreviewAutomationStatusSchema.Type; | ||
| 592 | |||
| 587 | export const DesktopPreviewNavStatusSchema = Schema.Union([ | 593 | export const DesktopPreviewNavStatusSchema = Schema.Union([ |
| 588 | Schema.Struct({ kind: Schema.Literal("Idle") }), | 594 | Schema.Struct({ kind: Schema.Literal("Idle") }), |
| 589 | Schema.Struct({ | 595 | Schema.Struct({ |
| ... | @@ -1217,7 +1223,7 @@ export interface DesktopPreviewBridge { | ... | @@ -1217,7 +1223,7 @@ export interface DesktopPreviewBridge { |
| 1217 | onFrame: (listener: (frame: DesktopPreviewRecordingFrame) => void) => () => void; | 1223 | onFrame: (listener: (frame: DesktopPreviewRecordingFrame) => void) => () => void; |
| 1218 | }; | 1224 | }; |
| 1219 | automation: { | 1225 | automation: { |
| 1220 | status: (tabId: string) => Promise<PreviewAutomationStatus>; | 1226 | status: (tabId: string) => Promise<DesktopPreviewAutomationStatus>; |
| 1221 | snapshot: (tabId: string) => Promise<PreviewAutomationSnapshot>; | 1227 | snapshot: (tabId: string) => Promise<PreviewAutomationSnapshot>; |
| 1222 | click: (tabId: string, input: PreviewAutomationClickInput) => Promise<void>; | 1228 | click: (tabId: string, input: PreviewAutomationClickInput) => Promise<void>; |
| 1223 | type: (tabId: string, input: PreviewAutomationTypeInput) => Promise<void>; | 1229 | type: (tabId: string, input: PreviewAutomationTypeInput) => Promise<void>; |