Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/lib/vscode-node/test/simpleExperimentationService.spec.ts
13399 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 { describe, expect, it } from 'vitest';
7
import { DefaultsOnlyConfigurationService } from '../../../platform/configuration/common/defaultsOnlyConfigurationService';
8
import { SimpleExperimentationService } from '../../node/chatLibMain';
9
10
describe('SimpleExperimentationService', () => {
11
it('should initialize with no treatment variables', async () => {
12
const service = new SimpleExperimentationService(false, new DefaultsOnlyConfigurationService());
13
await service.hasTreatments();
14
15
expect(service.getTreatmentVariable('nonexistent')).toBeUndefined();
16
17
service.dispose();
18
});
19
20
it('should update multiple treatment variables at once', () => {
21
const service = new SimpleExperimentationService(false, new DefaultsOnlyConfigurationService());
22
const variables: Record<string, boolean | number | string> = {
23
'feature-a': true,
24
'feature-b': false,
25
'max-count': 100,
26
'experiment-id': 'exp-123'
27
};
28
29
service.updateTreatmentVariables(variables);
30
31
expect(service.getTreatmentVariable<boolean>('feature-a')).toBe(true);
32
expect(service.getTreatmentVariable<boolean>('feature-b')).toBe(false);
33
expect(service.getTreatmentVariable<number>('max-count')).toBe(100);
34
expect(service.getTreatmentVariable<string>('experiment-id')).toBe('exp-123');
35
36
service.dispose();
37
});
38
39
it('should fire onDidTreatmentsChange event with all changed variables', () => {
40
const service = new SimpleExperimentationService(false, new DefaultsOnlyConfigurationService());
41
const events: string[][] = [];
42
43
service.onDidTreatmentsChange((event) => {
44
events.push(event.affectedTreatmentVariables);
45
});
46
47
const variables: Record<string, boolean | number | string> = {
48
'feature-a': true,
49
'feature-b': 50,
50
'feature-c': 'test'
51
};
52
service.updateTreatmentVariables(variables);
53
54
expect(events).toHaveLength(1);
55
expect(events[0]).toHaveLength(3);
56
expect(events[0]).toContain('feature-a');
57
expect(events[0]).toContain('feature-b');
58
expect(events[0]).toContain('feature-c');
59
60
service.dispose();
61
});
62
63
it('should not fire onDidTreatmentsChange event when no variables change', () => {
64
const service = new SimpleExperimentationService(false, new DefaultsOnlyConfigurationService());
65
const events: string[][] = [];
66
67
// Set initial value
68
const variables1: Record<string, boolean | number | string> = {
69
'feature-flag': true
70
};
71
service.updateTreatmentVariables(variables1);
72
73
service.onDidTreatmentsChange((event) => {
74
events.push(event.affectedTreatmentVariables);
75
});
76
77
// Update with same value
78
const variables2: Record<string, boolean | number | string> = {
79
'feature-flag': true
80
};
81
service.updateTreatmentVariables(variables2);
82
83
expect(events).toHaveLength(0);
84
85
service.dispose();
86
});
87
88
it('should fire onDidTreatmentsChange event only for changed variables', () => {
89
const service = new SimpleExperimentationService(false, new DefaultsOnlyConfigurationService());
90
91
// Set initial values
92
const variables1: Record<string, boolean | number | string> = {
93
'feature-a': true,
94
'feature-b': 50
95
};
96
service.updateTreatmentVariables(variables1);
97
98
const events: string[][] = [];
99
service.onDidTreatmentsChange((event) => {
100
events.push(event.affectedTreatmentVariables);
101
});
102
103
// Update with one changed value and one unchanged
104
const variables2: Record<string, boolean | number | string> = {
105
'feature-a': true, // unchanged
106
'feature-b': 100 // changed
107
};
108
service.updateTreatmentVariables(variables2);
109
110
expect(events).toHaveLength(1);
111
expect(events[0]).toEqual(['feature-b']);
112
113
service.dispose();
114
});
115
116
it('should overwrite existing treatment variables', () => {
117
const service = new SimpleExperimentationService(false, new DefaultsOnlyConfigurationService());
118
119
const variables1: Record<string, boolean | number | string> = {
120
'feature-flag': true
121
};
122
service.updateTreatmentVariables(variables1);
123
124
expect(service.getTreatmentVariable<boolean>('feature-flag')).toBe(true);
125
126
const variables2: Record<string, boolean | number | string> = {
127
'feature-flag': false
128
};
129
service.updateTreatmentVariables(variables2);
130
131
expect(service.getTreatmentVariable<boolean>('feature-flag')).toBe(false);
132
133
service.dispose();
134
});
135
136
it('should wait for treatment variables when waitForTreatmentVariables = true', async () => {
137
const service = new SimpleExperimentationService(true, new DefaultsOnlyConfigurationService());
138
139
// hasTreatments() should not resolve until updateTreatmentVariables() is called
140
let hasTreatmentsResolved = false;
141
const hasTreatmentsPromise = service.hasTreatments().then(() => {
142
hasTreatmentsResolved = true;
143
});
144
145
// Give a bit of time to ensure promise doesn't resolve immediately
146
await new Promise(resolve => setTimeout(resolve, 10));
147
expect(hasTreatmentsResolved).toBe(false);
148
149
// Now update treatment variables
150
const variables: Record<string, boolean | number | string> = {
151
'test-feature': true
152
};
153
service.updateTreatmentVariables(variables);
154
155
// Wait for hasTreatments to resolve
156
await hasTreatmentsPromise;
157
expect(hasTreatmentsResolved).toBe(true);
158
expect(service.getTreatmentVariable<boolean>('test-feature')).toBe(true);
159
160
service.dispose();
161
});
162
163
it('should remove treatment variable when omitted from update', () => {
164
const service = new SimpleExperimentationService(false, new DefaultsOnlyConfigurationService());
165
166
// Set initial variables
167
const variables1: Record<string, boolean | number | string> = {
168
'feature-a': true,
169
'feature-b': 50,
170
'feature-c': 'test'
171
};
172
service.updateTreatmentVariables(variables1);
173
174
expect(service.getTreatmentVariable<boolean>('feature-a')).toBe(true);
175
expect(service.getTreatmentVariable<number>('feature-b')).toBe(50);
176
expect(service.getTreatmentVariable<string>('feature-c')).toBe('test');
177
178
const events: string[][] = [];
179
service.onDidTreatmentsChange((event) => {
180
events.push(event.affectedTreatmentVariables);
181
});
182
183
// Remove feature-b by omitting it
184
const variables2: Record<string, boolean | number | string> = {
185
'feature-a': true,
186
'feature-c': 'test'
187
};
188
service.updateTreatmentVariables(variables2);
189
190
expect(service.getTreatmentVariable<boolean>('feature-a')).toBe(true);
191
expect(service.getTreatmentVariable<number>('feature-b')).toBeUndefined();
192
expect(service.getTreatmentVariable<string>('feature-c')).toBe('test');
193
194
expect(events).toHaveLength(1);
195
expect(events[0]).toEqual(['feature-b']);
196
197
service.dispose();
198
});
199
});
200
201