feat: initial commit - Jhonny Editor
- Adicionado estrutura completa do projeto - Configurado MCP server para Premiere Pro - Adicionado documentação e skills - Configurado Gitignore para o projeto
This commit is contained in:
+446
@@ -0,0 +1,446 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { UxpWebSocketBridge } from "../../src/bridge/uxp-websocket-bridge.js";
|
||||
import { getUxpTools } from "../../src/tools/uxp.js";
|
||||
|
||||
const ADVANCED_WORKFLOW_TOOLS = [
|
||||
"inspect_project_selection_uxp",
|
||||
"inspect_project_tree_uxp",
|
||||
"manage_markers_uxp",
|
||||
"apply_beat_markers_uxp",
|
||||
"create_silence_cut_source_stringout_uxp",
|
||||
"organize_project_items_uxp",
|
||||
"manage_sequence_settings_uxp",
|
||||
"manage_sequence_display_format_uxp",
|
||||
"import_project_media_uxp",
|
||||
"automate_effect_parameters_uxp",
|
||||
"transform_track_item_uxp",
|
||||
"edit_timeline_uxp",
|
||||
"manage_sequences_uxp",
|
||||
"encode_media_uxp",
|
||||
] as const;
|
||||
|
||||
describe("advanced stable UXP workflow MCP catalog", () => {
|
||||
it("publishes fourteen advanced tools with closed, bounded schemas", () => {
|
||||
const bridge = { request: vi.fn(), getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge) as Record<string, { parameters: Record<string, unknown> }>;
|
||||
|
||||
expect(Object.keys(tools)).toEqual(expect.arrayContaining(ADVANCED_WORKFLOW_TOOLS));
|
||||
expect(ADVANCED_WORKFLOW_TOOLS).toHaveLength(14);
|
||||
for (const name of ADVANCED_WORKFLOW_TOOLS) {
|
||||
const parameters = tools[name].parameters;
|
||||
expect(parameters).toMatchObject({
|
||||
type: "object",
|
||||
additionalProperties: false,
|
||||
});
|
||||
if (name !== "inspect_project_tree_uxp") {
|
||||
expect(parameters).toMatchObject({
|
||||
required: expect.arrayContaining([name === "apply_beat_markers_uxp" ? "beat_times_seconds" : name === "create_silence_cut_source_stringout_uxp" ? "source_project_item_id" : "action"]),
|
||||
});
|
||||
}
|
||||
}
|
||||
expect(tools.inspect_project_selection_uxp.parameters).toMatchObject({
|
||||
properties: { action: { enum: ["views", "selection"] }, view_id: { maxLength: 128 } },
|
||||
});
|
||||
expect(tools.inspect_project_tree_uxp.parameters).toMatchObject({
|
||||
additionalProperties: false,
|
||||
properties: { max_items: { minimum: 1, maximum: 512 }, max_depth: { minimum: 0, maximum: 16 } },
|
||||
});
|
||||
expect(tools.manage_markers_uxp.parameters).toMatchObject({
|
||||
properties: {
|
||||
action: { enum: ["inspect", "add", "update", "remove", "remove_many"] },
|
||||
marker_snapshots: {
|
||||
minItems: 1, maxItems: 128,
|
||||
items: { required: ["marker_guid", "expected_name", "expected_start_seconds", "expected_duration_seconds"] },
|
||||
},
|
||||
confirm_destructive: { type: "boolean" },
|
||||
},
|
||||
});
|
||||
expect(tools.manage_sequence_display_format_uxp.parameters).toMatchObject({
|
||||
properties: {
|
||||
action: { enum: ["inspect", "update"] },
|
||||
expected_sequence_guid: { maxLength: 128 },
|
||||
expected_display_formats: { required: ["audio_display_format", "video_display_format"] },
|
||||
updates: { additionalProperties: false },
|
||||
},
|
||||
});
|
||||
expect(tools.import_project_media_uxp.parameters).toMatchObject({
|
||||
required: ["action", "confirm_non_undoable"],
|
||||
properties: { paths: { maxItems: 100 }, confirm_non_undoable: { type: "boolean" } },
|
||||
});
|
||||
expect(tools.automate_effect_parameters_uxp.parameters).toMatchObject({
|
||||
properties: {
|
||||
action: { enum: ["inspect", "inspect_point_value", "inspect_point_displacement", "set_point_value", "inspect_color_value", "set_color_value", "inspect_keyframe", "set_value", "add_keyframe", "remove_keyframe", "remove_keyframe_range", "set_interpolation", "inspect_time_varying", "set_time_varying"] },
|
||||
point: { required: ["x", "y"], additionalProperties: false },
|
||||
expected_point_snapshot: { required: ["project_id", "sequence_id", "media_type", "track_index", "clip_index", "component_index", "component_id", "param_index", "param_name", "time_varying", "point"], additionalProperties: false },
|
||||
color: { required: ["red", "green", "blue", "alpha"], additionalProperties: false },
|
||||
expected_color_snapshot: { required: ["project_id", "sequence_id", "media_type", "track_index", "clip_index", "component_index", "component_id", "param_index", "param_name", "time_varying", "color"], additionalProperties: false },
|
||||
expected_sequence_id: { maxLength: 128 }, expected_time_varying: { type: "boolean" },
|
||||
expected_keyframe_times_seconds: { maxItems: 256, uniqueItems: true },
|
||||
keyframe_direction: { enum: ["at", "next", "previous", "nearest"] },
|
||||
time_varying: { type: "boolean" }, confirm_disable_time_varying: { type: "boolean" },
|
||||
},
|
||||
});
|
||||
expect(tools.encode_media_uxp.parameters).toMatchObject({
|
||||
properties: {
|
||||
action: { enum: ["preflight", "jobs", "wait", "sequence", "project_item", "file"] },
|
||||
job_id: { pattern: expect.any(String) },
|
||||
timeout_ms: { maximum: 60000 },
|
||||
output_file: { maxLength: 4096 },
|
||||
confirm_external_write: { type: "boolean" },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("maps guarded parameter keyframe and animation-mode reads to their exact UXP commands", async () => {
|
||||
const request = vi.fn().mockResolvedValue({ outcome: "verified" });
|
||||
const bridge = { request, getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge);
|
||||
const target = {
|
||||
media_type: "video", track_index: 0, clip_index: 1, component_index: 2, param_index: 3,
|
||||
expected_component_id: "ADBE Opacity", expected_param_name: "Opacity",
|
||||
};
|
||||
|
||||
await tools.automate_effect_parameters_uxp.handler({ action: "inspect_keyframe", ...target, time_seconds: 4, keyframe_direction: "next" });
|
||||
await tools.automate_effect_parameters_uxp.handler({ action: "inspect_keyframe", ...target, time_seconds: 4, end_seconds: 6, keyframe_direction: "nearest" });
|
||||
await tools.automate_effect_parameters_uxp.handler({ action: "inspect_time_varying", ...target, time_seconds: 4 });
|
||||
await tools.automate_effect_parameters_uxp.handler({
|
||||
action: "set_time_varying", ...target, expected_sequence_id: "sequence-1", expected_time_varying: true,
|
||||
expected_keyframe_times_seconds: [1, 2], time_varying: false, confirm_disable_time_varying: true,
|
||||
operation_id: "parameter-animation-op",
|
||||
});
|
||||
|
||||
expect(request.mock.calls).toEqual([
|
||||
["parameters.keyframe.inspect", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedComponentId: "ADBE Opacity", expectedParamName: "Opacity", timeSeconds: 4, direction: "next",
|
||||
}],
|
||||
["parameters.keyframe.inspect", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedComponentId: "ADBE Opacity", expectedParamName: "Opacity", timeSeconds: 4, direction: "nearest", endSeconds: 6,
|
||||
}],
|
||||
["parameters.timeVarying.inspect", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedComponentId: "ADBE Opacity", expectedParamName: "Opacity",
|
||||
}],
|
||||
["parameters.timeVarying.set", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedSequenceId: "sequence-1", expectedComponentId: "ADBE Opacity", expectedParamName: "Opacity",
|
||||
expectedTimeVarying: true, expectedKeyframeTimesSeconds: [1, 2], timeVarying: false,
|
||||
confirmDisableTimeVarying: true, operationId: "parameter-animation-op",
|
||||
}],
|
||||
]);
|
||||
});
|
||||
|
||||
it("maps guarded static PointF inspection and update actions to the exact UXP commands", async () => {
|
||||
const request = vi.fn().mockResolvedValue({ outcome: "verified" });
|
||||
const bridge = { request, getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge);
|
||||
const target = {
|
||||
media_type: "video", track_index: 0, clip_index: 1, component_index: 2, param_index: 3,
|
||||
expected_component_id: "ADBE Motion", expected_param_name: "Position",
|
||||
};
|
||||
const expectedPointSnapshot = {
|
||||
project_id: "project-1", sequence_id: "sequence-1", media_type: "video", track_index: 0, clip_index: 1,
|
||||
component_index: 2, component_id: "ADBE Motion", param_index: 3, param_name: "Position", time_varying: false,
|
||||
point: { x: 960, y: 540 },
|
||||
};
|
||||
|
||||
await tools.automate_effect_parameters_uxp.handler({ action: "inspect_point_value", ...target });
|
||||
await tools.automate_effect_parameters_uxp.handler({
|
||||
action: "set_point_value", ...target, expected_point_snapshot: expectedPointSnapshot,
|
||||
point: { x: 1100, y: 600 }, confirm_set_point: true, operation_id: "point-tool-op",
|
||||
});
|
||||
|
||||
expect(request.mock.calls).toEqual([
|
||||
["parameters.point.inspect", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedComponentId: "ADBE Motion", expectedParamName: "Position",
|
||||
}],
|
||||
["parameters.point.set", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedComponentId: "ADBE Motion", expectedParamName: "Position", point: { x: 1100, y: 600 },
|
||||
expectedSnapshot: {
|
||||
projectId: "project-1", sequenceId: "sequence-1", mediaType: "video", trackIndex: 0, clipIndex: 1,
|
||||
componentIndex: 2, componentId: "ADBE Motion", paramIndex: 3, paramName: "Position", timeVarying: false,
|
||||
point: { x: 960, y: 540 },
|
||||
},
|
||||
confirmSetPoint: true, operationId: "point-tool-op",
|
||||
}],
|
||||
]);
|
||||
});
|
||||
|
||||
it("maps bounded native PointF displacement inspection to its exact UXP command", async () => {
|
||||
const request = vi.fn().mockResolvedValue({ straightLineDistance: 5 });
|
||||
const bridge = { request, getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge);
|
||||
await tools.automate_effect_parameters_uxp.handler({
|
||||
action: "inspect_point_displacement", media_type: "video", track_index: 0, clip_index: 1,
|
||||
component_index: 2, param_index: 3, expected_component_id: "ADBE Motion", expected_param_name: "Position",
|
||||
time_seconds: 2, end_seconds: 5,
|
||||
});
|
||||
expect(request).toHaveBeenCalledWith("parameters.point.displacement.inspect", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedComponentId: "ADBE Motion", expectedParamName: "Position", startSeconds: 2, endSeconds: 5,
|
||||
});
|
||||
});
|
||||
|
||||
it("maps guarded static Color inspection and update actions to the exact UXP commands", async () => {
|
||||
const request = vi.fn().mockResolvedValue({ outcome: "verified" });
|
||||
const bridge = { request, getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge);
|
||||
const target = {
|
||||
media_type: "video", track_index: 0, clip_index: 1, component_index: 2, param_index: 3,
|
||||
expected_component_id: "ADBE Lumetri", expected_param_name: "Tint",
|
||||
};
|
||||
const expectedColorSnapshot = {
|
||||
project_id: "project-1", sequence_id: "sequence-1", media_type: "video", track_index: 0, clip_index: 1,
|
||||
component_index: 2, component_id: "ADBE Lumetri", param_index: 3, param_name: "Tint", time_varying: false,
|
||||
color: { red: 0.1, green: 0.2, blue: 0.3, alpha: 1 },
|
||||
};
|
||||
|
||||
await tools.automate_effect_parameters_uxp.handler({ action: "inspect_color_value", ...target });
|
||||
await tools.automate_effect_parameters_uxp.handler({
|
||||
action: "set_color_value", ...target, expected_color_snapshot: expectedColorSnapshot,
|
||||
color: { red: 0.9, green: 0.8, blue: 0.7, alpha: 0.6 }, confirm_set_color: true, operation_id: "color-tool-op",
|
||||
});
|
||||
|
||||
expect(request.mock.calls).toEqual([
|
||||
["parameters.color.inspect", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedComponentId: "ADBE Lumetri", expectedParamName: "Tint",
|
||||
}],
|
||||
["parameters.color.set", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedComponentId: "ADBE Lumetri", expectedParamName: "Tint",
|
||||
color: { red: 0.9, green: 0.8, blue: 0.7, alpha: 0.6 },
|
||||
expectedSnapshot: {
|
||||
projectId: "project-1", sequenceId: "sequence-1", mediaType: "video", trackIndex: 0, clipIndex: 1,
|
||||
componentIndex: 2, componentId: "ADBE Lumetri", paramIndex: 3, paramName: "Tint", timeVarying: false,
|
||||
color: { red: 0.1, green: 0.2, blue: 0.3, alpha: 1 },
|
||||
},
|
||||
confirmSetColor: true, operationId: "color-tool-op",
|
||||
}],
|
||||
]);
|
||||
});
|
||||
|
||||
it("maps every consolidated tool to its exact camel-case UXP command contract", async () => {
|
||||
const request = vi.fn().mockResolvedValue({ outcome: "verified" });
|
||||
const bridge = { request, getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge);
|
||||
|
||||
await tools.inspect_project_selection_uxp.handler({ action: "selection", view_id: "view-1" });
|
||||
await tools.inspect_project_tree_uxp.handler({ max_items: 12, max_depth: 3 });
|
||||
await tools.manage_markers_uxp.handler({
|
||||
action: "update", owner_type: "project_item", project_item_id: "clip-1",
|
||||
marker_guid: "marker-1", expected_name: "Old", name: "New", color_index: 3,
|
||||
operation_id: "marker-op",
|
||||
});
|
||||
await tools.manage_markers_uxp.handler({
|
||||
action: "remove_many", owner_type: "sequence", sequence_id: "sequence-1", marker_guid: "single-marker", expected_name: "Ignored", confirm_destructive: true,
|
||||
marker_snapshots: [{ marker_guid: "marker-1", expected_name: "Old", expected_start_seconds: 1, expected_duration_seconds: 0 }],
|
||||
operation_id: "marker-batch-op",
|
||||
});
|
||||
await tools.apply_beat_markers_uxp.handler({
|
||||
beat_times_seconds: [0.5, 1, 1.5], sequence_id: "sequence-1", offset_seconds: 2,
|
||||
name_prefix: "Downbeat", comments: "Detected beat grid", operation_id: "beat-grid-op",
|
||||
});
|
||||
await tools.create_silence_cut_source_stringout_uxp.handler({
|
||||
source_project_item_id: "clip-1", sequence_name: "Interview Tight", duration_seconds: 10,
|
||||
frame_rate: 30, silence_ranges: [{ start_seconds: 2, end_seconds: 4 }],
|
||||
keep_handle_frames: 0, confirm_non_undoable: true, operation_id: "silence-op",
|
||||
});
|
||||
await tools.organize_project_items_uxp.handler({
|
||||
action: "create_smart_bin", parent_bin_id: "bin-1", name: "Selects",
|
||||
search_query: "rating:5", operation_id: "bin-op",
|
||||
});
|
||||
await tools.manage_sequence_settings_uxp.handler({
|
||||
action: "update", sequence_id: "sequence-1",
|
||||
updates: { maximum_bit_depth: true, video_frame_rate: 24, video_width: 1920 },
|
||||
operation_id: "settings-op",
|
||||
});
|
||||
await tools.manage_sequence_display_format_uxp.handler({
|
||||
action: "update", sequence_id: "sequence-1", expected_sequence_guid: "sequence-1",
|
||||
expected_display_formats: { audio_display_format: 1, video_display_format: 20 },
|
||||
updates: { audio_display_format: 2, video_display_format: 26 }, operation_id: "display-format-op",
|
||||
});
|
||||
await tools.import_project_media_uxp.handler({
|
||||
action: "ae_comps", aep_path: "D:/Approved/graphics.aep",
|
||||
comp_names: ["Lower Third"], target_bin_id: "bin-1",
|
||||
confirm_non_undoable: true, operation_id: "import-op",
|
||||
});
|
||||
await tools.automate_effect_parameters_uxp.handler({
|
||||
action: "add_keyframe", media_type: "video", track_index: 0, clip_index: 1,
|
||||
component_index: 2, param_index: 3, expected_component_id: "ADBE Opacity",
|
||||
expected_param_name: "Opacity", value: 75, time_seconds: 2.5,
|
||||
operation_id: "keyframe-op",
|
||||
});
|
||||
await tools.transform_track_item_uxp.handler({
|
||||
action: "update", media_type: "audio", track_index: 1, clip_index: 2,
|
||||
expected_start_seconds: 10, expected_end_seconds: 20, move_by_seconds: 1.5,
|
||||
disabled: false, operation_id: "track-op",
|
||||
});
|
||||
await tools.edit_timeline_uxp.handler({
|
||||
action: "insert_mogrt_path", file_path: "D:/Approved/title.mogrt",
|
||||
time_seconds: 4, video_track_index: 2, audio_track_index: 0,
|
||||
confirm_non_undoable: true, operation_id: "timeline-op",
|
||||
});
|
||||
await tools.manage_sequences_uxp.handler({
|
||||
action: "create_from_media", name: "Assembly", project_item_ids: ["clip-1", "clip-2"],
|
||||
target_bin_id: "bin-1", confirm_non_undoable: true, operation_id: "sequence-op",
|
||||
});
|
||||
await tools.encode_media_uxp.handler({
|
||||
action: "file", file_path: "D:/Approved/input.mov", output_file: "D:/Approved/output.mp4",
|
||||
preset_file: "D:/Approved/h264.epr", in_seconds: 1, out_seconds: 8, work_area: 0,
|
||||
remove_upon_completion: true, start_queue_immediately: false,
|
||||
confirm_external_write: true, operation_id: "encode-op",
|
||||
});
|
||||
await tools.encode_media_uxp.handler({
|
||||
action: "wait", job_id: "encode-op", timeout_ms: 5000,
|
||||
});
|
||||
await tools.encode_media_uxp.handler({ action: "jobs", limit: 3 });
|
||||
await tools.encode_media_uxp.handler({ action: "wait", job_id: "encode-op" });
|
||||
|
||||
expect(request.mock.calls).toEqual([
|
||||
["projectSelection.inspect", { viewId: "view-1" }],
|
||||
["projectTree.inspect", { maxItems: 12, maxDepth: 3 }],
|
||||
["markers.update", {
|
||||
ownerType: "projectItem", projectItemId: "clip-1", markerGuid: "marker-1",
|
||||
expectedName: "Old", name: "New", colorIndex: 3, operationId: "marker-op",
|
||||
}],
|
||||
["markers.removeMany", {
|
||||
ownerType: "sequence", sequenceId: "sequence-1",
|
||||
markerSnapshots: [{ markerGuid: "marker-1", expectedName: "Old", expectedStartSeconds: 1, expectedDurationSeconds: 0 }],
|
||||
confirmDestructive: true, operationId: "marker-batch-op",
|
||||
}],
|
||||
["markers.addBeatGrid", {
|
||||
beatTimesSeconds: [0.5, 1, 1.5], sequenceId: "sequence-1", offsetSeconds: 2,
|
||||
namePrefix: "Downbeat", comments: "Detected beat grid", operationId: "beat-grid-op",
|
||||
}],
|
||||
["silence.deriveSequence", {
|
||||
sourceProjectItemId: "clip-1", name: "Interview Tight",
|
||||
keepRanges: [
|
||||
{ startFrame: 0, endFrame: 60, startSeconds: 0, endSeconds: 2 },
|
||||
{ startFrame: 120, endFrame: 300, startSeconds: 4, endSeconds: 10 },
|
||||
],
|
||||
confirmNonUndoable: true, operationId: "silence-op",
|
||||
}],
|
||||
["bins.createSmart", {
|
||||
parentBinId: "bin-1", name: "Selects", searchQuery: "rating:5", operationId: "bin-op",
|
||||
}],
|
||||
["sequenceSettings.update", {
|
||||
sequenceId: "sequence-1",
|
||||
updates: { maximumBitDepth: true, videoFrameRate: 24, videoWidth: 1920 },
|
||||
operationId: "settings-op",
|
||||
}],
|
||||
["sequence.displayFormat.update", {
|
||||
sequenceId: "sequence-1", expectedSequenceGuid: "sequence-1",
|
||||
expectedDisplayFormats: { audioDisplayFormat: 1, videoDisplayFormat: 20 },
|
||||
updates: { audioDisplayFormat: 2, videoDisplayFormat: 26 }, operationId: "display-format-op",
|
||||
}],
|
||||
["project.import", {
|
||||
mode: "aeComps", aepPath: "D:/Approved/graphics.aep", compNames: ["Lower Third"],
|
||||
targetBinId: "bin-1", confirmNonUndoable: true, operationId: "import-op",
|
||||
}],
|
||||
["parameters.keyframeAdd", {
|
||||
mediaType: "video", trackIndex: 0, clipIndex: 1, componentIndex: 2, paramIndex: 3,
|
||||
expectedComponentId: "ADBE Opacity", expectedParamName: "Opacity", timeSeconds: 2.5,
|
||||
value: 75, operationId: "keyframe-op",
|
||||
}],
|
||||
["trackItem.update", {
|
||||
mediaType: "audio", trackIndex: 1, clipIndex: 2, expectedStartSeconds: 10,
|
||||
expectedEndSeconds: 20, moveBySeconds: 1.5, disabled: false, operationId: "track-op",
|
||||
}],
|
||||
["timeline.mogrtPath", {
|
||||
timeSeconds: 4, videoTrackIndex: 2, audioTrackIndex: 0,
|
||||
filePath: "D:/Approved/title.mogrt", confirmNonUndoable: true,
|
||||
operationId: "timeline-op",
|
||||
}],
|
||||
["sequences.createFromMedia", {
|
||||
name: "Assembly", projectItemIds: ["clip-1", "clip-2"], targetBinId: "bin-1",
|
||||
confirmNonUndoable: true, operationId: "sequence-op",
|
||||
}],
|
||||
["encoder.file", {
|
||||
filePath: "D:/Approved/input.mov", outputFile: "D:/Approved/output.mp4",
|
||||
presetFile: "D:/Approved/h264.epr", inSeconds: 1, outSeconds: 8, workArea: 0,
|
||||
removeUponCompletion: true, startQueueImmediately: false,
|
||||
confirmExternalWrite: true, operationId: "encode-op",
|
||||
}],
|
||||
["encoder.wait", { jobId: "encode-op", timeoutMs: 5000 }, { minimumTimeoutMs: 10000 }],
|
||||
["encoder.jobs", { limit: 3 }],
|
||||
["encoder.wait", { jobId: "encode-op" }, { minimumTimeoutMs: 5000 }],
|
||||
]);
|
||||
});
|
||||
|
||||
it("rejects unknown public actions without contacting Premiere", async () => {
|
||||
const request = vi.fn();
|
||||
const bridge = { request, getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge);
|
||||
const results = await Promise.all([
|
||||
tools.inspect_project_selection_uxp.handler({ action: "destroy_everything" }),
|
||||
tools.manage_markers_uxp.handler({ action: "destroy_everything" }),
|
||||
tools.organize_project_items_uxp.handler({ action: "destroy_everything" }),
|
||||
tools.transform_track_item_uxp.handler({ action: "destroy_everything" }),
|
||||
]);
|
||||
|
||||
expect(results).toEqual(Array.from({ length: 4 }, () => ({
|
||||
success: false,
|
||||
error: "Unsupported workflow action: destroy_everything",
|
||||
})));
|
||||
expect(request).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects unreviewed or duplicate marker batch removal before contacting Premiere", async () => {
|
||||
const request = vi.fn();
|
||||
const bridge = { request, getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge);
|
||||
const snapshot = { marker_guid: "marker-1", expected_name: "Beat", expected_start_seconds: 0, expected_duration_seconds: 0 };
|
||||
|
||||
await expect(tools.manage_markers_uxp.handler({ action: "remove_many", marker_snapshots: [snapshot] })).resolves.toMatchObject({
|
||||
success: false, error: expect.stringContaining("confirm_destructive=true"),
|
||||
});
|
||||
await expect(tools.manage_markers_uxp.handler({
|
||||
action: "remove_many", confirm_destructive: true, marker_snapshots: [snapshot, snapshot],
|
||||
})).resolves.toMatchObject({ success: false, error: expect.stringContaining("duplicate marker_guid") });
|
||||
await expect(tools.manage_markers_uxp.handler({
|
||||
action: "remove_many", confirm_destructive: true, marker_snapshots: [null],
|
||||
})).resolves.toMatchObject({ success: false, error: expect.stringContaining("marker_snapshots[0] must be an object") });
|
||||
expect(request).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("normalizes Error and non-Error bridge rejections", async () => {
|
||||
const request = vi.fn()
|
||||
.mockRejectedValueOnce(new Error("Premiere unavailable"))
|
||||
.mockRejectedValueOnce("transport closed");
|
||||
const bridge = { request, getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge);
|
||||
|
||||
await expect(tools.inspect_project_selection_uxp.handler({ action: "views" })).resolves.toEqual({
|
||||
success: false,
|
||||
error: "Premiere unavailable",
|
||||
});
|
||||
await expect(tools.manage_sequence_settings_uxp.handler({ action: "get" })).resolves.toEqual({
|
||||
success: false,
|
||||
error: "transport closed",
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects missing actions in mapped dispatchers before bridge access", async () => {
|
||||
const request = vi.fn();
|
||||
const bridge = { request, getState: vi.fn() } as unknown as UxpWebSocketBridge;
|
||||
const tools = getUxpTools(bridge);
|
||||
|
||||
const results = await Promise.all([
|
||||
tools.import_project_media_uxp.handler({ confirm_non_undoable: true }),
|
||||
tools.automate_effect_parameters_uxp.handler({}),
|
||||
tools.edit_timeline_uxp.handler({}),
|
||||
tools.manage_sequences_uxp.handler({}),
|
||||
tools.encode_media_uxp.handler({}),
|
||||
]);
|
||||
|
||||
expect(results).toEqual(Array.from({ length: 5 }, () => ({
|
||||
success: false,
|
||||
error: "Unsupported workflow action: undefined",
|
||||
})));
|
||||
expect(request).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user