Skip to content

Commit 131974a

Browse files
committed
Merge remote-tracking branch 'origin/test/hourly-20260328-1414' into test/consolidate-18-test-prs
2 parents abb3c40 + 72819b1 commit 131974a

2 files changed

Lines changed: 229 additions & 0 deletions

File tree

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { describe, test, expect } from "bun:test"
2+
import { containerToConfig } from "../../src/altimate/native/connections/docker-discovery"
3+
import type { DockerContainer } from "../../src/altimate/native/types"
4+
5+
describe("containerToConfig: full container with all fields", () => {
6+
test("converts a complete DockerContainer to ConnectionConfig", () => {
7+
const container: DockerContainer = {
8+
container_id: "abc123def456",
9+
name: "my-postgres",
10+
image: "postgres:15-alpine",
11+
db_type: "postgres",
12+
host: "127.0.0.1",
13+
port: 5433,
14+
user: "myuser",
15+
password: "secret",
16+
database: "mydb",
17+
status: "running",
18+
}
19+
20+
const config = containerToConfig(container)
21+
22+
expect(config).toEqual({
23+
type: "postgres",
24+
host: "127.0.0.1",
25+
port: 5433,
26+
user: "myuser",
27+
password: "secret",
28+
database: "mydb",
29+
})
30+
})
31+
32+
test("omits optional fields when not present on container", () => {
33+
const container: DockerContainer = {
34+
container_id: "abc123",
35+
name: "bare-mysql",
36+
image: "mysql:8",
37+
db_type: "mysql",
38+
host: "127.0.0.1",
39+
port: 3306,
40+
status: "running",
41+
}
42+
43+
const config = containerToConfig(container)
44+
45+
// Should only have type, host, port — no user, password, database
46+
expect(Object.keys(config).sort()).toEqual(["host", "port", "type"])
47+
expect(config.type).toBe("mysql")
48+
expect(config.host).toBe("127.0.0.1")
49+
expect(config.port).toBe(3306)
50+
})
51+
52+
test("preserves db_type as config.type for all supported databases", () => {
53+
const dbTypes = ["postgres", "mysql", "sqlserver", "oracle", "duckdb", "sqlite", "mongodb"]
54+
55+
for (const dbType of dbTypes) {
56+
const container: DockerContainer = {
57+
container_id: "x",
58+
name: `test-${dbType}`,
59+
image: `${dbType}:latest`,
60+
db_type: dbType,
61+
host: "127.0.0.1",
62+
port: 5432,
63+
status: "running",
64+
}
65+
const config = containerToConfig(container)
66+
expect(config.type).toBe(dbType)
67+
}
68+
})
69+
70+
test("includes user but not password when only user is set", () => {
71+
const container: DockerContainer = {
72+
container_id: "x",
73+
name: "pg-no-pass",
74+
image: "postgres:15",
75+
db_type: "postgres",
76+
host: "127.0.0.1",
77+
port: 5432,
78+
user: "postgres",
79+
status: "running",
80+
}
81+
82+
const config = containerToConfig(container)
83+
84+
expect(config.user).toBe("postgres")
85+
expect(config.password).toBeUndefined()
86+
expect(Object.keys(config).sort()).toEqual(["host", "port", "type", "user"])
87+
})
88+
89+
test("includes database but not user/password when only database is set", () => {
90+
const container: DockerContainer = {
91+
container_id: "x",
92+
name: "pg-db-only",
93+
image: "postgres:15",
94+
db_type: "postgres",
95+
host: "127.0.0.1",
96+
port: 5432,
97+
database: "analytics",
98+
status: "running",
99+
}
100+
101+
const config = containerToConfig(container)
102+
103+
expect(config.database).toBe("analytics")
104+
expect(config.user).toBeUndefined()
105+
expect(config.password).toBeUndefined()
106+
})
107+
108+
test("does not include container_id, name, image, or status in config", () => {
109+
const container: DockerContainer = {
110+
container_id: "abc123def456",
111+
name: "my-container",
112+
image: "postgres:15",
113+
db_type: "postgres",
114+
host: "127.0.0.1",
115+
port: 5432,
116+
user: "pg",
117+
password: "pass",
118+
database: "db",
119+
status: "running",
120+
}
121+
122+
const config = containerToConfig(container)
123+
124+
// These Docker-specific fields should NOT leak into the ConnectionConfig
125+
expect((config as any).container_id).toBeUndefined()
126+
expect((config as any).name).toBeUndefined()
127+
expect((config as any).image).toBeUndefined()
128+
expect((config as any).status).toBeUndefined()
129+
expect((config as any).db_type).toBeUndefined()
130+
})
131+
})
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { describe, test, expect } from "bun:test"
2+
import { mapOpenAICompatibleFinishReason } from "../../src/provider/sdk/copilot/chat/map-openai-compatible-finish-reason"
3+
import { getResponseMetadata } from "../../src/provider/sdk/copilot/chat/get-response-metadata"
4+
5+
describe("mapOpenAICompatibleFinishReason", () => {
6+
test("maps 'stop' to 'stop'", () => {
7+
expect(mapOpenAICompatibleFinishReason("stop")).toBe("stop")
8+
})
9+
10+
test("maps 'length' to 'length'", () => {
11+
expect(mapOpenAICompatibleFinishReason("length")).toBe("length")
12+
})
13+
14+
test("maps 'content_filter' to 'content-filter'", () => {
15+
expect(mapOpenAICompatibleFinishReason("content_filter")).toBe("content-filter")
16+
})
17+
18+
test("maps 'function_call' to 'tool-calls'", () => {
19+
expect(mapOpenAICompatibleFinishReason("function_call")).toBe("tool-calls")
20+
})
21+
22+
test("maps 'tool_calls' to 'tool-calls'", () => {
23+
expect(mapOpenAICompatibleFinishReason("tool_calls")).toBe("tool-calls")
24+
})
25+
26+
test("maps null to 'unknown'", () => {
27+
expect(mapOpenAICompatibleFinishReason(null)).toBe("unknown")
28+
})
29+
30+
test("maps undefined to 'unknown'", () => {
31+
expect(mapOpenAICompatibleFinishReason(undefined)).toBe("unknown")
32+
})
33+
34+
test("maps unrecognized string to 'unknown'", () => {
35+
expect(mapOpenAICompatibleFinishReason("cancelled")).toBe("unknown")
36+
expect(mapOpenAICompatibleFinishReason("error")).toBe("unknown")
37+
expect(mapOpenAICompatibleFinishReason("")).toBe("unknown")
38+
})
39+
})
40+
41+
describe("getResponseMetadata", () => {
42+
test("converts all fields when present", () => {
43+
const result = getResponseMetadata({
44+
id: "chatcmpl-abc123",
45+
model: "gpt-4",
46+
created: 1700000000,
47+
})
48+
49+
expect(result.id).toBe("chatcmpl-abc123")
50+
expect(result.modelId).toBe("gpt-4")
51+
expect(result.timestamp).toEqual(new Date(1700000000 * 1000))
52+
})
53+
54+
test("returns undefined fields when inputs are null", () => {
55+
const result = getResponseMetadata({
56+
id: null,
57+
model: null,
58+
created: null,
59+
})
60+
61+
expect(result.id).toBeUndefined()
62+
expect(result.modelId).toBeUndefined()
63+
expect(result.timestamp).toBeUndefined()
64+
})
65+
66+
test("returns undefined fields when inputs are undefined", () => {
67+
const result = getResponseMetadata({
68+
id: undefined,
69+
model: undefined,
70+
created: undefined,
71+
})
72+
73+
expect(result.id).toBeUndefined()
74+
expect(result.modelId).toBeUndefined()
75+
expect(result.timestamp).toBeUndefined()
76+
})
77+
78+
test("handles empty input object", () => {
79+
const result = getResponseMetadata({})
80+
81+
expect(result.id).toBeUndefined()
82+
expect(result.modelId).toBeUndefined()
83+
expect(result.timestamp).toBeUndefined()
84+
})
85+
86+
test("converts created=0 to epoch Date (not undefined)", () => {
87+
// created=0 is falsy but not null/undefined, so it should produce a Date
88+
const result = getResponseMetadata({ created: 0 })
89+
expect(result.timestamp).toEqual(new Date(0))
90+
})
91+
92+
test("converts created timestamp correctly for recent dates", () => {
93+
// 2026-01-15 12:00:00 UTC
94+
const epoch = 1768478400
95+
const result = getResponseMetadata({ created: epoch })
96+
expect(result.timestamp?.getFullYear()).toBe(2026)
97+
})
98+
})

0 commit comments

Comments
 (0)