























@@ -23,7 +23,6 @@ import { startNodeRealtimeAudioBridge } from "./src/realtime-node.js";
2323import { startCommandRealtimeAudioBridge } from "./src/realtime.js";
2424import { normalizeMeetUrl } from "./src/runtime.js";
2525import type { GoogleMeetRuntime } from "./src/runtime.js";
26-import { CREATE_MEET_FROM_BROWSER_SCRIPT } from "./src/transports/chrome.js";
2726import { buildMeetDtmfSequence, normalizeDialInNumber } from "./src/transports/twilio.js";
28272928const voiceCallMocks = vi.hoisted(() => ({
@@ -74,39 +73,6 @@ function captureStdout() {
7473};
7574}
767577-async function runCreateMeetBrowserScript(params: { buttonText: string }) {
78-const location = {
79-href: "https://meet.google.com/new",
80-hostname: "meet.google.com",
81-};
82-const button = {
83-disabled: false,
84-innerText: params.buttonText,
85-textContent: params.buttonText,
86-getAttribute: (name: string) => (name === "aria-label" ? params.buttonText : null),
87-click: vi.fn(() => {
88-location.href = "https://meet.google.com/abc-defg-hij";
89-}),
90-};
91-const document = {
92-title: "Meet",
93-body: {
94-innerText: "Do you want people to hear you in the meeting?",
95-textContent: "Do you want people to hear you in the meeting?",
96-},
97-querySelectorAll: (selector: string) => (selector === "button" ? [button] : []),
98-};
99-vi.stubGlobal("document", document);
100-vi.stubGlobal("location", location);
101-const fn = (0, eval)(`(${CREATE_MEET_FROM_BROWSER_SCRIPT})`) as () => Promise<{
102-meetingUri?: string;
103-manualActionReason?: string;
104-notes?: string[];
105-retryAfterMs?: number;
106-}>;
107-return { button, result: await fn() };
108-}
109-11076type TestBridgeProcess = {
11177stdin?: { write(chunk: unknown): unknown } | null;
11278stdout?: { on(event: "data", listener: (chunk: unknown) => void): unknown } | null;
@@ -769,311 +735,6 @@ describe("google-meet plugin", () => {
769735}
770736});
771737772-it("CLI create prints the new meeting URL", async () => {
773-const fetchMock = vi.fn(async (input: RequestInfo | URL, _init?: RequestInit) => {
774-const url = input instanceof Request ? input.url : input.toString();
775-if (url.includes("oauth2.googleapis.com")) {
776-return new Response(
777-JSON.stringify({
778-access_token: "new-access-token",
779-expires_in: 3600,
780-token_type: "Bearer",
781-}),
782-{ status: 200, headers: { "Content-Type": "application/json" } },
783-);
784-}
785-return new Response(
786-JSON.stringify({
787-name: "spaces/new-space",
788-meetingCode: "new-abcd-xyz",
789-meetingUri: "https://meet.google.com/new-abcd-xyz",
790-}),
791-{ status: 200, headers: { "Content-Type": "application/json" } },
792-);
793-});
794-vi.stubGlobal("fetch", fetchMock);
795-const program = new Command();
796-const stdout = captureStdout();
797-registerGoogleMeetCli({
798- program,
799-config: resolveGoogleMeetConfig({
800-oauth: { clientId: "client-id", refreshToken: "refresh-token" },
801-}),
802-ensureRuntime: async () => ({}) as GoogleMeetRuntime,
803-});
804-805-try {
806-await program.parseAsync(["googlemeet", "create", "--no-join"], { from: "user" });
807-expect(stdout.output()).toContain("meeting uri: https://meet.google.com/new-abcd-xyz");
808-expect(stdout.output()).toContain("space: spaces/new-space");
809-} finally {
810-stdout.restore();
811-}
812-});
813-814-it("can create a Meet through browser fallback without joining when requested", async () => {
815-const { methods, nodesInvoke } = setup(
816-{
817-defaultTransport: "chrome-node",
818-chromeNode: { node: "parallels-macos" },
819-},
820-{
821-nodesInvokeHandler: async (params) => {
822-const proxy = params.params as { path?: string; body?: { url?: string } };
823-if (proxy.path === "/tabs") {
824-return { payload: { result: { tabs: [] } } };
825-}
826-if (proxy.path === "/tabs/open") {
827-return {
828-payload: {
829-result: {
830-targetId: "tab-1",
831-title: "Meet",
832-url: proxy.body?.url,
833-},
834-},
835-};
836-}
837-if (proxy.path === "/act") {
838-return {
839-payload: {
840-result: {
841-ok: true,
842-targetId: "tab-1",
843-result: {
844-meetingUri: "https://meet.google.com/browser-made-url",
845-browserUrl: "https://meet.google.com/browser-made-url",
846-browserTitle: "Meet",
847-},
848-},
849-},
850-};
851-}
852-return { payload: { result: { ok: true } } };
853-},
854-},
855-);
856-const handler = methods.get("googlemeet.create") as
857-| ((ctx: {
858-params: Record<string, unknown>;
859-respond: ReturnType<typeof vi.fn>;
860-}) => Promise<void>)
861-| undefined;
862-const respond = vi.fn();
863-864-await handler?.({ params: { join: false }, respond });
865-866-expect(respond.mock.calls[0]?.[0]).toBe(true);
867-expect(respond.mock.calls[0]?.[1]).toMatchObject({
868-source: "browser",
869-meetingUri: "https://meet.google.com/browser-made-url",
870-joined: false,
871-browser: { nodeId: "node-1", targetId: "tab-1" },
872-});
873-expect(nodesInvoke).toHaveBeenCalledWith(
874-expect.objectContaining({
875-command: "browser.proxy",
876-params: expect.objectContaining({
877-path: "/tabs/open",
878-body: { url: "https://meet.google.com/new" },
879-}),
880-}),
881-);
882-});
883-884-it("creates and joins a Meet through the create tool action by default", async () => {
885-const { tools, nodesInvoke } = setup(
886-{
887-defaultTransport: "chrome-node",
888-defaultMode: "transcribe",
889-chromeNode: { node: "parallels-macos" },
890-},
891-{
892-nodesInvokeHandler: async (params) => {
893-if (params.command === "googlemeet.chrome") {
894-return { payload: { launched: true } };
895-}
896-const proxy = params.params as {
897-path?: string;
898-body?: { url?: string; targetId?: string; fn?: string };
899-};
900-if (proxy.path === "/tabs") {
901-return { payload: { result: { tabs: [] } } };
902-}
903-if (proxy.path === "/tabs/open") {
904-return {
905-payload: {
906-result: {
907-targetId:
908-proxy.body?.url === "https://meet.google.com/new" ? "create-tab" : "join-tab",
909-title: "Meet",
910-url: proxy.body?.url,
911-},
912-},
913-};
914-}
915-if (proxy.path === "/act" && proxy.body?.fn?.includes("meetUrlPattern")) {
916-return {
917-payload: {
918-result: {
919-ok: true,
920-targetId: "create-tab",
921-result: {
922-meetingUri: "https://meet.google.com/new-abcd-xyz",
923-browserUrl: "https://meet.google.com/new-abcd-xyz",
924-browserTitle: "Meet",
925-},
926-},
927-},
928-};
929-}
930-if (proxy.path === "/act") {
931-return {
932-payload: {
933-result: {
934-ok: true,
935-targetId: "join-tab",
936-result: JSON.stringify({
937-inCall: true,
938-micMuted: false,
939-title: "Meet call",
940-url: "https://meet.google.com/new-abcd-xyz",
941-}),
942-},
943-},
944-};
945-}
946-return { payload: { result: { ok: true } } };
947-},
948-},
949-);
950-const tool = tools[0] as {
951-execute: (
952-id: string,
953-params: unknown,
954-) => Promise<{
955-details: { joined?: boolean; meetingUri?: string; join?: { session: { url: string } } };
956-}>;
957-};
958-959-const result = await tool.execute("id", { action: "create" });
960-961-expect(result.details).toMatchObject({
962-source: "browser",
963-joined: true,
964-meetingUri: "https://meet.google.com/new-abcd-xyz",
965-join: { session: { url: "https://meet.google.com/new-abcd-xyz" } },
966-});
967-expect(nodesInvoke).toHaveBeenCalledWith(
968-expect.objectContaining({
969-command: "googlemeet.chrome",
970-params: expect.objectContaining({
971-action: "start",
972-url: "https://meet.google.com/new-abcd-xyz",
973-launch: false,
974-}),
975-}),
976-);
977-});
978-979-it("reuses an existing browser create tab instead of opening duplicates", async () => {
980-const { methods, nodesInvoke } = setup(
981-{
982-defaultTransport: "chrome-node",
983-chromeNode: { node: "parallels-macos" },
984-},
985-{
986-nodesInvokeHandler: async (params) => {
987-const proxy = params.params as { path?: string; body?: { targetId?: string } };
988-if (proxy.path === "/tabs") {
989-return {
990-payload: {
991-result: {
992-tabs: [
993-{
994-targetId: "existing-create-tab",
995-title: "Meet",
996-url: "https://meet.google.com/new",
997-},
998-],
999-},
1000-},
1001-};
1002-}
1003-if (proxy.path === "/tabs/focus") {
1004-return { payload: { result: { ok: true } } };
1005-}
1006-if (proxy.path === "/act") {
1007-return {
1008-payload: {
1009-result: {
1010-ok: true,
1011-targetId: proxy.body?.targetId ?? "existing-create-tab",
1012-result: {
1013-meetingUri: "https://meet.google.com/reu-sedx-tab",
1014-browserUrl: "https://meet.google.com/reu-sedx-tab",
1015-browserTitle: "Meet",
1016-},
1017-},
1018-},
1019-};
1020-}
1021-throw new Error(`unexpected browser proxy path ${proxy.path}`);
1022-},
1023-},
1024-);
1025-const handler = methods.get("googlemeet.create") as
1026-| ((ctx: {
1027-params: Record<string, unknown>;
1028-respond: ReturnType<typeof vi.fn>;
1029-}) => Promise<void>)
1030-| undefined;
1031-const respond = vi.fn();
1032-1033-await handler?.({ params: { join: false }, respond });
1034-1035-expect(respond.mock.calls[0]?.[0]).toBe(true);
1036-expect(respond.mock.calls[0]?.[1]).toMatchObject({
1037-source: "browser",
1038-meetingUri: "https://meet.google.com/reu-sedx-tab",
1039-browser: { nodeId: "node-1", targetId: "existing-create-tab" },
1040-});
1041-expect(nodesInvoke).toHaveBeenCalledWith(
1042-expect.objectContaining({
1043-params: expect.objectContaining({
1044-path: "/tabs/focus",
1045-body: { targetId: "existing-create-tab" },
1046-}),
1047-}),
1048-);
1049-expect(nodesInvoke).not.toHaveBeenCalledWith(
1050-expect.objectContaining({
1051-params: expect.objectContaining({ path: "/tabs/open" }),
1052-}),
1053-);
1054-});
1055-1056-it.each([
1057-["Use microphone", "Accepted Meet microphone prompt with browser automation."],
1058-[
1059-"Continue without microphone",
1060-"Continued through Meet microphone prompt with browser automation.",
1061-],
1062-])(
1063-"uses browser automation for Meet's %s choice during browser creation",
1064-async (buttonText, note) => {
1065-const { button, result } = await runCreateMeetBrowserScript({ buttonText });
1066-1067-expect(result).toMatchObject({
1068-retryAfterMs: 1000,
1069-notes: [note],
1070-});
1071-expect(button.click).toHaveBeenCalledTimes(1);
1072-expect(result.meetingUri).toBeUndefined();
1073-expect(result.manualActionReason).toBeUndefined();
1074-},
1075-);
1076-1077738it("launches Chrome after the BlackHole check", async () => {
1078739const originalPlatform = process.platform;
1079740Object.defineProperty(process, "platform", { value: "darwin" });
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。