OpenHands/frontend/__tests__/build-websocket-url.test.ts
sp.wack 531683abae
feat(frontend): V1 conversation API (PARTIAL) (#11336)
Co-authored-by: Hiep Le <69354317+hieptl@users.noreply.github.com>
Co-authored-by: Tim O'Farrell <tofarr@gmail.com>
2025-10-20 20:57:40 +04:00

188 lines
5.3 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { buildWebSocketUrl } from "#/utils/websocket-url";
describe("buildWebSocketUrl", () => {
afterEach(() => {
vi.unstubAllGlobals();
});
describe("Basic URL construction", () => {
it("should build WebSocket URL with conversation ID and URL", () => {
vi.stubGlobal("location", {
protocol: "http:",
host: "localhost:3000",
});
const result = buildWebSocketUrl(
"conv-123",
"http://localhost:8080/api/conversations/conv-123",
);
expect(result).toBe("ws://localhost:8080/sockets/events/conv-123");
});
it("should use wss:// protocol when window.location.protocol is https:", () => {
vi.stubGlobal("location", {
protocol: "https:",
host: "localhost:3000",
});
const result = buildWebSocketUrl(
"conv-123",
"https://example.com:8080/api/conversations/conv-123",
);
expect(result).toBe("wss://example.com:8080/sockets/events/conv-123");
});
it("should extract host and port from conversation URL", () => {
vi.stubGlobal("location", {
protocol: "http:",
host: "localhost:3000",
});
const result = buildWebSocketUrl(
"conv-456",
"http://agent-server.com:9000/api/conversations/conv-456",
);
expect(result).toBe("ws://agent-server.com:9000/sockets/events/conv-456");
});
});
describe("Query parameters handling", () => {
beforeEach(() => {
vi.stubGlobal("location", {
protocol: "http:",
host: "localhost:3000",
});
});
it("should not include query parameters in the URL (handled by useWebSocket hook)", () => {
const result = buildWebSocketUrl(
"conv-123",
"http://localhost:8080/api/conversations/conv-123",
);
expect(result).toBe("ws://localhost:8080/sockets/events/conv-123");
expect(result).not.toContain("?");
expect(result).not.toContain("session_api_key");
});
});
describe("Fallback to window.location.host", () => {
it("should use window.location.host when conversation URL is null", () => {
vi.stubGlobal("location", {
protocol: "http:",
host: "fallback-host:4000",
});
const result = buildWebSocketUrl("conv-123", null);
expect(result).toBe("ws://fallback-host:4000/sockets/events/conv-123");
});
it("should use window.location.host when conversation URL is undefined", () => {
vi.stubGlobal("location", {
protocol: "http:",
host: "fallback-host:4000",
});
const result = buildWebSocketUrl("conv-123", undefined);
expect(result).toBe("ws://fallback-host:4000/sockets/events/conv-123");
});
it("should use window.location.host when conversation URL is relative path", () => {
vi.stubGlobal("location", {
protocol: "http:",
host: "fallback-host:4000",
});
const result = buildWebSocketUrl(
"conv-123",
"/api/conversations/conv-123",
);
expect(result).toBe("ws://fallback-host:4000/sockets/events/conv-123");
});
it("should use window.location.host when conversation URL is invalid", () => {
vi.stubGlobal("location", {
protocol: "http:",
host: "fallback-host:4000",
});
const result = buildWebSocketUrl("conv-123", "not-a-valid-url");
expect(result).toBe("ws://fallback-host:4000/sockets/events/conv-123");
});
});
describe("Edge cases", () => {
beforeEach(() => {
vi.stubGlobal("location", {
protocol: "http:",
host: "localhost:3000",
});
});
it("should return null when conversationId is undefined", () => {
const result = buildWebSocketUrl(
undefined,
"http://localhost:8080/api/conversations/conv-123",
);
expect(result).toBeNull();
});
it("should return null when conversationId is empty string", () => {
const result = buildWebSocketUrl(
"",
"http://localhost:8080/api/conversations/conv-123",
);
expect(result).toBeNull();
});
it("should handle conversation URLs with non-standard ports", () => {
const result = buildWebSocketUrl(
"conv-123",
"http://example.com:12345/api/conversations/conv-123",
);
expect(result).toBe("ws://example.com:12345/sockets/events/conv-123");
});
it("should handle conversation URLs without port (default port)", () => {
const result = buildWebSocketUrl(
"conv-123",
"http://example.com/api/conversations/conv-123",
);
expect(result).toBe("ws://example.com/sockets/events/conv-123");
});
it("should handle conversation IDs with special characters", () => {
const result = buildWebSocketUrl(
"conv-123-abc_def",
"http://localhost:8080/api/conversations/conv-123-abc_def",
);
expect(result).toBe(
"ws://localhost:8080/sockets/events/conv-123-abc_def",
);
});
it("should build URL without query parameters", () => {
const result = buildWebSocketUrl(
"conv-123",
"http://localhost:8080/api/conversations/conv-123",
);
expect(result).toBe("ws://localhost:8080/sockets/events/conv-123");
expect(result).not.toContain("?");
});
});
});