Skip to content

Commit b46e3ca

Browse files
Copilothotlong
andcommitted
Add test files for integration connector schemas (file-storage, database, message-queue, saas)
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent bdb1d0c commit b46e3ca

4 files changed

Lines changed: 847 additions & 0 deletions

File tree

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import { describe, it, expect } from 'vitest';
2+
import {
3+
DatabaseProviderSchema,
4+
DatabasePoolConfigSchema,
5+
SslConfigSchema,
6+
CdcConfigSchema,
7+
DatabaseTableSchema,
8+
DatabaseConnectorSchema,
9+
} from './database.zod';
10+
11+
const baseAuth = { type: 'none' as const };
12+
13+
const minimalTable = {
14+
name: 'customer',
15+
label: 'Customer',
16+
tableName: 'customers',
17+
primaryKey: 'id',
18+
};
19+
20+
const minimalConnector = {
21+
name: 'pg_main',
22+
label: 'PostgreSQL Main',
23+
type: 'database' as const,
24+
provider: 'postgresql' as const,
25+
authentication: baseAuth,
26+
connectionConfig: {
27+
host: 'localhost',
28+
port: 5432,
29+
database: 'mydb',
30+
username: 'user',
31+
password: 'pass',
32+
},
33+
tables: [minimalTable],
34+
};
35+
36+
describe('DatabaseProviderSchema', () => {
37+
it('should accept all valid providers', () => {
38+
const providers = ['postgresql', 'mysql', 'mariadb', 'mssql', 'oracle', 'mongodb', 'redis', 'cassandra', 'snowflake', 'bigquery', 'redshift', 'custom'];
39+
for (const p of providers) {
40+
expect(DatabaseProviderSchema.parse(p)).toBe(p);
41+
}
42+
});
43+
44+
it('should reject invalid provider', () => {
45+
expect(() => DatabaseProviderSchema.parse('sqlite')).toThrow();
46+
});
47+
});
48+
49+
describe('DatabasePoolConfigSchema', () => {
50+
it('should apply defaults', () => {
51+
const result = DatabasePoolConfigSchema.parse({});
52+
expect(result.min).toBe(2);
53+
expect(result.max).toBe(10);
54+
expect(result.idleTimeoutMs).toBe(30000);
55+
expect(result.testOnBorrow).toBe(true);
56+
});
57+
58+
it('should accept custom values', () => {
59+
const result = DatabasePoolConfigSchema.parse({ min: 0, max: 50, idleTimeoutMs: 5000 });
60+
expect(result.min).toBe(0);
61+
expect(result.max).toBe(50);
62+
});
63+
64+
it('should reject max below 1', () => {
65+
expect(() => DatabasePoolConfigSchema.parse({ max: 0 })).toThrow();
66+
});
67+
68+
it('should reject idleTimeoutMs below 1000', () => {
69+
expect(() => DatabasePoolConfigSchema.parse({ idleTimeoutMs: 500 })).toThrow();
70+
});
71+
});
72+
73+
describe('SslConfigSchema', () => {
74+
it('should apply defaults', () => {
75+
const result = SslConfigSchema.parse({});
76+
expect(result.enabled).toBe(false);
77+
expect(result.rejectUnauthorized).toBe(true);
78+
});
79+
80+
it('should accept full config', () => {
81+
const result = SslConfigSchema.parse({
82+
enabled: true,
83+
rejectUnauthorized: false,
84+
ca: 'ca-cert',
85+
cert: 'client-cert',
86+
key: 'client-key',
87+
});
88+
expect(result.enabled).toBe(true);
89+
expect(result.ca).toBe('ca-cert');
90+
});
91+
});
92+
93+
describe('CdcConfigSchema', () => {
94+
it('should accept valid CDC config', () => {
95+
const result = CdcConfigSchema.parse({ method: 'log_based' });
96+
expect(result.enabled).toBe(false);
97+
expect(result.batchSize).toBe(1000);
98+
expect(result.pollIntervalMs).toBe(1000);
99+
});
100+
101+
it('should accept all CDC methods', () => {
102+
for (const m of ['log_based', 'trigger_based', 'query_based', 'custom']) {
103+
expect(() => CdcConfigSchema.parse({ method: m })).not.toThrow();
104+
}
105+
});
106+
107+
it('should reject missing method', () => {
108+
expect(() => CdcConfigSchema.parse({ enabled: true })).toThrow();
109+
});
110+
111+
it('should reject batchSize out of range', () => {
112+
expect(() => CdcConfigSchema.parse({ method: 'log_based', batchSize: 0 })).toThrow();
113+
expect(() => CdcConfigSchema.parse({ method: 'log_based', batchSize: 10001 })).toThrow();
114+
});
115+
116+
it('should accept optional fields', () => {
117+
const result = CdcConfigSchema.parse({
118+
method: 'log_based',
119+
enabled: true,
120+
slotName: 'slot1',
121+
publicationName: 'pub1',
122+
startPosition: '0/1234',
123+
});
124+
expect(result.slotName).toBe('slot1');
125+
});
126+
});
127+
128+
describe('DatabaseTableSchema', () => {
129+
it('should accept valid table', () => {
130+
const result = DatabaseTableSchema.parse(minimalTable);
131+
expect(result.enabled).toBe(true);
132+
});
133+
134+
it('should accept table with all optional fields', () => {
135+
const data = {
136+
...minimalTable,
137+
schema: 'public',
138+
enabled: false,
139+
fieldMappings: [{ source: 'ext_id', target: 'id' }],
140+
whereClause: 'status = \'active\'',
141+
};
142+
expect(() => DatabaseTableSchema.parse(data)).not.toThrow();
143+
});
144+
145+
it('should reject non-snake_case name', () => {
146+
expect(() => DatabaseTableSchema.parse({ ...minimalTable, name: 'Customer' })).toThrow();
147+
});
148+
149+
it('should reject missing required fields', () => {
150+
expect(() => DatabaseTableSchema.parse({ name: 'tbl' })).toThrow();
151+
});
152+
});
153+
154+
describe('DatabaseConnectorSchema', () => {
155+
it('should accept minimal valid connector', () => {
156+
expect(() => DatabaseConnectorSchema.parse(minimalConnector)).not.toThrow();
157+
});
158+
159+
it('should apply defaults', () => {
160+
const result = DatabaseConnectorSchema.parse(minimalConnector);
161+
expect(result.queryTimeoutMs).toBe(30000);
162+
expect(result.enableQueryLogging).toBe(false);
163+
expect(result.enabled).toBe(true);
164+
});
165+
166+
it('should accept full connector', () => {
167+
const full = {
168+
...minimalConnector,
169+
poolConfig: { min: 5, max: 25 },
170+
sslConfig: { enabled: true },
171+
cdcConfig: { method: 'log_based', enabled: true },
172+
readReplicaConfig: {
173+
enabled: true,
174+
hosts: [{ host: 'replica1', port: 5432, weight: 0.5 }],
175+
},
176+
queryTimeoutMs: 60000,
177+
enableQueryLogging: true,
178+
};
179+
expect(() => DatabaseConnectorSchema.parse(full)).not.toThrow();
180+
});
181+
182+
it('should reject wrong type literal', () => {
183+
expect(() => DatabaseConnectorSchema.parse({ ...minimalConnector, type: 'saas' })).toThrow();
184+
});
185+
186+
it('should reject invalid port', () => {
187+
expect(() => DatabaseConnectorSchema.parse({
188+
...minimalConnector,
189+
connectionConfig: { ...minimalConnector.connectionConfig, port: 0 },
190+
})).toThrow();
191+
expect(() => DatabaseConnectorSchema.parse({
192+
...minimalConnector,
193+
connectionConfig: { ...minimalConnector.connectionConfig, port: 70000 },
194+
})).toThrow();
195+
});
196+
197+
it('should reject queryTimeoutMs out of range', () => {
198+
expect(() => DatabaseConnectorSchema.parse({ ...minimalConnector, queryTimeoutMs: 500 })).toThrow();
199+
expect(() => DatabaseConnectorSchema.parse({ ...minimalConnector, queryTimeoutMs: 500000 })).toThrow();
200+
});
201+
202+
it('should reject missing tables', () => {
203+
const { tables: _, ...noTables } = minimalConnector;
204+
expect(() => DatabaseConnectorSchema.parse(noTables)).toThrow();
205+
});
206+
207+
it('should reject read replica with invalid weight', () => {
208+
expect(() => DatabaseConnectorSchema.parse({
209+
...minimalConnector,
210+
readReplicaConfig: {
211+
enabled: true,
212+
hosts: [{ host: 'r1', port: 5432, weight: 2 }],
213+
},
214+
})).toThrow();
215+
});
216+
});

0 commit comments

Comments
 (0)