-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathConvexRouteAPIAdapter.test.ts
More file actions
117 lines (99 loc) · 4.2 KB
/
Copy pathConvexRouteAPIAdapter.test.ts
File metadata and controls
117 lines (99 loc) · 4.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { ConvexRouteAPIAdapter } from '@module/api/ConvexRouteAPIAdapter.js';
import { ConvexJsonSchemasResult } from '@module/client/ConvexAPITypes.js';
import { parseConvexLsn } from '@module/common/ConvexLSN.js';
import { normalizeConnectionConfig } from '@module/types/types.js';
import { ExpressionType, SqlSyncRules } from '@powersync/service-sync-rules';
import { describe, expect, it, vi } from 'vitest';
const HEAD_CURSOR = '1772817606884944123';
function createAdapter() {
const config = normalizeConnectionConfig({
type: 'convex',
deployment_url: 'https://example.convex.cloud',
deploy_key: 'test-key'
});
const adapter = new ConvexRouteAPIAdapter({
...config,
type: 'convex',
deployment_url: 'https://example.convex.cloud',
deploy_key: 'test-key'
});
(adapter as any).connectionManager.client = {
getJsonSchemas: async () => {
return {
tables: [
{
tableName: 'users',
schema: {
type: 'object',
properties: {
_id: { type: 'string' },
age: { type: 'integer' },
avatar: { type: 'string', $description: 'base64 bytes' }
}
}
}
]
} satisfies ConvexJsonSchemasResult;
},
getHeadCursor: async () => HEAD_CURSOR,
createWriteCheckpointMarker: async () => undefined
};
return adapter;
}
describe('ConvexRouteAPIAdapter', () => {
it('returns connection schema from Convex json schema', async () => {
const adapter = createAdapter();
const schema = await adapter.getConnectionSchema();
expect(schema[0]?.name).toBe('convex');
expect(schema[0]?.tables[0]?.name).toBe('users');
expect(schema[0]?.tables[0]?.columns.find((column) => column.name == '_id')?.type).toBe('id');
expect(schema[0]?.tables[0]?.columns.find((column) => column.name == '_creationTime')).toBeUndefined();
expect(schema[0]?.tables[0]?.columns.find((column) => column.name == 'avatar')?.sqlite_type).toBe(
ExpressionType.TEXT.typeFlags
);
await adapter.shutdown();
});
it('builds debug table info for matching patterns', async () => {
const adapter = createAdapter();
const syncRules = SqlSyncRules.fromYaml(
`
bucket_definitions:
test:
data:
- SELECT _id AS id FROM users
`,
{
defaultSchema: 'convex'
}
);
const result = await adapter.getDebugTablesInfo(syncRules.config.getSourceTables(), syncRules.config);
expect(result[0]?.table?.name).toBe('users');
await adapter.shutdown();
});
it('gets and advances replication head from the global snapshot cursor', async () => {
const adapter = createAdapter();
const getHeadCursor = vi.fn(async (_options?: any) => HEAD_CURSOR);
const createWriteCheckpointMarker = vi.fn(async (_options?: any) => undefined);
(adapter as any).connectionManager.client.getHeadCursor = getHeadCursor;
(adapter as any).connectionManager.client.createWriteCheckpointMarker = createWriteCheckpointMarker;
const head = await adapter.createReplicationHead(async (head) => ({ response: head, shouldAdvance: true }));
expect(head).toBe(parseConvexLsn(HEAD_CURSOR));
expect(getHeadCursor).toHaveBeenCalledTimes(1);
expect(getHeadCursor).toHaveBeenCalledWith();
expect(createWriteCheckpointMarker).toHaveBeenCalledTimes(1);
expect(createWriteCheckpointMarker).toHaveBeenCalledWith();
await adapter.shutdown();
});
it('does not write a checkpoint marker when the callback reports no advance', async () => {
const adapter = createAdapter();
const getHeadCursor = vi.fn(async (_options?: any) => HEAD_CURSOR);
const createWriteCheckpointMarker = vi.fn(async (_options?: any) => undefined);
(adapter as any).connectionManager.client.getHeadCursor = getHeadCursor;
(adapter as any).connectionManager.client.createWriteCheckpointMarker = createWriteCheckpointMarker;
const head = await adapter.createReplicationHead(async (head) => ({ response: head, shouldAdvance: false }));
expect(head).toBe(parseConvexLsn(HEAD_CURSOR));
expect(getHeadCursor).toHaveBeenCalledTimes(1);
expect(createWriteCheckpointMarker).not.toHaveBeenCalled();
await adapter.shutdown();
});
});