Skip to content

Commit 24becaa

Browse files
🧪 Add error handling tests for undo and redo modifications
1 parent 1e72c8b commit 24becaa

1 file changed

Lines changed: 160 additions & 1 deletion

File tree

tests/unit/databaseModel.test.ts

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import './vscode_mock_setup';
2-
import { describe, it, before, after, beforeEach } from 'node:test';
2+
import { describe, it, before, after, beforeEach, afterEach } from 'node:test';
33
import assert from 'node:assert';
44
import { mockVscode } from './mocks/vscode';
55

@@ -118,3 +118,162 @@ describe('isAutoCommitEnabled', () => {
118118
await setupEnvironmentAndTest(undefined, 'ssh-remote', 2 /* Workspace */, false);
119119
});
120120
});
121+
122+
123+
describe('DatabaseDocument undo/redo error handling', () => {
124+
let mockViewerProvider: any;
125+
let mockOpenContext: any;
126+
let originalShowErrorMessage: any;
127+
let originalL10n: any;
128+
129+
beforeEach(() => {
130+
originalShowErrorMessage = mockVscode.window.showErrorMessage;
131+
originalL10n = mockVscode.l10n.t;
132+
133+
mockVscode.l10n.t = (key: string, ...args: any[]) => {
134+
let res = key;
135+
args.forEach((arg, i) => {
136+
res = res.replace(`{${i}}`, String(arg));
137+
});
138+
return res;
139+
};
140+
141+
mockViewerProvider = {
142+
reporter: undefined,
143+
isVerified: true,
144+
context: { extensionUri: mockVscode.Uri.parse('file:///ext') },
145+
forceReadOnly: false
146+
};
147+
148+
mockOpenContext = {
149+
backupId: undefined
150+
};
151+
152+
const moduleCache = require('module')._cache;
153+
const workerFactoryPath = require.resolve('../../src/workerFactory');
154+
moduleCache[workerFactoryPath] = {
155+
id: workerFactoryPath,
156+
filename: workerFactoryPath,
157+
loaded: true,
158+
exports: {
159+
createDatabaseConnection: () => {
160+
return Promise.resolve({
161+
workerMethods: {
162+
open: () => Promise.resolve({ isReadOnly: false, bufferInfo: {} }),
163+
exec: () => Promise.resolve(),
164+
},
165+
establishConnection: () => Promise.resolve({ isReadOnly: false }),
166+
databaseOps: {
167+
undoModification: () => Promise.resolve(),
168+
redoModification: () => Promise.resolve(),
169+
close: () => Promise.resolve(),
170+
getSchema: () => Promise.resolve([]),
171+
query: () => Promise.resolve([])
172+
}
173+
});
174+
}
175+
}
176+
};
177+
178+
});
179+
180+
afterEach(() => {
181+
mockVscode.window.showErrorMessage = originalShowErrorMessage;
182+
mockVscode.l10n.t = originalL10n;
183+
});
184+
185+
it('should show error message when undoModification fails', async () => {
186+
let errorMessageShown = false;
187+
mockVscode.window.showErrorMessage = async (msg: string) => {
188+
if (msg.includes('Test Undo Error')) {
189+
errorMessageShown = true;
190+
}
191+
};
192+
193+
// We clear module cache of databaseModel so it uses the mocked workerFactory
194+
delete require('module')._cache[require.resolve('../../src/databaseModel')];
195+
const { DatabaseDocument } = require('../../src/databaseModel');
196+
197+
const uri = mockVscode.Uri.parse('file:///test.db');
198+
const doc = await DatabaseDocument.create(mockViewerProvider, uri, mockOpenContext);
199+
200+
// Mock database operations to throw error on undo
201+
const dbOps = doc.databaseOperations;
202+
if(dbOps) {
203+
dbOps.undoModification = () => Promise.reject(new Error("Test Undo Error"));
204+
} else {
205+
// force override via any
206+
(doc as any).connectionState = {
207+
databaseOps: {
208+
undoModification: () => Promise.reject(new Error("Test Undo Error")),
209+
redoModification: () => Promise.resolve()
210+
}
211+
};
212+
}
213+
214+
let undoAction: (() => Promise<void>) | undefined;
215+
doc.onDidChange((modification: any) => {
216+
undoAction = modification.undo;
217+
});
218+
219+
doc.recordModification({
220+
label: 'Test Mod',
221+
action: 'Test Mod Action',
222+
sql: [],
223+
inverseSql: []
224+
});
225+
226+
assert.ok(undoAction, 'Undo action should be emitted');
227+
228+
await undoAction();
229+
230+
assert.strictEqual(errorMessageShown, true, 'Error message should be shown for failed undo');
231+
});
232+
233+
it('should show error message when redoModification fails', async () => {
234+
let errorMessageShown = false;
235+
mockVscode.window.showErrorMessage = async (msg: string) => {
236+
if (msg.includes('Test Redo Error')) {
237+
errorMessageShown = true;
238+
}
239+
};
240+
241+
const { DatabaseDocument } = require('../../src/databaseModel');
242+
const uri = mockVscode.Uri.parse('file:///test.db');
243+
const doc = await DatabaseDocument.create(mockViewerProvider, uri, mockOpenContext);
244+
245+
// Mock database operations to throw error on redo
246+
const dbOps = doc.databaseOperations;
247+
if(dbOps) {
248+
dbOps.redoModification = () => Promise.reject(new Error("Test Redo Error"));
249+
} else {
250+
(doc as any).connectionState = {
251+
databaseOps: {
252+
undoModification: () => Promise.resolve(),
253+
redoModification: () => Promise.reject(new Error("Test Redo Error"))
254+
}
255+
};
256+
}
257+
258+
let redoAction: (() => Promise<void>) | undefined;
259+
let undoAction: (() => Promise<void>) | undefined;
260+
doc.onDidChange((modification: any) => {
261+
undoAction = modification.undo;
262+
redoAction = modification.redo;
263+
});
264+
265+
doc.recordModification({
266+
label: 'Test Mod',
267+
action: 'Test Mod Action',
268+
sql: [],
269+
inverseSql: []
270+
});
271+
272+
assert.ok(redoAction, 'Redo action should be emitted');
273+
274+
await undoAction();
275+
await redoAction();
276+
277+
assert.strictEqual(errorMessageShown, true, 'Error message should be shown for failed redo');
278+
});
279+
});

0 commit comments

Comments
 (0)