Skip to content

Commit fe56f6c

Browse files
author
Benjamin Pasero
committed
text editors - increase test coverage
1 parent 76c1220 commit fe56f6c

5 files changed

Lines changed: 117 additions & 28 deletions

File tree

src/vs/workbench/services/textfile/common/textFileEditorModel.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
4646
private readonly _onDidLoad = this._register(new Emitter<LoadReason>());
4747
readonly onDidLoad = this._onDidLoad.event;
4848

49+
private readonly _onDidChangeDirty = this._register(new Emitter<void>());
50+
readonly onDidChangeDirty = this._onDidChangeDirty.event;
51+
4952
private readonly _onDidSaveError = this._register(new Emitter<void>());
5053
readonly onDidSaveError = this._onDidSaveError.event;
5154

@@ -61,9 +64,6 @@ export class TextFileEditorModel extends BaseTextEditorModel implements ITextFil
6164
private readonly _onDidChangeOrphaned = this._register(new Emitter<void>());
6265
readonly onDidChangeOrphaned = this._onDidChangeOrphaned.event;
6366

64-
private readonly _onDidChangeDirty = this._register(new Emitter<void>());
65-
readonly onDidChangeDirty = this._onDidChangeDirty.event;
66-
6767
//#endregion
6868

6969
readonly capabilities = 0;

src/vs/workbench/services/textfile/test/textFileEditorModel.test.ts

Lines changed: 79 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,13 @@ suite('Files - TextFileEditorModel', () => {
6161
test('basic events', async function () {
6262
const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined);
6363

64+
let onDidLoadCounter = 0;
65+
model.onDidLoad(() => onDidLoadCounter++);
66+
6467
await model.load();
6568

69+
assert.equal(onDidLoadCounter, 1);
70+
6671
let onDidChangeContentCounter = 0;
6772
model.onDidChangeContent(() => onDidChangeContentCounter++);
6873

@@ -101,9 +106,7 @@ suite('Files - TextFileEditorModel', () => {
101106
assert.equal(accessor.workingCopyService.isDirty(model.resource), true);
102107

103108
let savedEvent = false;
104-
model.onDidSave(e => {
105-
savedEvent = true;
106-
});
109+
model.onDidSave(e => savedEvent = true);
107110

108111
let workingCopyEvent = false;
109112
accessor.workingCopyService.onDidChangeDirty(e => {
@@ -136,9 +139,7 @@ suite('Files - TextFileEditorModel', () => {
136139
await model.load();
137140

138141
let savedEvent = false;
139-
model.onDidSave(e => {
140-
savedEvent = true;
141-
});
142+
model.onDidSave(e => savedEvent = true);
142143

143144
let workingCopyEvent = false;
144145
accessor.workingCopyService.onDidChangeDirty(e => {
@@ -156,14 +157,81 @@ suite('Files - TextFileEditorModel', () => {
156157
assert.ok(!accessor.modelService.getModel(model.resource));
157158
});
158159

160+
test('save error (generic)', async function () {
161+
const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined);
162+
163+
await model.load();
164+
165+
model.textEditorModel!.setValue('bar');
166+
167+
let saveErrorEvent = false;
168+
model.onDidSaveError(e => saveErrorEvent = true);
169+
170+
accessor.fileService.writeShouldThrowError = new Error('failed to write');
171+
try {
172+
const pendingSave = model.save();
173+
assert.ok(model.hasState(ModelState.PENDING_SAVE));
174+
175+
await pendingSave;
176+
177+
assert.ok(model.hasState(ModelState.ERROR));
178+
assert.ok(model.isDirty());
179+
assert.ok(saveErrorEvent);
180+
181+
assert.equal(accessor.workingCopyService.dirtyCount, 1);
182+
assert.equal(accessor.workingCopyService.isDirty(model.resource), true);
183+
184+
model.dispose();
185+
} finally {
186+
accessor.fileService.writeShouldThrowError = undefined;
187+
}
188+
});
189+
190+
test('save error (conflict)', async function () {
191+
const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined);
192+
193+
await model.load();
194+
195+
model.textEditorModel!.setValue('bar');
196+
197+
let saveErrorEvent = false;
198+
model.onDidSaveError(e => saveErrorEvent = true);
199+
200+
accessor.fileService.writeShouldThrowError = new FileOperationError('save conflict', FileOperationResult.FILE_MODIFIED_SINCE);
201+
try {
202+
const pendingSave = model.save();
203+
assert.ok(model.hasState(ModelState.PENDING_SAVE));
204+
205+
await pendingSave;
206+
207+
assert.ok(model.hasState(ModelState.CONFLICT));
208+
assert.ok(model.isDirty());
209+
assert.ok(saveErrorEvent);
210+
211+
assert.equal(accessor.workingCopyService.dirtyCount, 1);
212+
assert.equal(accessor.workingCopyService.isDirty(model.resource), true);
213+
214+
model.dispose();
215+
} finally {
216+
accessor.fileService.writeShouldThrowError = undefined;
217+
}
218+
});
219+
159220
test('setEncoding - encode', function () {
160221
const model: TextFileEditorModel = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined);
161222

223+
let encodingEvent = false;
224+
model.onDidChangeEncoding(e => encodingEvent = true);
225+
162226
model.setEncoding('utf8', EncodingMode.Encode); // no-op
163227
assert.equal(getLastModifiedTime(model), -1);
164228

229+
assert.ok(!encodingEvent);
230+
165231
model.setEncoding('utf16', EncodingMode.Encode);
166232

233+
assert.ok(encodingEvent);
234+
167235
assert.ok(getLastModifiedTime(model) <= Date.now()); // indicates model was saved due to encoding change
168236

169237
model.dispose();
@@ -208,13 +276,8 @@ suite('Files - TextFileEditorModel', () => {
208276
const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index.txt'), 'utf8', undefined);
209277
assert.ok(model.hasState(ModelState.SAVED));
210278

211-
model.onDidSave(e => {
212-
assert.fail();
213-
});
214-
215-
model.onDidChangeDirty(e => {
216-
assert.fail();
217-
});
279+
model.onDidSave(e => assert.fail());
280+
model.onDidChangeDirty(e => assert.fail());
218281

219282
await model.load();
220283
assert.ok(model.isResolved());
@@ -240,9 +303,7 @@ suite('Files - TextFileEditorModel', () => {
240303

241304
const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined);
242305

243-
model.onDidRevert(e => {
244-
eventCounter++;
245-
});
306+
model.onDidRevert(e => eventCounter++);
246307

247308
let workingCopyEvent = false;
248309
accessor.workingCopyService.onDidChangeDirty(e => {
@@ -275,9 +336,7 @@ suite('Files - TextFileEditorModel', () => {
275336

276337
const model = instantiationService.createInstance(TextFileEditorModel, toResource.call(this, '/path/index_async.txt'), 'utf8', undefined);
277338

278-
model.onDidRevert(e => {
279-
eventCounter++;
280-
});
339+
model.onDidRevert(e => eventCounter++);
281340

282341
let workingCopyEvent = false;
283342
accessor.workingCopyService.onDidChangeDirty(e => {
@@ -333,9 +392,7 @@ suite('Files - TextFileEditorModel', () => {
333392
await model.revert({ soft: true });
334393
assert.ok(!model.isDirty());
335394

336-
model.onDidChangeDirty(e => {
337-
eventCounter++;
338-
});
395+
model.onDidChangeDirty(e => eventCounter++);
339396

340397
let workingCopyEvent = false;
341398
accessor.workingCopyService.onDidChangeDirty(e => {

src/vs/workbench/test/common/editor/resourceEditorInput.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class ServiceAccessor {
2121
) { }
2222
}
2323

24-
suite('Workbench resource editor input', () => {
24+
suite('Resource text editors', () => {
2525
let instantiationService: IInstantiationService;
2626
let accessor: ServiceAccessor;
2727

@@ -59,4 +59,4 @@ suite('Workbench resource editor input', () => {
5959
input.setMode('text');
6060
assert.equal(model.textEditorModel.getModeId(), PLAINTEXT_MODE_ID);
6161
});
62-
});
62+
});

src/vs/workbench/test/common/editor/untitledTextEditor.test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class ServiceAccessor {
2929
) { }
3030
}
3131

32-
suite('Workbench untitled text editors', () => {
32+
suite('Untitled text editors', () => {
3333

3434
let instantiationService: IInstantiationService;
3535
let accessor: ServiceAccessor;
@@ -394,23 +394,29 @@ suite('Workbench untitled text editors', () => {
394394

395395
model.textEditorModel.setValue('foo');
396396
assert.equal(input.getName(), 'foo');
397+
assert.equal(model.name, 'foo');
397398

398399
assert.equal(counter, 1);
399400
model.textEditorModel.setValue('bar');
400401
assert.equal(input.getName(), 'bar');
402+
assert.equal(model.name, 'bar');
401403

402404
assert.equal(counter, 2);
403405
model.textEditorModel.setValue('');
404406
assert.equal(input.getName(), 'Untitled-1');
407+
assert.equal(model.name, 'Untitled-1');
405408

406409
model.textEditorModel.setValue(' ');
407410
assert.equal(input.getName(), 'Untitled-1');
411+
assert.equal(model.name, 'Untitled-1');
408412

409413
model.textEditorModel.setValue('([]}'); // require actual words
410414
assert.equal(input.getName(), 'Untitled-1');
415+
assert.equal(model.name, 'Untitled-1');
411416

412417
model.textEditorModel.setValue('([]}hello '); // require actual words
413418
assert.equal(input.getName(), '([]}hello');
419+
assert.equal(model.name, '([]}hello');
414420

415421
assert.equal(counter, 4);
416422

@@ -467,4 +473,24 @@ suite('Workbench untitled text editors', () => {
467473
input.dispose();
468474
model.dispose();
469475
});
476+
477+
test('model#onDidChangeEncoding', async function () {
478+
const service = accessor.untitledTextEditorService;
479+
const input = service.create();
480+
481+
let counter = 0;
482+
483+
const model = await input.resolve();
484+
model.onDidChangeEncoding(() => counter++);
485+
486+
model.setEncoding('utf16');
487+
488+
assert.equal(counter, 1, 'Dirty model should trigger event');
489+
model.setEncoding('utf16');
490+
491+
assert.equal(counter, 1, 'Another change to same encoding does not fire event');
492+
493+
input.dispose();
494+
model.dispose();
495+
});
470496
});

src/vs/workbench/test/workbenchTestServices.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,9 +1087,15 @@ export class TestFileService implements IFileService {
10871087
});
10881088
}
10891089

1090+
writeShouldThrowError: Error | undefined = undefined;
1091+
10901092
async writeFile(resource: URI, bufferOrReadable: VSBuffer | VSBufferReadable, options?: IWriteFileOptions): Promise<IFileStatWithMetadata> {
10911093
await timeout(0);
10921094

1095+
if (this.writeShouldThrowError) {
1096+
throw this.writeShouldThrowError;
1097+
}
1098+
10931099
return ({
10941100
resource,
10951101
etag: 'index.txt',

0 commit comments

Comments
 (0)