@theia/scm 1.75.0-next.8 → 1.75.0
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/lib/browser/decorations/scm-navigator-decorator.d.ts.map +1 -1
- package/lib/browser/decorations/scm-navigator-decorator.js +1 -0
- package/lib/browser/decorations/scm-navigator-decorator.js.map +1 -1
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane-header.js +7 -10
- package/lib/browser/merge-editor/view/merge-editor-panes/merge-editor-pane-header.js.map +1 -1
- package/lib/browser/scm-action-button-widget.js +10 -15
- package/lib/browser/scm-action-button-widget.js.map +1 -1
- package/lib/browser/scm-amend-component.js +24 -57
- package/lib/browser/scm-amend-component.js.map +1 -1
- package/lib/browser/scm-commit-widget.d.ts +1 -1
- package/lib/browser/scm-commit-widget.d.ts.map +1 -1
- package/lib/browser/scm-commit-widget.js +9 -10
- package/lib/browser/scm-commit-widget.js.map +1 -1
- package/lib/browser/scm-context-key-service.d.ts +2 -0
- package/lib/browser/scm-context-key-service.d.ts.map +1 -1
- package/lib/browser/scm-context-key-service.js +4 -0
- package/lib/browser/scm-context-key-service.js.map +1 -1
- package/lib/browser/scm-context-key-service.spec.js +7 -0
- package/lib/browser/scm-context-key-service.spec.js.map +1 -1
- package/lib/browser/scm-frontend-module.d.ts.map +1 -1
- package/lib/browser/scm-frontend-module.js +6 -0
- package/lib/browser/scm-frontend-module.js.map +1 -1
- package/lib/browser/scm-history-graph-contribution.d.ts +49 -0
- package/lib/browser/scm-history-graph-contribution.d.ts.map +1 -0
- package/lib/browser/scm-history-graph-contribution.js +280 -0
- package/lib/browser/scm-history-graph-contribution.js.map +1 -0
- package/lib/browser/scm-history-graph-contribution.spec.d.ts +2 -0
- package/lib/browser/scm-history-graph-contribution.spec.d.ts.map +1 -0
- package/lib/browser/scm-history-graph-contribution.spec.js +119 -0
- package/lib/browser/scm-history-graph-contribution.spec.js.map +1 -0
- package/lib/browser/scm-history-graph-helpers.d.ts +59 -6
- package/lib/browser/scm-history-graph-helpers.d.ts.map +1 -1
- package/lib/browser/scm-history-graph-helpers.js +129 -5
- package/lib/browser/scm-history-graph-helpers.js.map +1 -1
- package/lib/browser/scm-history-graph-helpers.spec.d.ts +2 -0
- package/lib/browser/scm-history-graph-helpers.spec.d.ts.map +1 -0
- package/lib/browser/scm-history-graph-helpers.spec.js +154 -0
- package/lib/browser/scm-history-graph-helpers.spec.js.map +1 -0
- package/lib/browser/scm-history-graph-lanes.d.ts +19 -5
- package/lib/browser/scm-history-graph-lanes.d.ts.map +1 -1
- package/lib/browser/scm-history-graph-lanes.js +25 -9
- package/lib/browser/scm-history-graph-lanes.js.map +1 -1
- package/lib/browser/scm-history-graph-lanes.spec.js +62 -25
- package/lib/browser/scm-history-graph-lanes.spec.js.map +1 -1
- package/lib/browser/scm-history-graph-model.d.ts +75 -6
- package/lib/browser/scm-history-graph-model.d.ts.map +1 -1
- package/lib/browser/scm-history-graph-model.js +155 -10
- package/lib/browser/scm-history-graph-model.js.map +1 -1
- package/lib/browser/scm-history-graph-model.spec.js +299 -4
- package/lib/browser/scm-history-graph-model.spec.js.map +1 -1
- package/lib/browser/scm-history-graph-tooltip.d.ts +27 -2
- package/lib/browser/scm-history-graph-tooltip.d.ts.map +1 -1
- package/lib/browser/scm-history-graph-tooltip.js +113 -22
- package/lib/browser/scm-history-graph-tooltip.js.map +1 -1
- package/lib/browser/scm-history-graph-tooltip.spec.d.ts +2 -0
- package/lib/browser/scm-history-graph-tooltip.spec.d.ts.map +1 -0
- package/lib/browser/scm-history-graph-tooltip.spec.js +213 -0
- package/lib/browser/scm-history-graph-tooltip.spec.js.map +1 -0
- package/lib/browser/scm-history-graph-widget.d.ts +36 -2
- package/lib/browser/scm-history-graph-widget.d.ts.map +1 -1
- package/lib/browser/scm-history-graph-widget.js +174 -67
- package/lib/browser/scm-history-graph-widget.js.map +1 -1
- package/lib/browser/scm-history-graph-widget.spec.d.ts +2 -0
- package/lib/browser/scm-history-graph-widget.spec.d.ts.map +1 -0
- package/lib/browser/scm-history-graph-widget.spec.js +273 -0
- package/lib/browser/scm-history-graph-widget.spec.js.map +1 -0
- package/lib/browser/scm-provider.d.ts +9 -1
- package/lib/browser/scm-provider.d.ts.map +1 -1
- package/lib/browser/scm-provider.js.map +1 -1
- package/lib/browser/scm-repositories-widget.js +12 -21
- package/lib/browser/scm-repositories-widget.js.map +1 -1
- package/lib/browser/scm-tree-widget.js +35 -53
- package/lib/browser/scm-tree-widget.js.map +1 -1
- package/lib/common/scm-preferences.d.ts +3 -0
- package/lib/common/scm-preferences.d.ts.map +1 -1
- package/lib/common/scm-preferences.js +24 -0
- package/lib/common/scm-preferences.js.map +1 -1
- package/package.json +7 -7
- package/src/browser/decorations/scm-navigator-decorator.ts +3 -2
- package/src/browser/scm-context-key-service.spec.ts +9 -0
- package/src/browser/scm-context-key-service.ts +6 -0
- package/src/browser/scm-frontend-module.ts +7 -1
- package/src/browser/scm-history-graph-contribution.spec.ts +148 -0
- package/src/browser/scm-history-graph-contribution.ts +273 -0
- package/src/browser/scm-history-graph-helpers.spec.ts +193 -0
- package/src/browser/scm-history-graph-helpers.ts +180 -6
- package/src/browser/scm-history-graph-lanes.spec.ts +70 -25
- package/src/browser/scm-history-graph-lanes.ts +48 -11
- package/src/browser/scm-history-graph-model.spec.ts +378 -12
- package/src/browser/scm-history-graph-model.ts +181 -13
- package/src/browser/scm-history-graph-tooltip.spec.ts +254 -0
- package/src/browser/scm-history-graph-tooltip.ts +144 -24
- package/src/browser/scm-history-graph-widget.spec.ts +322 -0
- package/src/browser/scm-history-graph-widget.tsx +199 -39
- package/src/browser/scm-provider.ts +9 -1
- package/src/browser/style/scm-history-graph.css +53 -2
- package/src/common/scm-preferences.ts +27 -0
|
@@ -17,20 +17,21 @@
|
|
|
17
17
|
import { expect } from 'chai';
|
|
18
18
|
import { Emitter } from '@theia/core/lib/common/event';
|
|
19
19
|
import { ScmHistoryGraphModel, PAGE_SIZE } from './scm-history-graph-model';
|
|
20
|
-
import { ScmHistoryItem, ScmHistoryItemRef, ScmHistoryItemChange, ScmHistoryOptions, ScmHistoryProvider } from './scm-provider';
|
|
20
|
+
import { ScmHistoryItem, ScmHistoryItemRef, ScmHistoryItemRefsChangeEvent, ScmHistoryItemChange, ScmHistoryOptions, ScmHistoryProvider } from './scm-provider';
|
|
21
21
|
import { ScmRepository } from './scm-repository';
|
|
22
22
|
|
|
23
23
|
class StubHistoryProvider implements ScmHistoryProvider {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
currentHistoryItemRef: ScmHistoryItemRef | undefined;
|
|
25
|
+
currentHistoryItemRemoteRef: ScmHistoryItemRef | undefined;
|
|
26
|
+
currentHistoryItemBaseRef: ScmHistoryItemRef | undefined;
|
|
27
27
|
|
|
28
28
|
readonly onDidChangeCurrentHistoryItemRefs = new Emitter<void>().event;
|
|
29
|
-
readonly
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
protected readonly onDidChangeHistoryItemRefsEmitter = new Emitter<ScmHistoryItemRefsChangeEvent>();
|
|
30
|
+
readonly onDidChangeHistoryItemRefs = this.onDidChangeHistoryItemRefsEmitter.event;
|
|
31
|
+
|
|
32
|
+
fireHistoryItemRefsChanged(event: ScmHistoryItemRefsChangeEvent): void {
|
|
33
|
+
this.onDidChangeHistoryItemRefsEmitter.fire(event);
|
|
34
|
+
}
|
|
34
35
|
|
|
35
36
|
/** Pages this provider will return on consecutive calls (FIFO). */
|
|
36
37
|
pages: ScmHistoryItem[][] = [];
|
|
@@ -75,30 +76,46 @@ function makeItems(start: number, count: number): ScmHistoryItem[] {
|
|
|
75
76
|
/**
|
|
76
77
|
* Instantiates the model with a stub provider, bypassing inversify and the
|
|
77
78
|
* SCM service so tests can drive pagination directly via loadPage().
|
|
79
|
+
* When `wireRepository` is set, the provider is instead wired through a stub
|
|
80
|
+
* selected repository and refresh(), so provider event subscriptions are live.
|
|
78
81
|
*/
|
|
79
|
-
function createModel(
|
|
82
|
+
function createModel(
|
|
83
|
+
provider: ScmHistoryProvider,
|
|
84
|
+
preferences: Record<string, unknown> = {},
|
|
85
|
+
wireRepository = false
|
|
86
|
+
): { model: ScmHistoryGraphModel; loadPage(): Promise<void>; firePreferenceChanged(preferenceName: string): void } {
|
|
80
87
|
const model = new ScmHistoryGraphModel();
|
|
81
88
|
const internals = model as unknown as {
|
|
82
89
|
scmService: {
|
|
83
90
|
onDidChangeSelectedRepository: Emitter<ScmRepository | undefined>['event'];
|
|
84
91
|
selectedRepository: ScmRepository | undefined;
|
|
85
92
|
};
|
|
93
|
+
scmPreferences: Record<string, unknown>;
|
|
86
94
|
_provider: ScmHistoryProvider | undefined;
|
|
87
95
|
init(): void;
|
|
88
96
|
loadPage(): Promise<void>;
|
|
89
97
|
};
|
|
98
|
+
const preferenceEmitter = new Emitter<{ preferenceName: string }>();
|
|
90
99
|
internals.scmService = {
|
|
91
100
|
onDidChangeSelectedRepository: new Emitter<ScmRepository | undefined>().event,
|
|
92
|
-
selectedRepository: undefined,
|
|
101
|
+
selectedRepository: wireRepository ? { provider: { historyProvider: provider } } as unknown as ScmRepository : undefined,
|
|
93
102
|
};
|
|
103
|
+
internals.scmPreferences = Object.assign(preferences, { onPreferenceChanged: preferenceEmitter.event });
|
|
94
104
|
internals.init();
|
|
95
|
-
|
|
105
|
+
if (!wireRepository) {
|
|
106
|
+
internals._provider = provider;
|
|
107
|
+
}
|
|
96
108
|
return {
|
|
97
109
|
model,
|
|
98
110
|
loadPage: () => internals.loadPage(),
|
|
111
|
+
firePreferenceChanged: preferenceName => preferenceEmitter.fire({ preferenceName }),
|
|
99
112
|
};
|
|
100
113
|
}
|
|
101
114
|
|
|
115
|
+
async function nextTick(): Promise<void> {
|
|
116
|
+
return new Promise(resolve => setTimeout(resolve, 0));
|
|
117
|
+
}
|
|
118
|
+
|
|
102
119
|
describe('ScmHistoryGraphModel - pagination', () => {
|
|
103
120
|
|
|
104
121
|
it('hasMore is true when a full page returns', async () => {
|
|
@@ -169,3 +186,352 @@ describe('ScmHistoryGraphModel - pagination', () => {
|
|
|
169
186
|
expect(model.entries).to.have.length(PAGE_SIZE, 'should not grow when all items are duplicates');
|
|
170
187
|
});
|
|
171
188
|
});
|
|
189
|
+
|
|
190
|
+
describe('ScmHistoryGraphModel - page size preference', () => {
|
|
191
|
+
|
|
192
|
+
it('requests the configured page size and paginates by it', async () => {
|
|
193
|
+
const provider = new StubHistoryProvider();
|
|
194
|
+
provider.pages = [makeItems(1, 10)];
|
|
195
|
+
const { model, loadPage } = createModel(provider, { 'scm.graph.pageSize': 10 });
|
|
196
|
+
|
|
197
|
+
await loadPage();
|
|
198
|
+
|
|
199
|
+
expect(provider.receivedOptions[0].limit).to.equal(10);
|
|
200
|
+
expect(model.entries).to.have.length(10);
|
|
201
|
+
expect(model.hasMore).to.be.true;
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it('falls back to the default page size without a preference value', async () => {
|
|
205
|
+
const provider = new StubHistoryProvider();
|
|
206
|
+
provider.pages = [makeItems(1, 10)];
|
|
207
|
+
const { loadPage } = createModel(provider);
|
|
208
|
+
|
|
209
|
+
await loadPage();
|
|
210
|
+
|
|
211
|
+
expect(provider.receivedOptions[0].limit).to.equal(PAGE_SIZE);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('reloads from the start when scm.graph.pageSize changes', async () => {
|
|
215
|
+
const provider = new StubHistoryProvider();
|
|
216
|
+
provider.pages = [makeItems(1, 10), makeItems(1, 5)];
|
|
217
|
+
const preferences: Record<string, unknown> = { 'scm.graph.pageSize': 10 };
|
|
218
|
+
const { loadPage, firePreferenceChanged } = createModel(provider, preferences);
|
|
219
|
+
|
|
220
|
+
await loadPage();
|
|
221
|
+
expect(provider.receivedOptions[0].limit).to.equal(10);
|
|
222
|
+
|
|
223
|
+
preferences['scm.graph.pageSize'] = 5;
|
|
224
|
+
firePreferenceChanged('scm.graph.pageSize');
|
|
225
|
+
await nextTick();
|
|
226
|
+
|
|
227
|
+
expect(provider.receivedOptions[1].limit).to.equal(5);
|
|
228
|
+
expect(provider.receivedOptions[1].skip).to.equal(0);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
describe('ScmHistoryGraphModel - history item ref filter', () => {
|
|
233
|
+
|
|
234
|
+
const mainRef: ScmHistoryItemRef = { id: 'refs/heads/main', name: 'main', revision: 'c1' };
|
|
235
|
+
|
|
236
|
+
function createFilterProvider(): StubHistoryProvider {
|
|
237
|
+
const provider = new StubHistoryProvider();
|
|
238
|
+
provider.currentHistoryItemRef = mainRef;
|
|
239
|
+
provider.pages = [makeItems(1, 3), makeItems(1, 3), makeItems(1, 3)];
|
|
240
|
+
return provider;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
it('is in auto mode by default: current ref revisions are requested and the current ref is in the filter', async () => {
|
|
244
|
+
const provider = createFilterProvider();
|
|
245
|
+
const { model, loadPage } = createModel(provider);
|
|
246
|
+
await loadPage();
|
|
247
|
+
expect(provider.receivedOptions[0].historyItemRefs).to.deep.equal(['c1']);
|
|
248
|
+
expect(model.historyItemRefFilter).to.be.undefined;
|
|
249
|
+
expect(model.isCurrentRefInFilter()).to.be.true;
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('passes the picked ref ids to the provider and reloads', async () => {
|
|
253
|
+
const provider = createFilterProvider();
|
|
254
|
+
const { model } = createModel(provider);
|
|
255
|
+
model.setHistoryItemRefFilter(['refs/heads/feature']);
|
|
256
|
+
await nextTick();
|
|
257
|
+
expect(provider.receivedOptions[0].historyItemRefs).to.deep.equal(['refs/heads/feature']);
|
|
258
|
+
expect(model.historyItemRefFilter).to.deep.equal(['refs/heads/feature']);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it('reports whether the current ref is part of the filter', async () => {
|
|
262
|
+
const provider = createFilterProvider();
|
|
263
|
+
const { model } = createModel(provider);
|
|
264
|
+
model.setHistoryItemRefFilter(['refs/heads/feature']);
|
|
265
|
+
await nextTick();
|
|
266
|
+
expect(model.isCurrentRefInFilter()).to.be.false;
|
|
267
|
+
model.setHistoryItemRefFilter(['refs/heads/feature', 'refs/heads/main']);
|
|
268
|
+
await nextTick();
|
|
269
|
+
expect(model.isCurrentRefInFilter()).to.be.true;
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('returns to auto mode when the filter is cleared', async () => {
|
|
273
|
+
const provider = createFilterProvider();
|
|
274
|
+
const { model } = createModel(provider);
|
|
275
|
+
model.setHistoryItemRefFilter(['refs/heads/feature']);
|
|
276
|
+
await nextTick();
|
|
277
|
+
model.setHistoryItemRefFilter(undefined);
|
|
278
|
+
await nextTick();
|
|
279
|
+
expect(model.historyItemRefFilter).to.be.undefined;
|
|
280
|
+
expect(provider.receivedOptions[1].historyItemRefs).to.deep.equal(['c1']);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('does not apply ref role colors to refs excluded by the filter', async () => {
|
|
284
|
+
const provider = createFilterProvider();
|
|
285
|
+
provider.pages = [[
|
|
286
|
+
{ id: 'c1', subject: 'head', parentIds: ['c2'], references: [mainRef] },
|
|
287
|
+
{ id: 'c2', subject: 'base', parentIds: [] },
|
|
288
|
+
]];
|
|
289
|
+
const { model } = createModel(provider);
|
|
290
|
+
model.setHistoryItemRefFilter(['refs/heads/feature']);
|
|
291
|
+
await nextTick();
|
|
292
|
+
expect(model.entries[0].graphRow.color).to.not.equal(0);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
describe('ScmHistoryGraphModel - ref filter pruning', () => {
|
|
297
|
+
|
|
298
|
+
const mainRef: ScmHistoryItemRef = { id: 'refs/heads/main', name: 'main', revision: 'c1' };
|
|
299
|
+
const featureRef: ScmHistoryItemRef = { id: 'refs/heads/feature', name: 'feature', revision: 'c5' };
|
|
300
|
+
|
|
301
|
+
function createWiredProvider(): StubHistoryProvider {
|
|
302
|
+
const provider = new StubHistoryProvider();
|
|
303
|
+
provider.currentHistoryItemRef = mainRef;
|
|
304
|
+
return provider;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
it('drops a removed ref from the filter and keeps the remaining ones', async () => {
|
|
308
|
+
const provider = createWiredProvider();
|
|
309
|
+
const { model } = createModel(provider, {}, true);
|
|
310
|
+
model.setHistoryItemRefFilter([featureRef.id, mainRef.id]);
|
|
311
|
+
await nextTick();
|
|
312
|
+
|
|
313
|
+
provider.fireHistoryItemRefsChanged({ added: [], removed: [featureRef], modified: [] });
|
|
314
|
+
await nextTick();
|
|
315
|
+
|
|
316
|
+
expect(model.historyItemRefFilter).to.deep.equal([mainRef.id]);
|
|
317
|
+
const last = provider.receivedOptions[provider.receivedOptions.length - 1];
|
|
318
|
+
expect(last.historyItemRefs).to.deep.equal([mainRef.id]);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it('falls back to auto mode when all filtered refs are removed', async () => {
|
|
322
|
+
const provider = createWiredProvider();
|
|
323
|
+
const { model } = createModel(provider, {}, true);
|
|
324
|
+
model.setHistoryItemRefFilter([featureRef.id]);
|
|
325
|
+
await nextTick();
|
|
326
|
+
|
|
327
|
+
provider.fireHistoryItemRefsChanged({ added: [], removed: [featureRef], modified: [] });
|
|
328
|
+
await nextTick();
|
|
329
|
+
|
|
330
|
+
expect(model.historyItemRefFilter).to.be.undefined;
|
|
331
|
+
const last = provider.receivedOptions[provider.receivedOptions.length - 1];
|
|
332
|
+
expect(last.historyItemRefs).to.deep.equal(['c1']);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
it('keeps the filter when unrelated refs are removed', async () => {
|
|
336
|
+
const provider = createWiredProvider();
|
|
337
|
+
const { model } = createModel(provider, {}, true);
|
|
338
|
+
model.setHistoryItemRefFilter([mainRef.id]);
|
|
339
|
+
await nextTick();
|
|
340
|
+
|
|
341
|
+
provider.fireHistoryItemRefsChanged({ added: [], removed: [featureRef], modified: [] });
|
|
342
|
+
await nextTick();
|
|
343
|
+
|
|
344
|
+
expect(model.historyItemRefFilter).to.deep.equal([mainRef.id]);
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
describe('ScmHistoryGraphModel - ref colors and current item', () => {
|
|
349
|
+
|
|
350
|
+
const mainRef: ScmHistoryItemRef = { id: 'refs/heads/main', name: 'main', revision: 'c2' };
|
|
351
|
+
const originMainRef: ScmHistoryItemRef = { id: 'refs/remotes/origin/main', name: 'origin/main', revision: 'c1' };
|
|
352
|
+
|
|
353
|
+
/** Remote is one commit ahead: c1 (origin/main) → c2 (main = HEAD) → c3. */
|
|
354
|
+
function createBehindProvider(): StubHistoryProvider {
|
|
355
|
+
const provider = new StubHistoryProvider();
|
|
356
|
+
provider.currentHistoryItemRef = mainRef;
|
|
357
|
+
provider.currentHistoryItemRemoteRef = originMainRef;
|
|
358
|
+
provider.pages = [[
|
|
359
|
+
{ id: 'c1', subject: 'remote only', parentIds: ['c2'], references: [originMainRef] },
|
|
360
|
+
{ id: 'c2', subject: 'local head', parentIds: ['c3'], references: [mainRef] },
|
|
361
|
+
{ id: 'c3', subject: 'base', parentIds: [] },
|
|
362
|
+
]];
|
|
363
|
+
return provider;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
it('colors the remote ref tip with the remote ref color', async () => {
|
|
367
|
+
const { model, loadPage } = createModel(createBehindProvider());
|
|
368
|
+
await loadPage();
|
|
369
|
+
expect(model.entries[0].graphRow.color).to.equal(1);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it('colors the current ref chain with the current ref color', async () => {
|
|
373
|
+
const { model, loadPage } = createModel(createBehindProvider());
|
|
374
|
+
await loadPage();
|
|
375
|
+
expect(model.entries[1].graphRow.color).to.equal(0);
|
|
376
|
+
expect(model.entries[2].graphRow.color).to.equal(0);
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
it('prefers the current ref color when a commit carries both local and remote refs', async () => {
|
|
380
|
+
const provider = new StubHistoryProvider();
|
|
381
|
+
const syncedMain: ScmHistoryItemRef = { ...mainRef, revision: 'c1' };
|
|
382
|
+
const syncedRemote: ScmHistoryItemRef = { ...originMainRef, revision: 'c1' };
|
|
383
|
+
provider.currentHistoryItemRef = syncedMain;
|
|
384
|
+
provider.currentHistoryItemRemoteRef = syncedRemote;
|
|
385
|
+
provider.pages = [[
|
|
386
|
+
{ id: 'c1', subject: 'in sync', parentIds: [], references: [syncedRemote, syncedMain] },
|
|
387
|
+
]];
|
|
388
|
+
const { model, loadPage } = createModel(provider);
|
|
389
|
+
await loadPage();
|
|
390
|
+
expect(model.entries[0].graphRow.color).to.equal(0);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
it('marks only the entry at the current ref revision as current', async () => {
|
|
394
|
+
const { model, loadPage } = createModel(createBehindProvider());
|
|
395
|
+
await loadPage();
|
|
396
|
+
expect(model.entries.map(e => e.isCurrent)).to.deep.equal([false, true, false]);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it('marks no entry as current when the provider has no current ref', async () => {
|
|
400
|
+
const provider = new StubHistoryProvider();
|
|
401
|
+
provider.pages = [makeItems(1, 3)];
|
|
402
|
+
const { model, loadPage } = createModel(provider);
|
|
403
|
+
await loadPage();
|
|
404
|
+
expect(model.entries.every(e => !e.isCurrent)).to.be.true;
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
describe('ScmHistoryGraphModel - view mode', () => {
|
|
409
|
+
|
|
410
|
+
it('shows the changes of a history item as a list by default', () => {
|
|
411
|
+
const { model } = createModel(new StubHistoryProvider());
|
|
412
|
+
expect(model.viewMode).to.equal('list');
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
it('switches the view mode', () => {
|
|
416
|
+
const { model } = createModel(new StubHistoryProvider());
|
|
417
|
+
model.setViewMode('tree');
|
|
418
|
+
expect(model.viewMode).to.equal('tree');
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
it('notifies listeners when the view mode changes', () => {
|
|
422
|
+
const { model } = createModel(new StubHistoryProvider());
|
|
423
|
+
let changes = 0;
|
|
424
|
+
model.onDidChange(() => changes++);
|
|
425
|
+
|
|
426
|
+
model.setViewMode('tree');
|
|
427
|
+
|
|
428
|
+
expect(changes).to.equal(1);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('does not notify listeners when the view mode is unchanged', () => {
|
|
432
|
+
const { model } = createModel(new StubHistoryProvider());
|
|
433
|
+
model.setViewMode('tree');
|
|
434
|
+
let changes = 0;
|
|
435
|
+
model.onDidChange(() => changes++);
|
|
436
|
+
|
|
437
|
+
model.setViewMode('tree');
|
|
438
|
+
|
|
439
|
+
expect(changes).to.equal(0);
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
it('does not reload history when the view mode changes', async () => {
|
|
443
|
+
const provider = new StubHistoryProvider();
|
|
444
|
+
provider.pages = [makeItems(1, 10)];
|
|
445
|
+
const { model, loadPage } = createModel(provider);
|
|
446
|
+
await loadPage();
|
|
447
|
+
const requestsBefore = provider.receivedOptions.length;
|
|
448
|
+
|
|
449
|
+
model.setViewMode('tree');
|
|
450
|
+
await nextTick();
|
|
451
|
+
|
|
452
|
+
expect(provider.receivedOptions).to.have.length(requestsBefore);
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
describe('ScmHistoryGraphModel - revealing the current history item', () => {
|
|
457
|
+
|
|
458
|
+
function createProviderAt(revision: string): StubHistoryProvider {
|
|
459
|
+
const provider = new StubHistoryProvider();
|
|
460
|
+
provider.currentHistoryItemRef = { id: 'refs/heads/main', name: 'main', revision };
|
|
461
|
+
return provider;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
it('requests a reveal of the index of the current history item', async () => {
|
|
465
|
+
const provider = createProviderAt('c3');
|
|
466
|
+
provider.pages = [makeItems(1, 10)];
|
|
467
|
+
const { model, loadPage } = createModel(provider);
|
|
468
|
+
await loadPage();
|
|
469
|
+
const revealed: number[] = [];
|
|
470
|
+
model.onDidRequestReveal(revealedIndex => revealed.push(revealedIndex));
|
|
471
|
+
|
|
472
|
+
const index = await model.revealCurrentHistoryItem();
|
|
473
|
+
|
|
474
|
+
expect(index).to.equal(2);
|
|
475
|
+
expect(revealed).to.deep.equal([2]);
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
it('loads further pages until the current history item is found', async () => {
|
|
479
|
+
const provider = createProviderAt('c55');
|
|
480
|
+
provider.pages = [makeItems(1, PAGE_SIZE), makeItems(PAGE_SIZE + 1, PAGE_SIZE)];
|
|
481
|
+
const { model, loadPage } = createModel(provider);
|
|
482
|
+
await loadPage();
|
|
483
|
+
expect(model.entries).to.have.length(PAGE_SIZE);
|
|
484
|
+
|
|
485
|
+
const index = await model.revealCurrentHistoryItem();
|
|
486
|
+
|
|
487
|
+
expect(index).to.equal(54);
|
|
488
|
+
expect(model.entries).to.have.length(2 * PAGE_SIZE);
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
it('does not request a reveal when the current history item is not in the history', async () => {
|
|
492
|
+
const provider = createProviderAt('not-loaded');
|
|
493
|
+
provider.pages = [makeItems(1, 10)];
|
|
494
|
+
const { model, loadPage } = createModel(provider);
|
|
495
|
+
await loadPage();
|
|
496
|
+
const revealed: number[] = [];
|
|
497
|
+
model.onDidRequestReveal(revealedIndex => revealed.push(revealedIndex));
|
|
498
|
+
|
|
499
|
+
const index = await model.revealCurrentHistoryItem();
|
|
500
|
+
|
|
501
|
+
expect(index).to.be.undefined;
|
|
502
|
+
expect(revealed).to.be.empty;
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
it('does not request a reveal when the provider has no current history item ref', async () => {
|
|
506
|
+
const provider = new StubHistoryProvider();
|
|
507
|
+
provider.pages = [makeItems(1, 10)];
|
|
508
|
+
const { model, loadPage } = createModel(provider);
|
|
509
|
+
await loadPage();
|
|
510
|
+
const revealed: number[] = [];
|
|
511
|
+
model.onDidRequestReveal(revealedIndex => revealed.push(revealedIndex));
|
|
512
|
+
|
|
513
|
+
const index = await model.revealCurrentHistoryItem();
|
|
514
|
+
|
|
515
|
+
expect(index).to.be.undefined;
|
|
516
|
+
expect(revealed).to.be.empty;
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
it('stops paging when further pages add no new items', async () => {
|
|
520
|
+
const provider = createProviderAt('never-returned');
|
|
521
|
+
const page = makeItems(1, PAGE_SIZE);
|
|
522
|
+
// A provider that keeps returning the same full page: `hasMore` stays true
|
|
523
|
+
// forever, so only a no-progress guard can end the search.
|
|
524
|
+
provider.provideHistoryItems = async options => {
|
|
525
|
+
provider.receivedOptions.push(options);
|
|
526
|
+
return page;
|
|
527
|
+
};
|
|
528
|
+
const { model, loadPage } = createModel(provider);
|
|
529
|
+
await loadPage();
|
|
530
|
+
expect(model.hasMore).to.be.true;
|
|
531
|
+
|
|
532
|
+
const index = await model.revealCurrentHistoryItem();
|
|
533
|
+
|
|
534
|
+
expect(index).to.be.undefined;
|
|
535
|
+
expect(model.entries).to.have.length(PAGE_SIZE);
|
|
536
|
+
});
|
|
537
|
+
});
|