Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/comments/test/browser/commentsView.test.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import assert from 'assert';
7
import { workbenchInstantiationService } from '../../../../test/browser/workbenchTestServices.js';
8
import { IRange, Range } from '../../../../../editor/common/core/range.js';
9
import { CommentsPanel } from '../../browser/commentsView.js';
10
import { CommentService, ICommentController, ICommentInfo, ICommentService, INotebookCommentInfo } from '../../browser/commentService.js';
11
import { Comment, CommentInput, CommentReaction, CommentThread, CommentThreadCollapsibleState, CommentThreadState } from '../../../../../editor/common/languages.js';
12
import { Emitter, Event } from '../../../../../base/common/event.js';
13
import { TestInstantiationService } from '../../../../../platform/instantiation/test/common/instantiationServiceMock.js';
14
import { IViewContainerModel, IViewDescriptor, IViewDescriptorService, ViewContainer, ViewContainerLocation } from '../../../../common/views.js';
15
import { IConfigurationService } from '../../../../../platform/configuration/common/configuration.js';
16
import { TestConfigurationService } from '../../../../../platform/configuration/test/common/testConfigurationService.js';
17
import { IContextViewService } from '../../../../../platform/contextview/browser/contextView.js';
18
import { DisposableStore } from '../../../../../base/common/lifecycle.js';
19
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
20
import { CancellationToken } from '../../../../../base/common/cancellation.js';
21
import { URI, UriComponents } from '../../../../../base/common/uri.js';
22
import { IHoverService } from '../../../../../platform/hover/browser/hover.js';
23
import { NullHoverService } from '../../../../../platform/hover/test/browser/nullHoverService.js';
24
25
class TestCommentThread implements CommentThread<IRange> {
26
isDocumentCommentThread(): this is CommentThread<IRange> {
27
return true;
28
}
29
constructor(public readonly commentThreadHandle: number,
30
public readonly controllerHandle: number,
31
public readonly threadId: string,
32
public readonly resource: string,
33
public readonly range: IRange,
34
public readonly comments: Comment[]) { }
35
36
onDidChangeComments: Event<readonly Comment[] | undefined> = new Emitter<readonly Comment[] | undefined>().event;
37
onDidChangeInitialCollapsibleState: Event<CommentThreadCollapsibleState | undefined> = new Emitter<CommentThreadCollapsibleState | undefined>().event;
38
canReply: boolean = false;
39
onDidChangeInput: Event<CommentInput | undefined> = new Emitter<CommentInput | undefined>().event;
40
onDidChangeRange: Event<IRange> = new Emitter<IRange>().event;
41
onDidChangeLabel: Event<string | undefined> = new Emitter<string | undefined>().event;
42
onDidChangeCollapsibleState: Event<CommentThreadCollapsibleState | undefined> = new Emitter<CommentThreadCollapsibleState | undefined>().event;
43
onDidChangeState: Event<CommentThreadState | undefined> = new Emitter<CommentThreadState | undefined>().event;
44
onDidChangeCanReply: Event<boolean> = new Emitter<boolean>().event;
45
isDisposed: boolean = false;
46
isTemplate: boolean = false;
47
label: string | undefined = undefined;
48
contextValue: string | undefined = undefined;
49
}
50
51
class TestCommentController implements ICommentController {
52
activeComment: { thread: CommentThread; comment?: Comment } | undefined;
53
id: string = 'test';
54
label: string = 'Test Comments';
55
owner: string = 'test';
56
features = {};
57
createCommentThreadTemplate(resource: UriComponents, range: IRange | undefined): Promise<void> {
58
throw new Error('Method not implemented.');
59
}
60
updateCommentThreadTemplate(threadHandle: number, range: IRange): Promise<void> {
61
throw new Error('Method not implemented.');
62
}
63
deleteCommentThreadMain(commentThreadId: string): void {
64
throw new Error('Method not implemented.');
65
}
66
toggleReaction(uri: URI, thread: CommentThread<IRange>, comment: Comment, reaction: CommentReaction, token: CancellationToken): Promise<void> {
67
throw new Error('Method not implemented.');
68
}
69
getDocumentComments(resource: URI, token: CancellationToken): Promise<ICommentInfo> {
70
throw new Error('Method not implemented.');
71
}
72
getNotebookComments(resource: URI, token: CancellationToken): Promise<INotebookCommentInfo> {
73
throw new Error('Method not implemented.');
74
}
75
setActiveCommentAndThread(commentInfo: { thread: CommentThread; comment: Comment } | undefined): Promise<void> {
76
throw new Error('Method not implemented.');
77
}
78
79
}
80
81
export class TestViewDescriptorService implements Partial<IViewDescriptorService> {
82
getViewLocationById(id: string): ViewContainerLocation | null {
83
return ViewContainerLocation.Panel;
84
}
85
readonly onDidChangeLocation: Event<{ views: IViewDescriptor[]; from: ViewContainerLocation; to: ViewContainerLocation }> = new Emitter<{ views: IViewDescriptor[]; from: ViewContainerLocation; to: ViewContainerLocation }>().event;
86
getViewDescriptorById(id: string): IViewDescriptor | null {
87
return null;
88
}
89
getViewContainerByViewId(id: string): ViewContainer | null {
90
return {
91
id: 'comments',
92
title: { value: 'Comments', original: 'Comments' },
93
ctorDescriptor: {} as any
94
};
95
}
96
getViewContainerModel(viewContainer: ViewContainer): IViewContainerModel {
97
const partialViewContainerModel: Partial<IViewContainerModel> = {
98
onDidChangeContainerInfo: new Emitter<{ title?: boolean; icon?: boolean; keybindingId?: boolean }>().event
99
};
100
return partialViewContainerModel as IViewContainerModel;
101
}
102
getDefaultContainerById(id: string): ViewContainer | null {
103
return null;
104
}
105
}
106
107
suite('Comments View', function () {
108
teardown(() => {
109
instantiationService.dispose();
110
commentService.dispose();
111
disposables.dispose();
112
});
113
114
ensureNoDisposablesAreLeakedInTestSuite();
115
116
let disposables: DisposableStore;
117
let instantiationService: TestInstantiationService;
118
let commentService: CommentService;
119
120
setup(() => {
121
disposables = new DisposableStore();
122
instantiationService = workbenchInstantiationService({}, disposables);
123
instantiationService.stub(IConfigurationService, new TestConfigurationService());
124
instantiationService.stub(IHoverService, NullHoverService);
125
instantiationService.stub(IContextViewService, {});
126
instantiationService.stub(IViewDescriptorService, new TestViewDescriptorService());
127
commentService = instantiationService.createInstance(CommentService);
128
instantiationService.stub(ICommentService, commentService);
129
commentService.registerCommentController('test', new TestCommentController());
130
});
131
132
133
134
test('collapse all', async function () {
135
const view = instantiationService.createInstance(CommentsPanel, { id: 'comments', title: 'Comments' });
136
view.render();
137
commentService.setWorkspaceComments('test', [
138
new TestCommentThread(1, 1, '1', 'test1', new Range(1, 1, 1, 1), [{ body: 'test', uniqueIdInThread: 1, userName: 'alex' }]),
139
new TestCommentThread(2, 1, '1', 'test2', new Range(1, 1, 1, 1), [{ body: 'test', uniqueIdInThread: 1, userName: 'alex' }]),
140
]);
141
assert.strictEqual(view.getFilterStats().total, 2);
142
assert.strictEqual(view.areAllCommentsExpanded(), true);
143
view.collapseAll();
144
assert.strictEqual(view.isSomeCommentsExpanded(), false);
145
view.dispose();
146
});
147
148
test('expand all', async function () {
149
const view = instantiationService.createInstance(CommentsPanel, { id: 'comments', title: 'Comments' });
150
view.render();
151
commentService.setWorkspaceComments('test', [
152
new TestCommentThread(1, 1, '1', 'test1', new Range(1, 1, 1, 1), [{ body: 'test', uniqueIdInThread: 1, userName: 'alex' }]),
153
new TestCommentThread(2, 1, '1', 'test2', new Range(1, 1, 1, 1), [{ body: 'test', uniqueIdInThread: 1, userName: 'alex' }]),
154
]);
155
assert.strictEqual(view.getFilterStats().total, 2);
156
view.collapseAll();
157
assert.strictEqual(view.isSomeCommentsExpanded(), false);
158
view.expandAll();
159
assert.strictEqual(view.areAllCommentsExpanded(), true);
160
view.dispose();
161
});
162
163
test('filter by text', async function () {
164
const view = instantiationService.createInstance(CommentsPanel, { id: 'comments', title: 'Comments' });
165
view.setVisible(true);
166
view.render();
167
commentService.setWorkspaceComments('test', [
168
new TestCommentThread(1, 1, '1', 'test1', new Range(1, 1, 1, 1), [{ body: 'This comment is a cat.', uniqueIdInThread: 1, userName: 'alex' }]),
169
new TestCommentThread(2, 1, '1', 'test2', new Range(1, 1, 1, 1), [{ body: 'This comment is a dog.', uniqueIdInThread: 1, userName: 'alex' }]),
170
]);
171
assert.strictEqual(view.getFilterStats().total, 2);
172
assert.strictEqual(view.getFilterStats().filtered, 2);
173
view.getFilterWidget().setFilterText('cat');
174
// Setting showResolved causes the filter to trigger for the purposes of this test.
175
view.filters.showResolved = false;
176
177
assert.strictEqual(view.getFilterStats().total, 2);
178
assert.strictEqual(view.getFilterStats().filtered, 1);
179
view.clearFilterText();
180
// Setting showResolved causes the filter to trigger for the purposes of this test.
181
view.filters.showResolved = true;
182
assert.strictEqual(view.getFilterStats().total, 2);
183
assert.strictEqual(view.getFilterStats().filtered, 2);
184
view.dispose();
185
});
186
});
187
188