


























@@ -556,23 +556,216 @@ describe("browser config", () => {
556556expect(profile?.cdpIsLoopback).toBe(true);
557557});
558558559-it("prefers cdpPort over stale WebSocket devtools cdpUrl when both are set", () => {
560-const resolved = resolveBrowserConfig({
561-profiles: {
562-"chrome-cdp": {
563-cdpPort: 9222,
564-cdpUrl: "ws://127.0.0.1:9222/devtools/browser/old-stale-id",
565-attachOnly: true,
566-color: "#F59E0B",
559+describe("cdpPort vs cdpUrl port precedence", () => {
560+it("URL with non-default port wins over cdpPort", () => {
561+const resolved = resolveBrowserConfig({
562+profiles: {
563+openclaw: {
564+cdpPort: 18800,
565+cdpUrl: "http://127.0.0.1:9222",
566+color: "#FF4500",
567+driver: "openclaw",
568+},
567569},
568-},
570+});
571+const profile = resolveProfile(resolved, "openclaw");
572+expect(profile?.cdpPort).toBe(9222);
573+expect(profile?.cdpUrl).toBe("http://127.0.0.1:9222");
574+});
575+576+it("URL with explicit default port :80 wins over cdpPort", () => {
577+const resolved = resolveBrowserConfig({
578+profiles: {
579+openclaw: {
580+cdpPort: 18800,
581+cdpUrl: "http://127.0.0.1:80",
582+color: "#FF4500",
583+driver: "openclaw",
584+},
585+},
586+});
587+const profile = resolveProfile(resolved, "openclaw");
588+expect(profile?.cdpPort).toBe(80);
589+expect(profile?.cdpUrl).toBe("http://127.0.0.1:80");
590+});
591+592+it("URL with explicit default port preserves normalized URL details", () => {
593+const resolved = resolveBrowserConfig({
594+profiles: {
595+secure: {
596+cdpPort: 18800,
597+cdpUrl: "https://user:pass@remote-browser.example.com:443/json/version?token=abc#frag",
598+color: "#0066CC",
599+driver: "openclaw",
600+},
601+websocket: {
602+cdpPort: 18800,
603+cdpUrl: "wss://remote-browser.example.com:443/json/version?token=abc",
604+color: "#0066CC",
605+driver: "openclaw",
606+},
607+ipv6: {
608+cdpPort: 18800,
609+cdpUrl: "http://[::1]:80/json/version?token=abc",
610+color: "#0066CC",
611+driver: "openclaw",
612+},
613+},
614+});
615+616+const secure = resolveProfile(resolved, "secure");
617+expect(secure?.cdpPort).toBe(443);
618+expect(secure?.cdpUrl).toBe(
619+"https://user:pass@remote-browser.example.com:443/json/version?token=abc#frag",
620+);
621+622+const websocket = resolveProfile(resolved, "websocket");
623+expect(websocket?.cdpPort).toBe(443);
624+expect(websocket?.cdpUrl).toBe("wss://remote-browser.example.com:443/json/version?token=abc");
625+626+const ipv6 = resolveProfile(resolved, "ipv6");
627+expect(ipv6?.cdpPort).toBe(80);
628+expect(ipv6?.cdpUrl).toBe("http://[::1]:80/json/version?token=abc");
629+});
630+631+it("userinfo colons without a URL port defer to cdpPort", () => {
632+const resolved = resolveBrowserConfig({
633+profiles: {
634+openclaw: {
635+cdpPort: 18800,
636+cdpUrl: "http://user:pass@127.0.0.1/json/version",
637+color: "#FF4500",
638+driver: "openclaw",
639+},
640+},
641+});
642+const profile = resolveProfile(resolved, "openclaw");
643+expect(profile?.cdpPort).toBe(18800);
644+expect(profile?.cdpUrl).toBe("http://user:pass@127.0.0.1:18800/json/version");
645+});
646+647+it("URL without port defers to cdpPort", () => {
648+const resolved = resolveBrowserConfig({
649+profiles: {
650+openclaw: {
651+cdpPort: 18800,
652+cdpUrl: "http://127.0.0.1",
653+color: "#FF4500",
654+driver: "openclaw",
655+},
656+},
657+});
658+const profile = resolveProfile(resolved, "openclaw");
659+expect(profile?.cdpPort).toBe(18800);
660+expect(profile?.cdpUrl).toBe("http://127.0.0.1:18800");
661+});
662+663+it("URL with non-default port, no cdpPort configured", () => {
664+const resolved = resolveBrowserConfig({
665+profiles: {
666+openclaw: {
667+cdpUrl: "http://127.0.0.1:9222",
668+color: "#FF4500",
669+driver: "openclaw",
670+},
671+},
672+});
673+const profile = resolveProfile(resolved, "openclaw");
674+expect(profile?.cdpPort).toBe(9222);
675+expect(profile?.cdpUrl).toBe("http://127.0.0.1:9222");
676+});
677+678+it("URL without port and no cdpPort falls back to protocol default", () => {
679+const resolved = resolveBrowserConfig({
680+profiles: {
681+openclaw: {
682+cdpUrl: "https://remote-browser.example.com",
683+color: "#FF4500",
684+driver: "openclaw",
685+},
686+},
687+});
688+const profile = resolveProfile(resolved, "openclaw");
689+expect(profile?.cdpPort).toBe(443);
690+expect(profile?.cdpUrl).toBe("https://remote-browser.example.com");
691+});
692+693+it("no URL + cdpPort constructs URL from defaults", () => {
694+const resolved = resolveBrowserConfig({
695+profiles: {
696+openclaw: {
697+cdpPort: 9222,
698+color: "#FF4500",
699+driver: "openclaw",
700+},
701+},
702+});
703+const profile = resolveProfile(resolved, "openclaw");
704+expect(profile?.cdpPort).toBe(9222);
705+expect(profile?.cdpUrl).toContain(":9222");
706+});
707+708+it("no URL + no cdpPort throws", () => {
709+const resolved = resolveBrowserConfig({
710+profiles: {
711+bad: {
712+color: "#FF4500",
713+driver: "openclaw",
714+},
715+},
716+});
717+expect(() => resolveProfile(resolved, "bad")).toThrow("must define cdpPort or cdpUrl");
718+});
719+720+it("stale WS devtools URL + cdpPort drops path and uses cdpPort", () => {
721+const resolved = resolveBrowserConfig({
722+profiles: {
723+"chrome-cdp": {
724+cdpPort: 9222,
725+cdpUrl: "ws://127.0.0.1:12345/devtools/browser/old-stale-id",
726+attachOnly: true,
727+color: "#F59E0B",
728+},
729+},
730+});
731+const profile = resolveProfile(resolved, "chrome-cdp");
732+expect(profile?.cdpUrl).toBe("http://127.0.0.1:9222");
733+expect(profile?.cdpPort).toBe(9222);
734+expect(profile?.cdpIsLoopback).toBe(true);
735+expect(profile?.attachOnly).toBe(true);
736+});
737+738+it("IPv6 URL without port defers to cdpPort", () => {
739+const resolved = resolveBrowserConfig({
740+profiles: {
741+openclaw: {
742+cdpPort: 18800,
743+cdpUrl: "http://[::1]",
744+color: "#FF4500",
745+driver: "openclaw",
746+},
747+},
748+});
749+const profile = resolveProfile(resolved, "openclaw");
750+expect(profile?.cdpPort).toBe(18800);
751+expect(profile?.cdpUrl).toBe("http://[::1]:18800");
752+});
753+754+it("IPv6 URL with explicit port wins over cdpPort", () => {
755+const resolved = resolveBrowserConfig({
756+profiles: {
757+openclaw: {
758+cdpPort: 18800,
759+cdpUrl: "http://[::1]:9222",
760+color: "#FF4500",
761+driver: "openclaw",
762+},
763+},
764+});
765+const profile = resolveProfile(resolved, "openclaw");
766+expect(profile?.cdpPort).toBe(9222);
767+expect(profile?.cdpUrl).toBe("http://[::1]:9222");
569768});
570-const profile = resolveProfile(resolved, "chrome-cdp");
571-// cdpPort produces a stable HTTP endpoint; the stale WS session ID is dropped.
572-expect(profile?.cdpUrl).toBe("http://127.0.0.1:9222");
573-expect(profile?.cdpPort).toBe(9222);
574-expect(profile?.cdpIsLoopback).toBe(true);
575-expect(profile?.attachOnly).toBe(true);
576769});
577770578771it("preserves profile host when dropping stale devtools WS path", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。