@substrate-ai/core 0.20.1 → 0.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -33
- package/package.json +10 -2
- package/dist/__tests__/adapter.test.d.ts +0 -12
- package/dist/__tests__/adapter.test.d.ts.map +0 -1
- package/dist/__tests__/adapter.test.js +0 -259
- package/dist/__tests__/adapter.test.js.map +0 -1
- package/dist/__tests__/event-bus.test.d.ts +0 -14
- package/dist/__tests__/event-bus.test.d.ts.map +0 -1
- package/dist/__tests__/event-bus.test.js +0 -199
- package/dist/__tests__/event-bus.test.js.map +0 -1
- package/dist/__tests__/output-quality.test.d.ts +0 -8
- package/dist/__tests__/output-quality.test.d.ts.map +0 -1
- package/dist/__tests__/output-quality.test.js +0 -166
- package/dist/__tests__/output-quality.test.js.map +0 -1
- package/dist/__tests__/schema-suffix.test.d.ts +0 -9
- package/dist/__tests__/schema-suffix.test.d.ts.map +0 -1
- package/dist/__tests__/schema-suffix.test.js +0 -126
- package/dist/__tests__/schema-suffix.test.js.map +0 -1
- package/dist/__tests__/yaml-parser.test.d.ts +0 -18
- package/dist/__tests__/yaml-parser.test.d.ts.map +0 -1
- package/dist/__tests__/yaml-parser.test.js +0 -475
- package/dist/__tests__/yaml-parser.test.js.map +0 -1
- package/dist/adapters/__tests__/adapter-output-normalizer.test.d.ts +0 -12
- package/dist/adapters/__tests__/adapter-output-normalizer.test.d.ts.map +0 -1
- package/dist/adapters/__tests__/adapter-output-normalizer.test.js +0 -193
- package/dist/adapters/__tests__/adapter-output-normalizer.test.js.map +0 -1
- package/dist/persistence/dolt-adapter-transaction.test.d.ts +0 -10
- package/dist/persistence/dolt-adapter-transaction.test.d.ts.map +0 -1
- package/dist/persistence/dolt-adapter-transaction.test.js +0 -359
- package/dist/persistence/dolt-adapter-transaction.test.js.map +0 -1
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for AdapterOutputNormalizer (Story 53-10).
|
|
3
|
-
*
|
|
4
|
-
* Tests all 4 normalization strategies:
|
|
5
|
-
* 1. standard — direct extractYamlBlock
|
|
6
|
-
* 2. strip-prose — remove leading prose, retry
|
|
7
|
-
* 3. strip-markdown — remove markdown artifacts, retry
|
|
8
|
-
* 4. json-fallback — parse embedded JSON, dump to YAML
|
|
9
|
-
* Plus error handling when all strategies are exhausted.
|
|
10
|
-
*/
|
|
11
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
12
|
-
import { AdapterOutputNormalizer } from '../adapter-output-normalizer.js';
|
|
13
|
-
import { AdapterFormatError } from '../adapter-format-error.js';
|
|
14
|
-
const silentLogger = { debug: vi.fn(), warn: vi.fn() };
|
|
15
|
-
describe('AdapterOutputNormalizer', () => {
|
|
16
|
-
// -----------------------------------------------------------------------
|
|
17
|
-
// Strategy 1: standard
|
|
18
|
-
// -----------------------------------------------------------------------
|
|
19
|
-
describe('standard strategy', () => {
|
|
20
|
-
it('extracts fenced YAML block directly', () => {
|
|
21
|
-
const output = [
|
|
22
|
-
'Here is my analysis.',
|
|
23
|
-
'',
|
|
24
|
-
'```yaml',
|
|
25
|
-
'result: success',
|
|
26
|
-
'files_modified:',
|
|
27
|
-
' - src/foo.ts',
|
|
28
|
-
'```',
|
|
29
|
-
].join('\n');
|
|
30
|
-
const normalizer = new AdapterOutputNormalizer(silentLogger);
|
|
31
|
-
const result = normalizer.normalize(output, 'claude-code');
|
|
32
|
-
expect(result).not.toBeInstanceOf(AdapterFormatError);
|
|
33
|
-
const success = result;
|
|
34
|
-
expect(success.strategy).toBe('standard');
|
|
35
|
-
expect(success.yaml).toContain('result:');
|
|
36
|
-
});
|
|
37
|
-
it('extracts unfenced YAML starting with anchor key', () => {
|
|
38
|
-
const output = 'verdict: SHIP_IT\nscore: 95\nnotes: looks good';
|
|
39
|
-
const normalizer = new AdapterOutputNormalizer(silentLogger);
|
|
40
|
-
const result = normalizer.normalize(output, 'claude-code');
|
|
41
|
-
expect(result).not.toBeInstanceOf(AdapterFormatError);
|
|
42
|
-
const success = result;
|
|
43
|
-
expect(success.strategy).toBe('standard');
|
|
44
|
-
expect(success.yaml).toContain('verdict:');
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
// -----------------------------------------------------------------------
|
|
48
|
-
// Strategy 2: strip-prose
|
|
49
|
-
// -----------------------------------------------------------------------
|
|
50
|
-
describe('strip-prose strategy', () => {
|
|
51
|
-
it('strips leading prose and finds YAML block', () => {
|
|
52
|
-
// Fenced block after prose — standard strategy should find this too,
|
|
53
|
-
// but the test validates that strip-prose doesn't break anything
|
|
54
|
-
const output = [
|
|
55
|
-
'I have completed the code review.',
|
|
56
|
-
'The implementation looks correct.',
|
|
57
|
-
'',
|
|
58
|
-
'```yaml',
|
|
59
|
-
'verdict: SHIP_IT',
|
|
60
|
-
'score: 92',
|
|
61
|
-
'```',
|
|
62
|
-
].join('\n');
|
|
63
|
-
const normalizer = new AdapterOutputNormalizer(silentLogger);
|
|
64
|
-
const result = normalizer.normalize(output, 'codex');
|
|
65
|
-
expect(result).not.toBeInstanceOf(AdapterFormatError);
|
|
66
|
-
const success = result;
|
|
67
|
-
expect(success.yaml).toContain('verdict:');
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
// -----------------------------------------------------------------------
|
|
71
|
-
// Strategy 3: strip-markdown
|
|
72
|
-
// -----------------------------------------------------------------------
|
|
73
|
-
describe('strip-markdown strategy', () => {
|
|
74
|
-
it('strips blockquote prefixes and extracts YAML', () => {
|
|
75
|
-
// Blockquote-wrapped YAML — standard extractYamlBlock won't find it
|
|
76
|
-
// because the `> ` prefix breaks anchor detection
|
|
77
|
-
const output = [
|
|
78
|
-
'> ```yaml',
|
|
79
|
-
'> verdict: SHIP_IT',
|
|
80
|
-
'> score: 88',
|
|
81
|
-
'> ```',
|
|
82
|
-
].join('\n');
|
|
83
|
-
const normalizer = new AdapterOutputNormalizer(silentLogger);
|
|
84
|
-
const result = normalizer.normalize(output, 'gemini');
|
|
85
|
-
expect(result).not.toBeInstanceOf(AdapterFormatError);
|
|
86
|
-
const success = result;
|
|
87
|
-
expect(success.yaml).toContain('verdict:');
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
// -----------------------------------------------------------------------
|
|
91
|
-
// Strategy 4: json-fallback
|
|
92
|
-
// -----------------------------------------------------------------------
|
|
93
|
-
describe('json-fallback strategy', () => {
|
|
94
|
-
it('extracts JSON with anchor keys and converts to YAML', () => {
|
|
95
|
-
// No YAML fences, no anchor keys on their own lines — just embedded JSON
|
|
96
|
-
// Use a format that won't match standard/strip-prose/strip-markdown
|
|
97
|
-
const output = [
|
|
98
|
-
'Output from agent:',
|
|
99
|
-
'---BEGIN---',
|
|
100
|
-
'{"result": "success", "files_modified": ["src/foo.ts"]}',
|
|
101
|
-
'---END---',
|
|
102
|
-
].join('\n');
|
|
103
|
-
const normalizer = new AdapterOutputNormalizer(silentLogger);
|
|
104
|
-
const result = normalizer.normalize(output, 'codex');
|
|
105
|
-
// This may match standard (yaml-parser has JSON fallback) or json-fallback
|
|
106
|
-
if (result instanceof AdapterFormatError) {
|
|
107
|
-
// JSON is on single line — the multiline JSON regex (\{[\s\S]*?\n\}) won't match
|
|
108
|
-
// That's fine — this tests the boundary. Let's use a multiline JSON instead.
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
it('extracts multiline JSON with anchor keys', () => {
|
|
112
|
-
const output = [
|
|
113
|
-
'Some narrative text without any yaml markers.',
|
|
114
|
-
'More narrative.',
|
|
115
|
-
'{',
|
|
116
|
-
'"result": "success",',
|
|
117
|
-
'"files_modified": ["src/foo.ts"]',
|
|
118
|
-
'}',
|
|
119
|
-
'End of output.',
|
|
120
|
-
].join('\n');
|
|
121
|
-
const normalizer = new AdapterOutputNormalizer(silentLogger);
|
|
122
|
-
const result = normalizer.normalize(output, 'codex');
|
|
123
|
-
expect(result).not.toBeInstanceOf(AdapterFormatError);
|
|
124
|
-
const success = result;
|
|
125
|
-
expect(success.yaml).toContain('result:');
|
|
126
|
-
});
|
|
127
|
-
it('ignores JSON without anchor keys', () => {
|
|
128
|
-
const output = [
|
|
129
|
-
'Some text.',
|
|
130
|
-
'{',
|
|
131
|
-
'"status": "ok",',
|
|
132
|
-
'"count": 42',
|
|
133
|
-
'}',
|
|
134
|
-
'End.',
|
|
135
|
-
].join('\n');
|
|
136
|
-
const normalizer = new AdapterOutputNormalizer(silentLogger);
|
|
137
|
-
const result = normalizer.normalize(output, 'codex');
|
|
138
|
-
expect(result).toBeInstanceOf(AdapterFormatError);
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
// -----------------------------------------------------------------------
|
|
142
|
-
// All strategies exhausted
|
|
143
|
-
// -----------------------------------------------------------------------
|
|
144
|
-
describe('all strategies exhausted', () => {
|
|
145
|
-
it('returns AdapterFormatError with diagnostic fields', () => {
|
|
146
|
-
const output = 'This is just plain text with no YAML or JSON whatsoever.';
|
|
147
|
-
const normalizer = new AdapterOutputNormalizer(silentLogger);
|
|
148
|
-
const result = normalizer.normalize(output, 'claude-code');
|
|
149
|
-
expect(result).toBeInstanceOf(AdapterFormatError);
|
|
150
|
-
const err = result;
|
|
151
|
-
expect(err.adapter_id).toBe('claude-code');
|
|
152
|
-
expect(err.tried_strategies).toEqual(['standard', 'strip-prose', 'strip-markdown', 'json-fallback']);
|
|
153
|
-
expect(err.raw_output_snippet).toBe(output);
|
|
154
|
-
expect(err.extraction_error).toContain('json-fallback');
|
|
155
|
-
expect(err.rootCause).toBe('adapter-format');
|
|
156
|
-
});
|
|
157
|
-
it('truncates raw_output_snippet to 500 chars', () => {
|
|
158
|
-
const output = 'x'.repeat(1000);
|
|
159
|
-
const normalizer = new AdapterOutputNormalizer(silentLogger);
|
|
160
|
-
const result = normalizer.normalize(output, 'test');
|
|
161
|
-
expect(result).toBeInstanceOf(AdapterFormatError);
|
|
162
|
-
const err = result;
|
|
163
|
-
expect(err.raw_output_snippet.length).toBe(500);
|
|
164
|
-
});
|
|
165
|
-
it('logs a warning when all strategies fail', () => {
|
|
166
|
-
const logger = { debug: vi.fn(), warn: vi.fn() };
|
|
167
|
-
const normalizer = new AdapterOutputNormalizer(logger);
|
|
168
|
-
normalizer.normalize('no yaml here', 'test-adapter');
|
|
169
|
-
expect(logger.warn).toHaveBeenCalledWith(expect.objectContaining({
|
|
170
|
-
adapter_id: 'test-adapter',
|
|
171
|
-
tried_strategies: ['standard', 'strip-prose', 'strip-markdown', 'json-fallback'],
|
|
172
|
-
}), expect.stringContaining('exhausted all strategies'));
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
// -----------------------------------------------------------------------
|
|
176
|
-
// AdapterFormatError
|
|
177
|
-
// -----------------------------------------------------------------------
|
|
178
|
-
describe('AdapterFormatError', () => {
|
|
179
|
-
it('has rootCause = adapter-format', () => {
|
|
180
|
-
const err = new AdapterFormatError({
|
|
181
|
-
adapter_id: 'codex',
|
|
182
|
-
rawOutput: 'garbage',
|
|
183
|
-
tried_strategies: ['standard'],
|
|
184
|
-
extraction_error: 'no yaml found',
|
|
185
|
-
});
|
|
186
|
-
expect(err.rootCause).toBe('adapter-format');
|
|
187
|
-
expect(err.name).toBe('AdapterFormatError');
|
|
188
|
-
expect(err.message).toContain('codex');
|
|
189
|
-
expect(err.message).toContain('standard');
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
//# sourceMappingURL=adapter-output-normalizer.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter-output-normalizer.test.js","sourceRoot":"","sources":["../../../src/adapters/__tests__/adapter-output-normalizer.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAE/D,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAA;AAEtD,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,0EAA0E;IAC1E,uBAAuB;IACvB,0EAA0E;IAE1E,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,MAAM,GAAG;gBACb,sBAAsB;gBACtB,EAAE;gBACF,SAAS;gBACT,iBAAiB;gBACjB,iBAAiB;gBACjB,gBAAgB;gBAChB,KAAK;aACN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAEZ,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;YAE1D,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAA;YACrD,MAAM,OAAO,GAAG,MAA4C,CAAA;YAC5D,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YACzC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;YACzD,MAAM,MAAM,GAAG,gDAAgD,CAAA;YAE/D,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;YAE1D,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAA;YACrD,MAAM,OAAO,GAAG,MAA4C,CAAA;YAC5D,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YACzC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;QAC5C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,0EAA0E;IAC1E,0BAA0B;IAC1B,0EAA0E;IAE1E,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,qEAAqE;YACrE,iEAAiE;YACjE,MAAM,MAAM,GAAG;gBACb,mCAAmC;gBACnC,mCAAmC;gBACnC,EAAE;gBACF,SAAS;gBACT,kBAAkB;gBAClB,WAAW;gBACX,KAAK;aACN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAEZ,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YAEpD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAA;YACrD,MAAM,OAAO,GAAG,MAA4C,CAAA;YAC5D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;QAC5C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,0EAA0E;IAC1E,6BAA6B;IAC7B,0EAA0E;IAE1E,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;YACtD,oEAAoE;YACpE,kDAAkD;YAClD,MAAM,MAAM,GAAG;gBACb,WAAW;gBACX,oBAAoB;gBACpB,aAAa;gBACb,OAAO;aACR,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAEZ,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;YAErD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAA;YACrD,MAAM,OAAO,GAAG,MAA4C,CAAA;YAC5D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;QAC5C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,0EAA0E;IAC1E,4BAA4B;IAC5B,0EAA0E;IAE1E,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,yEAAyE;YACzE,oEAAoE;YACpE,MAAM,MAAM,GAAG;gBACb,oBAAoB;gBACpB,aAAa;gBACb,yDAAyD;gBACzD,WAAW;aACZ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAEZ,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YAEpD,2EAA2E;YAC3E,IAAI,MAAM,YAAY,kBAAkB,EAAE,CAAC;gBACzC,iFAAiF;gBACjF,6EAA6E;YAC/E,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,MAAM,MAAM,GAAG;gBACb,+CAA+C;gBAC/C,iBAAiB;gBACjB,GAAG;gBACH,sBAAsB;gBACtB,kCAAkC;gBAClC,GAAG;gBACH,gBAAgB;aACjB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAEZ,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YAEpD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAA;YACrD,MAAM,OAAO,GAAG,MAA4C,CAAA;YAC5D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,MAAM,GAAG;gBACb,YAAY;gBACZ,GAAG;gBACH,iBAAiB;gBACjB,aAAa;gBACb,GAAG;gBACH,MAAM;aACP,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAEZ,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YAEpD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAA;QACnD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,0EAA0E;IAC1E,2BAA2B;IAC3B,0EAA0E;IAE1E,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACxC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,MAAM,GAAG,0DAA0D,CAAA;YAEzE,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;YAE1D,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAA;YACjD,MAAM,GAAG,GAAG,MAA4B,CAAA;YACxC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;YAC1C,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,CAAC,CAAC,CAAA;YACpG,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAC3C,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAA;YACvD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAE/B,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,YAAY,CAAC,CAAA;YAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;YAEnD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAA;YACjD,MAAM,GAAG,GAAG,MAA4B,CAAA;YACxC,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACjD,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;YACjD,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAA;YAChD,MAAM,UAAU,GAAG,IAAI,uBAAuB,CAAC,MAAM,CAAC,CAAA;YAEtD,UAAU,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC,CAAA;YAEpD,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,oBAAoB,CACtC,MAAM,CAAC,gBAAgB,CAAC;gBACtB,UAAU,EAAE,cAAc;gBAC1B,gBAAgB,EAAE,CAAC,UAAU,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,CAAC;aACjF,CAAC,EACF,MAAM,CAAC,gBAAgB,CAAC,0BAA0B,CAAC,CACpD,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,0EAA0E;IAC1E,qBAAqB;IACrB,0EAA0E;IAE1E,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,GAAG,GAAG,IAAI,kBAAkB,CAAC;gBACjC,UAAU,EAAE,OAAO;gBACnB,SAAS,EAAE,SAAS;gBACpB,gBAAgB,EAAE,CAAC,UAAU,CAAC;gBAC9B,gBAAgB,EAAE,eAAe;aAClC,CAAC,CAAA;YAEF,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;YAC5C,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;YAC3C,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;YACtC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,CAAA;QAC3C,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for DoltDatabaseAdapter transaction() + DoltClient.transact()
|
|
3
|
-
*
|
|
4
|
-
* Story 53-14 acceptance criteria:
|
|
5
|
-
* AC1: Pool-mode transactions use a dedicated connection (no query scatter)
|
|
6
|
-
* AC2: CLI-mode transactions use a single batched dolt sql invocation
|
|
7
|
-
* AC4: Existing DoltDatabaseAdapter.transaction() call sites unchanged
|
|
8
|
-
*/
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=dolt-adapter-transaction.test.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dolt-adapter-transaction.test.d.ts","sourceRoot":"","sources":["../../src/persistence/dolt-adapter-transaction.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for DoltDatabaseAdapter transaction() + DoltClient.transact()
|
|
3
|
-
*
|
|
4
|
-
* Story 53-14 acceptance criteria:
|
|
5
|
-
* AC1: Pool-mode transactions use a dedicated connection (no query scatter)
|
|
6
|
-
* AC2: CLI-mode transactions use a single batched dolt sql invocation
|
|
7
|
-
* AC4: Existing DoltDatabaseAdapter.transaction() call sites unchanged
|
|
8
|
-
*/
|
|
9
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
10
|
-
import { DoltDatabaseAdapter } from './dolt-adapter.js';
|
|
11
|
-
import { DoltClient } from './dolt-client.js';
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
// Helpers
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
/** Build a minimal mock DoltClientLike that includes both query() and transact(). */
|
|
16
|
-
function makeMockClient(overrides = {}) {
|
|
17
|
-
return {
|
|
18
|
-
query: vi.fn().mockResolvedValue([]),
|
|
19
|
-
transact: vi.fn().mockImplementation(async (fn) => {
|
|
20
|
-
const txQuery = (_sql, _params) => Promise.resolve([]);
|
|
21
|
-
return fn(txQuery);
|
|
22
|
-
}),
|
|
23
|
-
close: vi.fn().mockResolvedValue(undefined),
|
|
24
|
-
...overrides,
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
// ---------------------------------------------------------------------------
|
|
28
|
-
// AC1: Pool-mode — dedicated connection, BEGIN + COMMIT on same conn
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
describe('DoltClient.transact() — pool mode (AC1)', () => {
|
|
31
|
-
function makeClientWithMockPool() {
|
|
32
|
-
const mockConn = {
|
|
33
|
-
execute: vi.fn().mockResolvedValue([[], []]),
|
|
34
|
-
release: vi.fn(),
|
|
35
|
-
};
|
|
36
|
-
const mockPool = {
|
|
37
|
-
getConnection: vi.fn().mockResolvedValue(mockConn),
|
|
38
|
-
};
|
|
39
|
-
const client = new DoltClient({ repoPath: '/tmp/fake-repo' });
|
|
40
|
-
// @ts-expect-error - private field injection for test
|
|
41
|
-
client._pool = mockPool;
|
|
42
|
-
// @ts-expect-error - private field injection for test
|
|
43
|
-
client._useCliMode = false;
|
|
44
|
-
// @ts-expect-error - private field injection for test
|
|
45
|
-
client._connected = true;
|
|
46
|
-
return { client, mockConn, mockPool };
|
|
47
|
-
}
|
|
48
|
-
it('executes BEGIN, user queries, and COMMIT on the same connection', async () => {
|
|
49
|
-
const { client, mockConn, mockPool } = makeClientWithMockPool();
|
|
50
|
-
const executedSql = [];
|
|
51
|
-
mockConn.execute.mockImplementation(async (sql) => {
|
|
52
|
-
executedSql.push(sql);
|
|
53
|
-
return [[], []];
|
|
54
|
-
});
|
|
55
|
-
await client.transact(async (txQuery) => {
|
|
56
|
-
await txQuery('INSERT INTO foo VALUES (1)');
|
|
57
|
-
await txQuery('INSERT INTO foo VALUES (2)');
|
|
58
|
-
});
|
|
59
|
-
// All calls go through the same connection object
|
|
60
|
-
expect(executedSql).toEqual([
|
|
61
|
-
'BEGIN',
|
|
62
|
-
'INSERT INTO foo VALUES (1)',
|
|
63
|
-
'INSERT INTO foo VALUES (2)',
|
|
64
|
-
'COMMIT',
|
|
65
|
-
]);
|
|
66
|
-
// Exactly one connection was acquired
|
|
67
|
-
expect(mockPool.getConnection).toHaveBeenCalledOnce();
|
|
68
|
-
// Connection is released in finally
|
|
69
|
-
expect(mockConn.release).toHaveBeenCalledOnce();
|
|
70
|
-
});
|
|
71
|
-
it('issues ROLLBACK and releases connection when fn() throws', async () => {
|
|
72
|
-
const { client, mockConn } = makeClientWithMockPool();
|
|
73
|
-
const executedSql = [];
|
|
74
|
-
mockConn.execute.mockImplementation(async (sql) => {
|
|
75
|
-
executedSql.push(sql);
|
|
76
|
-
return [[], []];
|
|
77
|
-
});
|
|
78
|
-
await expect(client.transact(async () => {
|
|
79
|
-
throw new Error('forced failure');
|
|
80
|
-
})).rejects.toThrow('forced failure');
|
|
81
|
-
expect(executedSql).toContain('ROLLBACK');
|
|
82
|
-
expect(executedSql).not.toContain('COMMIT');
|
|
83
|
-
// Connection must be released even on error
|
|
84
|
-
expect(mockConn.release).toHaveBeenCalledOnce();
|
|
85
|
-
});
|
|
86
|
-
it('two concurrent transactions acquire separate connections (no query interleaving)', async () => {
|
|
87
|
-
const connA = {
|
|
88
|
-
execute: vi.fn().mockResolvedValue([[], []]),
|
|
89
|
-
release: vi.fn(),
|
|
90
|
-
};
|
|
91
|
-
const connB = {
|
|
92
|
-
execute: vi.fn().mockResolvedValue([[], []]),
|
|
93
|
-
release: vi.fn(),
|
|
94
|
-
};
|
|
95
|
-
let acquireCount = 0;
|
|
96
|
-
const mockPool = {
|
|
97
|
-
getConnection: vi.fn().mockImplementation(() => {
|
|
98
|
-
acquireCount++;
|
|
99
|
-
return Promise.resolve(acquireCount === 1 ? connA : connB);
|
|
100
|
-
}),
|
|
101
|
-
};
|
|
102
|
-
const client = new DoltClient({ repoPath: '/tmp/fake-repo' });
|
|
103
|
-
// @ts-expect-error - private field injection for test
|
|
104
|
-
client._pool = mockPool;
|
|
105
|
-
// @ts-expect-error - private field injection for test
|
|
106
|
-
client._useCliMode = false;
|
|
107
|
-
// @ts-expect-error - private field injection for test
|
|
108
|
-
client._connected = true;
|
|
109
|
-
// Run both transactions concurrently
|
|
110
|
-
await Promise.all([
|
|
111
|
-
client.transact(async (txQuery) => {
|
|
112
|
-
await txQuery('INSERT INTO t1 VALUES (1)');
|
|
113
|
-
}),
|
|
114
|
-
client.transact(async (txQuery) => {
|
|
115
|
-
await txQuery('INSERT INTO t2 VALUES (2)');
|
|
116
|
-
}),
|
|
117
|
-
]);
|
|
118
|
-
// Two separate connections were acquired
|
|
119
|
-
expect(mockPool.getConnection).toHaveBeenCalledTimes(2);
|
|
120
|
-
// connA contains only t1 SQL; connB contains only t2 SQL
|
|
121
|
-
const sqlA = connA.execute.mock.calls.map((c) => c[0]);
|
|
122
|
-
const sqlB = connB.execute.mock.calls.map((c) => c[0]);
|
|
123
|
-
expect(sqlA).toContain('INSERT INTO t1 VALUES (1)');
|
|
124
|
-
expect(sqlA).not.toContain('INSERT INTO t2 VALUES (2)');
|
|
125
|
-
expect(sqlB).toContain('INSERT INTO t2 VALUES (2)');
|
|
126
|
-
expect(sqlB).not.toContain('INSERT INTO t1 VALUES (1)');
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
// ---------------------------------------------------------------------------
|
|
130
|
-
// AC2: CLI mode — batch statement collection + single dolt invocation
|
|
131
|
-
// ---------------------------------------------------------------------------
|
|
132
|
-
describe('DoltClient.transact() — CLI mode (AC2)', () => {
|
|
133
|
-
function makeCliClient() {
|
|
134
|
-
const client = new DoltClient({ repoPath: '/tmp/dolt-repo' });
|
|
135
|
-
// @ts-expect-error - private field injection for test
|
|
136
|
-
client._useCliMode = true;
|
|
137
|
-
// @ts-expect-error - private field injection for test
|
|
138
|
-
client._connected = true;
|
|
139
|
-
return client;
|
|
140
|
-
}
|
|
141
|
-
it('does NOT call query() for statements within transact() — they are collected', async () => {
|
|
142
|
-
const client = makeCliClient();
|
|
143
|
-
const querySpy = vi.spyOn(client, 'query');
|
|
144
|
-
// Stub _withCliLock to avoid actual dolt binary invocation by assigning a no-op
|
|
145
|
-
const lockStub = vi.fn().mockResolvedValue(undefined);
|
|
146
|
-
// @ts-expect-error - override private method for test
|
|
147
|
-
client._withCliLock = lockStub;
|
|
148
|
-
await client.transact(async (txQuery) => {
|
|
149
|
-
await txQuery('INSERT INTO foo VALUES (1)');
|
|
150
|
-
await txQuery('INSERT INTO foo VALUES (2)');
|
|
151
|
-
});
|
|
152
|
-
// query() must NOT be called — statements are batched, not individually dispatched
|
|
153
|
-
expect(querySpy).not.toHaveBeenCalled();
|
|
154
|
-
// _withCliLock WAS called once (the single batch invocation)
|
|
155
|
-
expect(lockStub).toHaveBeenCalledOnce();
|
|
156
|
-
});
|
|
157
|
-
it('assembles BEGIN/.../COMMIT batch and invokes _withCliLock exactly once', async () => {
|
|
158
|
-
const client = makeCliClient();
|
|
159
|
-
let capturedBatchSql;
|
|
160
|
-
// Execute the inner fn so we can inspect the batch SQL.
|
|
161
|
-
// runExecFile will throw (no real dolt binary), but DoltQueryError
|
|
162
|
-
// exposes the batch SQL via its .sql property — capture it and swallow
|
|
163
|
-
// the error so that transact() can return normally.
|
|
164
|
-
const lockStub = vi.fn().mockImplementation(async (fn) => {
|
|
165
|
-
try {
|
|
166
|
-
await fn();
|
|
167
|
-
}
|
|
168
|
-
catch (err) {
|
|
169
|
-
if (err instanceof Error && 'sql' in err) {
|
|
170
|
-
capturedBatchSql = err.sql;
|
|
171
|
-
}
|
|
172
|
-
// Swallow error to allow transact() to complete normally
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
// @ts-expect-error - override private method for test
|
|
176
|
-
client._withCliLock = lockStub;
|
|
177
|
-
await client.transact(async (txQuery) => {
|
|
178
|
-
await txQuery("INSERT INTO foo (id) VALUES (1)");
|
|
179
|
-
await txQuery("INSERT INTO foo (id) VALUES (2)");
|
|
180
|
-
});
|
|
181
|
-
// Single batch invocation regardless of statement count
|
|
182
|
-
expect(lockStub).toHaveBeenCalledOnce();
|
|
183
|
-
// The batch SQL must wrap all statements with BEGIN and COMMIT in order
|
|
184
|
-
expect(capturedBatchSql).toBe("BEGIN; INSERT INTO foo (id) VALUES (1); INSERT INTO foo (id) VALUES (2); COMMIT");
|
|
185
|
-
});
|
|
186
|
-
it('does NOT call _withCliLock when fn() issues zero statements', async () => {
|
|
187
|
-
const client = makeCliClient();
|
|
188
|
-
const lockStub = vi.fn().mockResolvedValue(undefined);
|
|
189
|
-
// @ts-expect-error - override private method for test
|
|
190
|
-
client._withCliLock = lockStub;
|
|
191
|
-
const result = await client.transact(async () => {
|
|
192
|
-
// No SQL statements
|
|
193
|
-
return 'empty';
|
|
194
|
-
});
|
|
195
|
-
expect(lockStub).not.toHaveBeenCalled();
|
|
196
|
-
expect(result).toBe('empty');
|
|
197
|
-
});
|
|
198
|
-
it('CLI-mode transact() rejects when the batch dolt invocation fails', async () => {
|
|
199
|
-
const client = makeCliClient();
|
|
200
|
-
// _withCliLock stub that executes the inner fn (which calls runExecFile — will fail)
|
|
201
|
-
const lockStub = vi.fn().mockImplementation(async (fn) => fn());
|
|
202
|
-
// @ts-expect-error - override private method for test
|
|
203
|
-
client._withCliLock = lockStub;
|
|
204
|
-
// Should reject (no real dolt binary available)
|
|
205
|
-
await expect(client.transact(async (txQuery) => {
|
|
206
|
-
await txQuery("INSERT INTO foo VALUES (1)");
|
|
207
|
-
})).rejects.toBeDefined();
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
// ---------------------------------------------------------------------------
|
|
211
|
-
// _resolveParams unit tests (AC2 — correct param interpolation in batch SQL)
|
|
212
|
-
// ---------------------------------------------------------------------------
|
|
213
|
-
describe('DoltClient._resolveParams() — parameter interpolation (AC2)', () => {
|
|
214
|
-
function resolveParams(sql, params) {
|
|
215
|
-
const client = new DoltClient({ repoPath: '/tmp/repo' });
|
|
216
|
-
// @ts-expect-error - accessing private method for test
|
|
217
|
-
return client._resolveParams(sql, params);
|
|
218
|
-
}
|
|
219
|
-
it('substitutes numeric params without quoting', () => {
|
|
220
|
-
expect(resolveParams('SELECT * FROM t WHERE id = ?', [42])).toBe('SELECT * FROM t WHERE id = 42');
|
|
221
|
-
});
|
|
222
|
-
it('substitutes string params with single-quote escaping', () => {
|
|
223
|
-
expect(resolveParams("INSERT INTO t VALUES (?)", ['hello'])).toBe("INSERT INTO t VALUES ('hello')");
|
|
224
|
-
});
|
|
225
|
-
it('escapes single quotes inside string values', () => {
|
|
226
|
-
expect(resolveParams("INSERT INTO t VALUES (?)", ["it's fine"])).toBe("INSERT INTO t VALUES ('it''s fine')");
|
|
227
|
-
});
|
|
228
|
-
it('substitutes null/undefined as NULL', () => {
|
|
229
|
-
expect(resolveParams("INSERT INTO t VALUES (?, ?)", [null, undefined])).toBe("INSERT INTO t VALUES (NULL, NULL)");
|
|
230
|
-
});
|
|
231
|
-
it('handles multiple params in order', () => {
|
|
232
|
-
expect(resolveParams("INSERT INTO t (a, b) VALUES (?, ?)", ['hello', null])).toBe("INSERT INTO t (a, b) VALUES ('hello', NULL)");
|
|
233
|
-
});
|
|
234
|
-
it('returns SQL unchanged when no params', () => {
|
|
235
|
-
expect(resolveParams('SELECT 1', undefined)).toBe('SELECT 1');
|
|
236
|
-
expect(resolveParams('SELECT 1', [])).toBe('SELECT 1');
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
// ---------------------------------------------------------------------------
|
|
240
|
-
// DoltDatabaseAdapter.transaction() — delegates to client.transact() (AC4)
|
|
241
|
-
// ---------------------------------------------------------------------------
|
|
242
|
-
describe('DoltDatabaseAdapter.transaction() — delegates to client.transact()', () => {
|
|
243
|
-
it('calls client.transact() — does NOT issue BEGIN/COMMIT via query()', async () => {
|
|
244
|
-
const transactMock = vi.fn().mockImplementation(async (fn) => {
|
|
245
|
-
const txQuery = (_sql, _params) => Promise.resolve([]);
|
|
246
|
-
return fn(txQuery);
|
|
247
|
-
});
|
|
248
|
-
const client = makeMockClient({ transact: transactMock });
|
|
249
|
-
const adapter = new DoltDatabaseAdapter(client);
|
|
250
|
-
const result = await adapter.transaction(async (tx) => {
|
|
251
|
-
await tx.exec("INSERT INTO t VALUES (1)");
|
|
252
|
-
return 'done';
|
|
253
|
-
});
|
|
254
|
-
expect(result).toBe('done');
|
|
255
|
-
expect(transactMock).toHaveBeenCalledOnce();
|
|
256
|
-
// Critically: BEGIN and COMMIT must NOT be issued via query()
|
|
257
|
-
expect(vi.mocked(client.query)).not.toHaveBeenCalledWith('BEGIN', undefined);
|
|
258
|
-
expect(vi.mocked(client.query)).not.toHaveBeenCalledWith('COMMIT', undefined);
|
|
259
|
-
});
|
|
260
|
-
it('txAdapter has backendType = "dolt"', async () => {
|
|
261
|
-
let capturedBackendType;
|
|
262
|
-
const client = makeMockClient();
|
|
263
|
-
const adapter = new DoltDatabaseAdapter(client);
|
|
264
|
-
await adapter.transaction(async (tx) => {
|
|
265
|
-
capturedBackendType = tx.backendType;
|
|
266
|
-
});
|
|
267
|
-
expect(capturedBackendType).toBe('dolt');
|
|
268
|
-
});
|
|
269
|
-
it('nested transaction() on txAdapter is a pass-through — no second transact() call', async () => {
|
|
270
|
-
let innerCallCount = 0;
|
|
271
|
-
const transactMock = vi.fn().mockImplementation(async (fn) => {
|
|
272
|
-
const txQuery = (_sql, _params) => Promise.resolve([]);
|
|
273
|
-
return fn(txQuery);
|
|
274
|
-
});
|
|
275
|
-
const client = makeMockClient({ transact: transactMock });
|
|
276
|
-
const adapter = new DoltDatabaseAdapter(client);
|
|
277
|
-
await adapter.transaction(async (outerTx) => {
|
|
278
|
-
await outerTx.transaction(async (innerTx) => {
|
|
279
|
-
innerCallCount++;
|
|
280
|
-
await innerTx.exec('INSERT INTO t VALUES (99)');
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
// transact() was called exactly once (the outer call — nested is pass-through)
|
|
284
|
-
expect(transactMock).toHaveBeenCalledOnce();
|
|
285
|
-
expect(innerCallCount).toBe(1);
|
|
286
|
-
});
|
|
287
|
-
it('propagates rejection from fn() through transact()', async () => {
|
|
288
|
-
const client = makeMockClient();
|
|
289
|
-
const adapter = new DoltDatabaseAdapter(client);
|
|
290
|
-
await expect(adapter.transaction(async () => {
|
|
291
|
-
throw new Error('tx failed');
|
|
292
|
-
})).rejects.toThrow('tx failed');
|
|
293
|
-
});
|
|
294
|
-
it('txAdapter.exec() passes SQL to txQuery with undefined params', async () => {
|
|
295
|
-
let capturedSql;
|
|
296
|
-
let capturedParams;
|
|
297
|
-
const transactMock = vi.fn().mockImplementation(async (fn) => {
|
|
298
|
-
const txQuery = (sql, params) => {
|
|
299
|
-
capturedSql = sql;
|
|
300
|
-
capturedParams = params;
|
|
301
|
-
return Promise.resolve([]);
|
|
302
|
-
};
|
|
303
|
-
return fn(txQuery);
|
|
304
|
-
});
|
|
305
|
-
const client = makeMockClient({ transact: transactMock });
|
|
306
|
-
const adapter = new DoltDatabaseAdapter(client);
|
|
307
|
-
await adapter.transaction(async (tx) => {
|
|
308
|
-
await tx.exec('DELETE FROM foo WHERE id = 1');
|
|
309
|
-
});
|
|
310
|
-
expect(capturedSql).toBe('DELETE FROM foo WHERE id = 1');
|
|
311
|
-
expect(capturedParams).toBeUndefined();
|
|
312
|
-
});
|
|
313
|
-
});
|
|
314
|
-
// ---------------------------------------------------------------------------
|
|
315
|
-
// AC3: Integration test — data survives process exit (gated on real Dolt repo)
|
|
316
|
-
// ---------------------------------------------------------------------------
|
|
317
|
-
/**
|
|
318
|
-
* Integration test (AC3): verifies that rows committed via adapter.transaction()
|
|
319
|
-
* are visible to a fresh process querying via Dolt CLI.
|
|
320
|
-
*
|
|
321
|
-
* SKIPPED unless DOLT_INTEGRATION_TEST=1 is set in the environment.
|
|
322
|
-
* Requires: Dolt CLI on PATH + a git repo initialized with `dolt init`.
|
|
323
|
-
*/
|
|
324
|
-
describe('DoltClient.transact() — integration (AC3, skipped by default)', () => {
|
|
325
|
-
const runIntegration = process.env['DOLT_INTEGRATION_TEST'] === '1';
|
|
326
|
-
it.skipIf(!runIntegration)('rows written in a transaction are visible to a fresh CLI process after close()', async () => {
|
|
327
|
-
const { execFile } = await import('node:child_process');
|
|
328
|
-
const { promisify } = await import('node:util');
|
|
329
|
-
const { mkdtemp, rm } = await import('node:fs/promises');
|
|
330
|
-
const execFileAsync = promisify(execFile);
|
|
331
|
-
// Create a temp dir and initialize a Dolt repo
|
|
332
|
-
const tmpDir = await mkdtemp('/tmp/dolt-test-');
|
|
333
|
-
try {
|
|
334
|
-
await execFileAsync('dolt', ['init'], { cwd: tmpDir });
|
|
335
|
-
// Create a test table via Dolt CLI
|
|
336
|
-
await execFileAsync('dolt', ['sql', '-q', 'CREATE TABLE tx_test (id INT PRIMARY KEY, val TEXT)'], {
|
|
337
|
-
cwd: tmpDir,
|
|
338
|
-
});
|
|
339
|
-
// Import the real DoltClient
|
|
340
|
-
const { DoltClient: DoltClientReal } = await import('./dolt-client.js');
|
|
341
|
-
const client = new DoltClientReal({ repoPath: tmpDir });
|
|
342
|
-
// Write two rows in a single transaction
|
|
343
|
-
await client.transact(async (txQuery) => {
|
|
344
|
-
await txQuery("INSERT INTO tx_test (id, val) VALUES (1, 'alpha')");
|
|
345
|
-
await txQuery("INSERT INTO tx_test (id, val) VALUES (2, 'beta')");
|
|
346
|
-
});
|
|
347
|
-
// Close the client (release resources)
|
|
348
|
-
await client.close();
|
|
349
|
-
// Verify via a fresh Dolt CLI invocation (new process, new session)
|
|
350
|
-
const { stdout } = await execFileAsync('dolt', ['sql', '-q', 'SELECT COUNT(*) AS cnt FROM tx_test', '--result-format', 'json'], { cwd: tmpDir });
|
|
351
|
-
const parsed = JSON.parse(stdout);
|
|
352
|
-
expect(parsed.rows[0].cnt).toBe(2);
|
|
353
|
-
}
|
|
354
|
-
finally {
|
|
355
|
-
await rm(tmpDir, { recursive: true, force: true });
|
|
356
|
-
}
|
|
357
|
-
});
|
|
358
|
-
});
|
|
359
|
-
//# sourceMappingURL=dolt-adapter-transaction.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dolt-adapter-transaction.test.js","sourceRoot":"","sources":["../../src/persistence/dolt-adapter-transaction.test.ts"],"names":[],"mappings":"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"}
|