Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/lib/test/render.test.ts
4772 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 { renderADMLString, renderProfileString, renderADMX, renderADML, renderProfileManifest, renderMacOSPolicy, renderGP, renderJsonPolicies } from '../policies/render.ts';
8
import { type NlsString, type LanguageTranslations, type Category, type Policy, PolicyType } from '../policies/types.ts';
9
10
suite('Render Functions', () => {
11
12
suite('renderADMLString', () => {
13
14
test('should render ADML string without translations', () => {
15
const nlsString: NlsString = {
16
value: 'Test description',
17
nlsKey: 'test.description'
18
};
19
20
const result = renderADMLString('TestPrefix', 'testModule', nlsString);
21
22
assert.strictEqual(result, '<string id="TestPrefix_test_description">Test description</string>');
23
});
24
25
test('should replace dots with underscores in nls key', () => {
26
const nlsString: NlsString = {
27
value: 'Test value',
28
nlsKey: 'my.test.nls.key'
29
};
30
31
const result = renderADMLString('Prefix', 'testModule', nlsString);
32
33
assert.ok(result.includes('id="Prefix_my_test_nls_key"'));
34
});
35
36
test('should use translation when available', () => {
37
const nlsString: NlsString = {
38
value: 'Original value',
39
nlsKey: 'test.key'
40
};
41
42
const translations: LanguageTranslations = {
43
'testModule': {
44
'test.key': 'Translated value'
45
}
46
};
47
48
const result = renderADMLString('TestPrefix', 'testModule', nlsString, translations);
49
50
assert.ok(result.includes('>Translated value</string>'));
51
});
52
53
test('should fallback to original value when translation not found', () => {
54
const nlsString: NlsString = {
55
value: 'Original value',
56
nlsKey: 'test.key'
57
};
58
59
const translations: LanguageTranslations = {
60
'testModule': {
61
'other.key': 'Other translation'
62
}
63
};
64
65
const result = renderADMLString('TestPrefix', 'testModule', nlsString, translations);
66
67
assert.ok(result.includes('>Original value</string>'));
68
});
69
});
70
71
suite('renderProfileString', () => {
72
73
test('should render profile string without translations', () => {
74
const nlsString: NlsString = {
75
value: 'Profile description',
76
nlsKey: 'profile.description'
77
};
78
79
const result = renderProfileString('ProfilePrefix', 'testModule', nlsString);
80
81
assert.strictEqual(result, 'Profile description');
82
});
83
84
test('should use translation when available', () => {
85
const nlsString: NlsString = {
86
value: 'Original profile value',
87
nlsKey: 'profile.key'
88
};
89
90
const translations: LanguageTranslations = {
91
'testModule': {
92
'profile.key': 'Translated profile value'
93
}
94
};
95
96
const result = renderProfileString('ProfilePrefix', 'testModule', nlsString, translations);
97
98
assert.strictEqual(result, 'Translated profile value');
99
});
100
101
test('should fallback to original value when translation not found', () => {
102
const nlsString: NlsString = {
103
value: 'Original profile value',
104
nlsKey: 'profile.key'
105
};
106
107
const translations: LanguageTranslations = {
108
'testModule': {
109
'other.key': 'Other translation'
110
}
111
};
112
113
const result = renderProfileString('ProfilePrefix', 'testModule', nlsString, translations);
114
115
assert.strictEqual(result, 'Original profile value');
116
});
117
});
118
119
suite('renderADMX', () => {
120
121
const mockCategory: Category = {
122
moduleName: 'testModule',
123
name: { value: 'Test Category', nlsKey: 'test.category' }
124
};
125
126
const mockPolicy: Policy = {
127
name: 'TestPolicy',
128
type: PolicyType.Boolean,
129
category: mockCategory,
130
minimumVersion: '1.85',
131
renderADMX: (regKey: string) => [
132
`<policy name="TestPolicy" class="Both" displayName="$(string.TestPolicy)" key="Software\\Policies\\Microsoft\\${regKey}">`,
133
` <enabledValue><decimal value="1" /></enabledValue>`,
134
`</policy>`
135
],
136
renderADMLStrings: () => ['<string id="TestPolicy">Test Policy</string>'],
137
renderADMLPresentation: () => '<presentation id="TestPolicy"/>',
138
renderProfile: () => ['<key>TestPolicy</key>', '<true/>'],
139
renderProfileManifest: () => '<dict><key>pfm_name</key><string>TestPolicy</string></dict>',
140
renderJsonValue: () => null
141
};
142
143
test('should render ADMX with correct XML structure', () => {
144
const result = renderADMX('VSCode', ['1.85'], [mockCategory], [mockPolicy]);
145
146
assert.ok(result.includes('<?xml version="1.0" encoding="utf-8"?>'));
147
assert.ok(result.includes('<policyDefinitions'));
148
assert.ok(result.includes('</policyDefinitions>'));
149
});
150
151
test('should include policy namespaces with regKey', () => {
152
const result = renderADMX('TestApp', ['1.0'], [mockCategory], [mockPolicy]);
153
154
assert.ok(result.includes('<target prefix="TestApp" namespace="Microsoft.Policies.TestApp"'));
155
});
156
157
test('should replace dots in versions with underscores', () => {
158
const result = renderADMX('VSCode', ['1.85.0', '1.90.1'], [mockCategory], [mockPolicy]);
159
160
assert.ok(result.includes('Supported_1_85_0'));
161
assert.ok(result.includes('Supported_1_90_1'));
162
assert.ok(!result.includes('Supported_1.85.0'));
163
});
164
165
test('should include categories in correct structure', () => {
166
const result = renderADMX('VSCode', ['1.0'], [mockCategory], [mockPolicy]);
167
168
assert.ok(result.includes('<categories>'));
169
assert.ok(result.includes('<category displayName="$(string.Application)" name="Application"'));
170
assert.ok(result.includes(`<category displayName="$(string.Category_${mockCategory.name.nlsKey})"`));
171
assert.ok(result.includes('</categories>'));
172
});
173
174
test('should include policies section', () => {
175
const result = renderADMX('VSCode', ['1.0'], [mockCategory], [mockPolicy]);
176
177
assert.ok(result.includes('<policies>'));
178
assert.ok(result.includes('TestPolicy'));
179
assert.ok(result.includes('</policies>'));
180
});
181
182
test('should handle multiple versions', () => {
183
const result = renderADMX('VSCode', ['1.0', '1.5', '2.0'], [mockCategory], [mockPolicy]);
184
185
assert.ok(result.includes('Supported_1_0'));
186
assert.ok(result.includes('Supported_1_5'));
187
assert.ok(result.includes('Supported_2_0'));
188
});
189
190
test('should handle multiple categories', () => {
191
const category1: Category = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } };
192
const category2: Category = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } };
193
194
const result = renderADMX('VSCode', ['1.0'], [category1, category2], [mockPolicy]);
195
196
assert.ok(result.includes('Category_cat1'));
197
assert.ok(result.includes('Category_cat2'));
198
});
199
200
test('should handle multiple policies', () => {
201
const policy2: Policy = {
202
name: 'TestPolicy2',
203
type: PolicyType.String,
204
category: mockCategory,
205
minimumVersion: '1.85',
206
renderADMX: (regKey: string) => [
207
`<policy name="TestPolicy2" class="Both" displayName="$(string.TestPolicy2)" key="Software\\Policies\\Microsoft\\${regKey}">`,
208
` <enabledValue><string /></enabledValue>`,
209
`</policy>`
210
],
211
renderADMLStrings: () => ['<string id="TestPolicy2">Test Policy 2</string>'],
212
renderADMLPresentation: () => '<presentation id="TestPolicy2"/>',
213
renderProfile: () => ['<key>TestPolicy2</key>', '<string/>'],
214
renderProfileManifest: () => '<dict><key>pfm_name</key><string>TestPolicy2</string></dict>',
215
renderJsonValue: () => null
216
};
217
const result = renderADMX('VSCode', ['1.0'], [mockCategory], [mockPolicy, policy2]);
218
219
assert.ok(result.includes('TestPolicy'));
220
assert.ok(result.includes('TestPolicy2'));
221
});
222
});
223
224
suite('renderADML', () => {
225
226
const mockCategory: Category = {
227
moduleName: 'testModule',
228
name: { value: 'Test Category', nlsKey: 'test.category' }
229
};
230
231
const mockPolicy: Policy = {
232
name: 'TestPolicy',
233
type: PolicyType.String,
234
category: mockCategory,
235
minimumVersion: '1.85',
236
renderADMX: () => [],
237
renderADMLStrings: (translations?: LanguageTranslations) => [
238
`<string id="TestPolicy">Test Policy ${translations?.['testModule']?.['test.policy'] || 'Default'}</string>`
239
],
240
renderADMLPresentation: () => '<presentation id="TestPolicy"><textBox refId="TestPolicy"/></presentation>',
241
renderProfile: () => [],
242
renderProfileManifest: () => '',
243
renderJsonValue: () => null
244
};
245
246
test('should render ADML with correct XML structure', () => {
247
const result = renderADML('VS Code', ['1.85'], [mockCategory], [mockPolicy]);
248
249
assert.ok(result.includes('<?xml version="1.0" encoding="utf-8"?>'));
250
assert.ok(result.includes('<policyDefinitionResources'));
251
assert.ok(result.includes('</policyDefinitionResources>'));
252
});
253
254
test('should include application name', () => {
255
const result = renderADML('My Application', ['1.0'], [mockCategory], [mockPolicy]);
256
257
assert.ok(result.includes('<string id="Application">My Application</string>'));
258
});
259
260
test('should include supported versions with escaped greater-than', () => {
261
const result = renderADML('VS Code', ['1.85', '1.90'], [mockCategory], [mockPolicy]);
262
263
assert.ok(result.includes('VS Code &gt;= 1.85'));
264
assert.ok(result.includes('VS Code &gt;= 1.90'));
265
});
266
267
test('should include category strings', () => {
268
const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy]);
269
270
assert.ok(result.includes('Category_test_category'));
271
});
272
273
test('should include policy strings', () => {
274
const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy]);
275
276
assert.ok(result.includes('TestPolicy'));
277
assert.ok(result.includes('Test Policy Default'));
278
});
279
280
test('should include policy presentations', () => {
281
const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy]);
282
283
assert.ok(result.includes('<presentationTable>'));
284
assert.ok(result.includes('<presentation id="TestPolicy">'));
285
assert.ok(result.includes('</presentationTable>'));
286
});
287
288
test('should pass translations to policy strings', () => {
289
const translations: LanguageTranslations = {
290
'testModule': {
291
'test.policy': 'Translated'
292
}
293
};
294
295
const result = renderADML('VS Code', ['1.0'], [mockCategory], [mockPolicy], translations);
296
297
assert.ok(result.includes('Test Policy Translated'));
298
});
299
300
test('should handle multiple categories', () => {
301
const category1: Category = { moduleName: 'testModule', name: { value: 'Cat1', nlsKey: 'cat1' } };
302
const category2: Category = { moduleName: 'testModule', name: { value: 'Cat2', nlsKey: 'cat2' } };
303
304
const result = renderADML('VS Code', ['1.0'], [category1, category2], [mockPolicy]);
305
306
assert.ok(result.includes('Category_cat1'));
307
assert.ok(result.includes('Category_cat2'));
308
});
309
});
310
311
suite('renderProfileManifest', () => {
312
313
const mockCategory: Category = {
314
moduleName: 'testModule',
315
name: { value: 'Test Category', nlsKey: 'test.category' }
316
};
317
318
const mockPolicy: Policy = {
319
name: 'TestPolicy',
320
type: PolicyType.Boolean,
321
category: mockCategory,
322
minimumVersion: '1.0',
323
renderADMX: () => [],
324
renderADMLStrings: () => [],
325
renderADMLPresentation: () => '',
326
renderProfile: () => [],
327
renderProfileManifest: (translations?: LanguageTranslations) => `<dict>
328
<key>pfm_name</key>
329
<string>TestPolicy</string>
330
<key>pfm_description</key>
331
<string>${translations?.['testModule']?.['test.desc'] || 'Default Desc'}</string>
332
</dict>`,
333
renderJsonValue: () => null
334
};
335
336
test('should render profile manifest with correct XML structure', () => {
337
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
338
339
assert.ok(result.includes('<?xml version="1.0" encoding="UTF-8"?>'));
340
assert.ok(result.includes('<!DOCTYPE plist PUBLIC'));
341
assert.ok(result.includes('<plist version="1.0">'));
342
assert.ok(result.includes('</plist>'));
343
});
344
345
test('should include app name', () => {
346
const result = renderProfileManifest('My App', 'com.example.myapp', ['1.0'], [mockCategory], [mockPolicy]);
347
348
assert.ok(result.includes('<string>My App Managed Settings</string>'));
349
assert.ok(result.includes('<string>My App</string>'));
350
});
351
352
test('should include bundle identifier', () => {
353
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
354
355
assert.ok(result.includes('<string>com.microsoft.vscode</string>'));
356
});
357
358
test('should include required payload fields', () => {
359
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
360
361
assert.ok(result.includes('PayloadDescription'));
362
assert.ok(result.includes('PayloadDisplayName'));
363
assert.ok(result.includes('PayloadIdentifier'));
364
assert.ok(result.includes('PayloadType'));
365
assert.ok(result.includes('PayloadUUID'));
366
assert.ok(result.includes('PayloadVersion'));
367
assert.ok(result.includes('PayloadOrganization'));
368
});
369
370
test('should include policy manifests in subkeys', () => {
371
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
372
373
assert.ok(result.includes('<key>pfm_subkeys</key>'));
374
assert.ok(result.includes('TestPolicy'));
375
assert.ok(result.includes('Default Desc'));
376
});
377
378
test('should pass translations to policy manifests', () => {
379
const translations: LanguageTranslations = {
380
'testModule': {
381
'test.desc': 'Translated Description'
382
}
383
};
384
385
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy], translations);
386
387
assert.ok(result.includes('Translated Description'));
388
});
389
390
test('should include VS Code specific URLs', () => {
391
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
392
393
assert.ok(result.includes('https://code.visualstudio.com/'));
394
assert.ok(result.includes('https://code.visualstudio.com/docs/setup/enterprise'));
395
});
396
397
test('should include last modified date', () => {
398
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
399
400
assert.ok(result.includes('<key>pfm_last_modified</key>'));
401
assert.ok(result.includes('<date>'));
402
});
403
404
test('should mark manifest as unique', () => {
405
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
406
407
assert.ok(result.includes('<key>pfm_unique</key>'));
408
assert.ok(result.includes('<true/>'));
409
});
410
411
test('should handle multiple policies', () => {
412
const policy2: Policy = {
413
...mockPolicy,
414
name: 'TestPolicy2',
415
renderProfileManifest: () => `<dict>
416
<key>pfm_name</key>
417
<string>TestPolicy2</string>
418
</dict>`
419
};
420
421
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy, policy2]);
422
423
assert.ok(result.includes('TestPolicy'));
424
assert.ok(result.includes('TestPolicy2'));
425
});
426
427
test('should set format version to 1', () => {
428
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
429
430
assert.ok(result.includes('<key>pfm_format_version</key>'));
431
assert.ok(result.includes('<integer>1</integer>'));
432
});
433
434
test('should set interaction to combined', () => {
435
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
436
437
assert.ok(result.includes('<key>pfm_interaction</key>'));
438
assert.ok(result.includes('<string>combined</string>'));
439
});
440
441
test('should set platform to macOS', () => {
442
const result = renderProfileManifest('VS Code', 'com.microsoft.vscode', ['1.0'], [mockCategory], [mockPolicy]);
443
444
assert.ok(result.includes('<key>pfm_platforms</key>'));
445
assert.ok(result.includes('<string>macOS</string>'));
446
});
447
});
448
449
suite('renderMacOSPolicy', () => {
450
451
const mockCategory: Category = {
452
moduleName: 'testModule',
453
name: { value: 'Test Category', nlsKey: 'test.category' }
454
};
455
456
const mockPolicy: Policy = {
457
name: 'TestPolicy',
458
type: PolicyType.Boolean,
459
category: mockCategory,
460
minimumVersion: '1.0',
461
renderADMX: () => [],
462
renderADMLStrings: () => [],
463
renderADMLPresentation: () => '',
464
renderProfile: () => ['<key>TestPolicy</key>', '<true/>'],
465
renderProfileManifest: (translations?: LanguageTranslations) => `<dict>
466
<key>pfm_name</key>
467
<string>TestPolicy</string>
468
<key>pfm_description</key>
469
<string>${translations?.['testModule']?.['test.desc'] || 'Default Desc'}</string>
470
</dict>`,
471
renderJsonValue: () => null
472
};
473
474
test('should render complete macOS policy profile', () => {
475
const product = {
476
nameLong: 'VS Code',
477
darwinBundleIdentifier: 'com.microsoft.vscode',
478
darwinProfilePayloadUUID: 'payload-uuid',
479
darwinProfileUUID: 'uuid',
480
win32RegValueName: 'VSCode'
481
};
482
const result = renderMacOSPolicy(product, [mockPolicy], []);
483
484
const expected = `<?xml version="1.0" encoding="UTF-8"?>
485
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
486
<plist version="1.0">
487
<dict>
488
<key>PayloadContent</key>
489
<array>
490
<dict>
491
<key>PayloadDisplayName</key>
492
<string>VS Code</string>
493
<key>PayloadIdentifier</key>
494
<string>com.microsoft.vscode.uuid</string>
495
<key>PayloadType</key>
496
<string>com.microsoft.vscode</string>
497
<key>PayloadUUID</key>
498
<string>uuid</string>
499
<key>PayloadVersion</key>
500
<integer>1</integer>
501
<key>TestPolicy</key>
502
<true/>
503
</dict>
504
</array>
505
<key>PayloadDescription</key>
506
<string>This profile manages VS Code. For more information see https://code.visualstudio.com/docs/setup/enterprise</string>
507
<key>PayloadDisplayName</key>
508
<string>VS Code</string>
509
<key>PayloadIdentifier</key>
510
<string>com.microsoft.vscode</string>
511
<key>PayloadOrganization</key>
512
<string>Microsoft</string>
513
<key>PayloadType</key>
514
<string>Configuration</string>
515
<key>PayloadUUID</key>
516
<string>payload-uuid</string>
517
<key>PayloadVersion</key>
518
<integer>1</integer>
519
<key>TargetDeviceType</key>
520
<integer>5</integer>
521
</dict>
522
</plist>`;
523
524
assert.strictEqual(result.profile, expected);
525
});
526
527
test('should include en-us manifest by default', () => {
528
const product = {
529
nameLong: 'VS Code',
530
darwinBundleIdentifier: 'com.microsoft.vscode',
531
darwinProfilePayloadUUID: 'payload-uuid',
532
darwinProfileUUID: 'uuid',
533
win32RegValueName: 'VSCode'
534
};
535
const result = renderMacOSPolicy(product, [mockPolicy], []);
536
537
assert.strictEqual(result.manifests.length, 1);
538
assert.strictEqual(result.manifests[0].languageId, 'en-us');
539
assert.ok(result.manifests[0].contents.includes('VS Code Managed Settings'));
540
});
541
542
test('should include translations', () => {
543
const product = {
544
nameLong: 'VS Code',
545
darwinBundleIdentifier: 'com.microsoft.vscode',
546
darwinProfilePayloadUUID: 'payload-uuid',
547
darwinProfileUUID: 'uuid',
548
win32RegValueName: 'VSCode'
549
};
550
const translations = [
551
{ languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.desc': 'Description Française' } } },
552
{ languageId: 'de-de', languageTranslations: { 'testModule': { 'test.desc': 'Deutsche Beschreibung' } } }
553
];
554
555
const result = renderMacOSPolicy(product, [mockPolicy], translations);
556
557
assert.strictEqual(result.manifests.length, 3); // en-us + 2 translations
558
assert.strictEqual(result.manifests[0].languageId, 'en-us');
559
assert.strictEqual(result.manifests[1].languageId, 'fr-fr');
560
assert.strictEqual(result.manifests[2].languageId, 'de-de');
561
562
assert.ok(result.manifests[1].contents.includes('Description Française'));
563
assert.ok(result.manifests[2].contents.includes('Deutsche Beschreibung'));
564
});
565
566
test('should handle multiple policies with correct indentation', () => {
567
const policy2: Policy = {
568
...mockPolicy,
569
name: 'TestPolicy2',
570
renderProfile: () => ['<key>TestPolicy2</key>', '<string>test value</string>']
571
};
572
573
const product = {
574
nameLong: 'VS Code',
575
darwinBundleIdentifier: 'com.microsoft.vscode',
576
darwinProfilePayloadUUID: 'payload-uuid',
577
darwinProfileUUID: 'uuid',
578
win32RegValueName: 'VSCode'
579
};
580
const result = renderMacOSPolicy(product, [mockPolicy, policy2], []);
581
582
assert.ok(result.profile.includes('<key>TestPolicy</key>'));
583
assert.ok(result.profile.includes('<true/>'));
584
assert.ok(result.profile.includes('<key>TestPolicy2</key>'));
585
assert.ok(result.profile.includes('<string>test value</string>'));
586
});
587
588
test('should use provided UUIDs in profile', () => {
589
const product = {
590
nameLong: 'My App',
591
darwinBundleIdentifier: 'com.example.app',
592
darwinProfilePayloadUUID: 'custom-payload-uuid',
593
darwinProfileUUID: 'custom-uuid',
594
win32RegValueName: 'VSCode'
595
};
596
const result = renderMacOSPolicy(product, [mockPolicy], []);
597
598
assert.ok(result.profile.includes('<string>custom-payload-uuid</string>'));
599
assert.ok(result.profile.includes('<string>custom-uuid</string>'));
600
assert.ok(result.profile.includes('<string>com.example.app.custom-uuid</string>'));
601
});
602
603
test('should include enterprise documentation link', () => {
604
const product = {
605
nameLong: 'VS Code',
606
darwinBundleIdentifier: 'com.microsoft.vscode',
607
darwinProfilePayloadUUID: 'payload-uuid',
608
darwinProfileUUID: 'uuid',
609
win32RegValueName: 'VSCode'
610
};
611
const result = renderMacOSPolicy(product, [mockPolicy], []);
612
613
assert.ok(result.profile.includes('https://code.visualstudio.com/docs/setup/enterprise'));
614
});
615
616
test('should set TargetDeviceType to 5', () => {
617
const product = {
618
nameLong: 'VS Code',
619
darwinBundleIdentifier: 'com.microsoft.vscode',
620
darwinProfilePayloadUUID: 'payload-uuid',
621
darwinProfileUUID: 'uuid',
622
win32RegValueName: 'VSCode'
623
};
624
const result = renderMacOSPolicy(product, [mockPolicy], []);
625
626
assert.ok(result.profile.includes('<key>TargetDeviceType</key>'));
627
assert.ok(result.profile.includes('<integer>5</integer>'));
628
});
629
});
630
631
suite('renderGP', () => {
632
633
const mockCategory: Category = {
634
moduleName: 'testModule',
635
name: { value: 'Test Category', nlsKey: 'test.category' }
636
};
637
638
const mockPolicy: Policy = {
639
name: 'TestPolicy',
640
type: PolicyType.Boolean,
641
category: mockCategory,
642
minimumVersion: '1.85',
643
renderADMX: (regKey: string) => [
644
`<policy name="TestPolicy" class="Both" displayName="$(string.TestPolicy)" key="Software\\Policies\\Microsoft\\${regKey}">`,
645
` <enabledValue><decimal value="1" /></enabledValue>`,
646
`</policy>`
647
],
648
renderADMLStrings: (translations?: LanguageTranslations) => [
649
`<string id="TestPolicy">${translations?.['testModule']?.['test.policy'] || 'Test Policy'}</string>`
650
],
651
renderADMLPresentation: () => '<presentation id="TestPolicy"/>',
652
renderProfile: () => [],
653
renderProfileManifest: () => '',
654
renderJsonValue: () => null
655
};
656
657
test('should render complete GP with ADMX and ADML', () => {
658
const product = {
659
nameLong: 'VS Code',
660
darwinBundleIdentifier: 'com.microsoft.vscode',
661
darwinProfilePayloadUUID: 'payload-uuid',
662
darwinProfileUUID: 'uuid',
663
win32RegValueName: 'VSCode'
664
};
665
const result = renderGP(product, [mockPolicy], []);
666
667
assert.ok(result.admx);
668
assert.ok(result.adml);
669
assert.ok(Array.isArray(result.adml));
670
});
671
672
test('should include regKey in ADMX', () => {
673
const product = {
674
nameLong: 'VS Code',
675
darwinBundleIdentifier: 'com.microsoft.vscode',
676
darwinProfilePayloadUUID: 'payload-uuid',
677
darwinProfileUUID: 'uuid',
678
win32RegValueName: 'CustomRegKey'
679
};
680
const result = renderGP(product, [mockPolicy], []);
681
682
assert.ok(result.admx.includes('CustomRegKey'));
683
assert.ok(result.admx.includes('Software\\Policies\\Microsoft\\CustomRegKey'));
684
});
685
686
test('should include en-us ADML by default', () => {
687
const product = {
688
nameLong: 'VS Code',
689
darwinBundleIdentifier: 'com.microsoft.vscode',
690
darwinProfilePayloadUUID: 'payload-uuid',
691
darwinProfileUUID: 'uuid',
692
win32RegValueName: 'VSCode'
693
};
694
const result = renderGP(product, [mockPolicy], []);
695
696
assert.strictEqual(result.adml.length, 1);
697
assert.strictEqual(result.adml[0].languageId, 'en-us');
698
assert.ok(result.adml[0].contents.includes('VS Code'));
699
});
700
701
test('should include translations in ADML', () => {
702
const product = {
703
nameLong: 'VS Code',
704
darwinBundleIdentifier: 'com.microsoft.vscode',
705
darwinProfilePayloadUUID: 'payload-uuid',
706
darwinProfileUUID: 'uuid',
707
win32RegValueName: 'VSCode'
708
};
709
const translations = [
710
{ languageId: 'fr-fr', languageTranslations: { 'testModule': { 'test.policy': 'Politique de test' } } },
711
{ languageId: 'de-de', languageTranslations: { 'testModule': { 'test.policy': 'Testrichtlinie' } } }
712
];
713
714
const result = renderGP(product, [mockPolicy], translations);
715
716
assert.strictEqual(result.adml.length, 3); // en-us + 2 translations
717
assert.strictEqual(result.adml[0].languageId, 'en-us');
718
assert.strictEqual(result.adml[1].languageId, 'fr-fr');
719
assert.strictEqual(result.adml[2].languageId, 'de-de');
720
721
assert.ok(result.adml[1].contents.includes('Politique de test'));
722
assert.ok(result.adml[2].contents.includes('Testrichtlinie'));
723
});
724
725
test('should pass versions to ADMX', () => {
726
const product = {
727
nameLong: 'VS Code',
728
darwinBundleIdentifier: 'com.microsoft.vscode',
729
darwinProfilePayloadUUID: 'payload-uuid',
730
darwinProfileUUID: 'uuid',
731
win32RegValueName: 'VSCode'
732
};
733
const result = renderGP(product, [mockPolicy], []);
734
735
assert.ok(result.admx.includes('Supported_1_85'));
736
});
737
738
test('should pass versions to ADML', () => {
739
const product = {
740
nameLong: 'VS Code',
741
darwinBundleIdentifier: 'com.microsoft.vscode',
742
darwinProfilePayloadUUID: 'payload-uuid',
743
darwinProfileUUID: 'uuid',
744
win32RegValueName: 'VSCode'
745
};
746
const result = renderGP(product, [mockPolicy], []);
747
748
assert.ok(result.adml[0].contents.includes('VS Code &gt;= 1.85'));
749
});
750
751
test('should pass categories to ADMX', () => {
752
const product = {
753
nameLong: 'VS Code',
754
darwinBundleIdentifier: 'com.microsoft.vscode',
755
darwinProfilePayloadUUID: 'payload-uuid',
756
darwinProfileUUID: 'uuid',
757
win32RegValueName: 'VSCode'
758
};
759
const result = renderGP(product, [mockPolicy], []);
760
761
assert.ok(result.admx.includes('test.category'));
762
});
763
764
test('should pass categories to ADML', () => {
765
const product = {
766
nameLong: 'VS Code',
767
darwinBundleIdentifier: 'com.microsoft.vscode',
768
darwinProfilePayloadUUID: 'payload-uuid',
769
darwinProfileUUID: 'uuid',
770
win32RegValueName: 'VSCode'
771
};
772
const result = renderGP(product, [mockPolicy], []);
773
774
assert.ok(result.adml[0].contents.includes('Category_test_category'));
775
});
776
777
test('should handle multiple policies', () => {
778
const policy2: Policy = {
779
...mockPolicy,
780
name: 'TestPolicy2',
781
renderADMX: (regKey: string) => [
782
`<policy name="TestPolicy2" class="Both" displayName="$(string.TestPolicy2)" key="Software\\Policies\\Microsoft\\${regKey}">`,
783
` <enabledValue><decimal value="1" /></enabledValue>`,
784
`</policy>`
785
],
786
renderADMLStrings: () => ['<string id="TestPolicy2">Test Policy 2</string>']
787
};
788
789
const product = {
790
nameLong: 'VS Code',
791
darwinBundleIdentifier: 'com.microsoft.vscode',
792
darwinProfilePayloadUUID: 'payload-uuid',
793
darwinProfileUUID: 'uuid',
794
win32RegValueName: 'VSCode'
795
};
796
const result = renderGP(product, [mockPolicy, policy2], []);
797
798
assert.ok(result.admx.includes('TestPolicy'));
799
assert.ok(result.admx.includes('TestPolicy2'));
800
assert.ok(result.adml[0].contents.includes('TestPolicy'));
801
assert.ok(result.adml[0].contents.includes('TestPolicy2'));
802
});
803
804
test('should include app name in ADML', () => {
805
const product = {
806
nameLong: 'My Custom App',
807
darwinBundleIdentifier: 'com.microsoft.vscode',
808
darwinProfilePayloadUUID: 'payload-uuid',
809
darwinProfileUUID: 'uuid',
810
win32RegValueName: 'VSCode'
811
};
812
const result = renderGP(product, [mockPolicy], []);
813
814
assert.ok(result.adml[0].contents.includes('My Custom App'));
815
});
816
817
test('should return structured result with admx and adml properties', () => {
818
const product = {
819
nameLong: 'VS Code',
820
darwinBundleIdentifier: 'com.microsoft.vscode',
821
darwinProfilePayloadUUID: 'payload-uuid',
822
darwinProfileUUID: 'uuid',
823
win32RegValueName: 'VSCode'
824
};
825
const result = renderGP(product, [mockPolicy], []);
826
827
assert.ok('admx' in result);
828
assert.ok('adml' in result);
829
assert.strictEqual(typeof result.admx, 'string');
830
assert.ok(Array.isArray(result.adml));
831
});
832
});
833
834
suite('renderJsonPolicies', () => {
835
836
const mockCategory: Category = {
837
moduleName: 'testModule',
838
name: { value: 'Test Category', nlsKey: 'test.category' }
839
};
840
841
test('should render boolean policy JSON value', () => {
842
const booleanPolicy: Policy = {
843
name: 'BooleanPolicy',
844
type: PolicyType.Boolean,
845
category: mockCategory,
846
minimumVersion: '1.0',
847
renderADMX: () => [],
848
renderADMLStrings: () => [],
849
renderADMLPresentation: () => '',
850
renderProfile: () => [],
851
renderProfileManifest: () => '',
852
renderJsonValue: () => false
853
};
854
855
const result = renderJsonPolicies([booleanPolicy]);
856
857
assert.deepStrictEqual(result, { BooleanPolicy: false });
858
});
859
860
test('should render number policy JSON value', () => {
861
const numberPolicy: Policy = {
862
name: 'NumberPolicy',
863
type: PolicyType.Number,
864
category: mockCategory,
865
minimumVersion: '1.0',
866
renderADMX: () => [],
867
renderADMLStrings: () => [],
868
renderADMLPresentation: () => '',
869
renderProfile: () => [],
870
renderProfileManifest: () => '',
871
renderJsonValue: () => 42
872
};
873
874
const result = renderJsonPolicies([numberPolicy]);
875
876
assert.deepStrictEqual(result, { NumberPolicy: 42 });
877
});
878
879
test('should render string policy JSON value', () => {
880
const stringPolicy: Policy = {
881
name: 'StringPolicy',
882
type: PolicyType.String,
883
category: mockCategory,
884
minimumVersion: '1.0',
885
renderADMX: () => [],
886
renderADMLStrings: () => [],
887
renderADMLPresentation: () => '',
888
renderProfile: () => [],
889
renderProfileManifest: () => '',
890
renderJsonValue: () => ''
891
};
892
893
const result = renderJsonPolicies([stringPolicy]);
894
895
assert.deepStrictEqual(result, { StringPolicy: '' });
896
});
897
898
test('should render string enum policy JSON value', () => {
899
const stringEnumPolicy: Policy = {
900
name: 'StringEnumPolicy',
901
type: PolicyType.StringEnum,
902
category: mockCategory,
903
minimumVersion: '1.0',
904
renderADMX: () => [],
905
renderADMLStrings: () => [],
906
renderADMLPresentation: () => '',
907
renderProfile: () => [],
908
renderProfileManifest: () => '',
909
renderJsonValue: () => 'auto'
910
};
911
912
const result = renderJsonPolicies([stringEnumPolicy]);
913
914
assert.deepStrictEqual(result, { StringEnumPolicy: 'auto' });
915
});
916
917
test('should render object policy JSON value', () => {
918
const objectPolicy: Policy = {
919
name: 'ObjectPolicy',
920
type: PolicyType.Object,
921
category: mockCategory,
922
minimumVersion: '1.0',
923
renderADMX: () => [],
924
renderADMLStrings: () => [],
925
renderADMLPresentation: () => '',
926
renderProfile: () => [],
927
renderProfileManifest: () => '',
928
renderJsonValue: () => ''
929
};
930
931
const result = renderJsonPolicies([objectPolicy]);
932
933
assert.deepStrictEqual(result, { ObjectPolicy: '' });
934
});
935
936
test('should render multiple policies', () => {
937
const booleanPolicy: Policy = {
938
name: 'BooleanPolicy',
939
type: PolicyType.Boolean,
940
category: mockCategory,
941
minimumVersion: '1.0',
942
renderADMX: () => [],
943
renderADMLStrings: () => [],
944
renderADMLPresentation: () => '',
945
renderProfile: () => [],
946
renderProfileManifest: () => '',
947
renderJsonValue: () => true
948
};
949
950
const numberPolicy: Policy = {
951
name: 'NumberPolicy',
952
type: PolicyType.Number,
953
category: mockCategory,
954
minimumVersion: '1.0',
955
renderADMX: () => [],
956
renderADMLStrings: () => [],
957
renderADMLPresentation: () => '',
958
renderProfile: () => [],
959
renderProfileManifest: () => '',
960
renderJsonValue: () => 100
961
};
962
963
const stringPolicy: Policy = {
964
name: 'StringPolicy',
965
type: PolicyType.String,
966
category: mockCategory,
967
minimumVersion: '1.0',
968
renderADMX: () => [],
969
renderADMLStrings: () => [],
970
renderADMLPresentation: () => '',
971
renderProfile: () => [],
972
renderProfileManifest: () => '',
973
renderJsonValue: () => 'test-value'
974
};
975
976
const result = renderJsonPolicies([booleanPolicy, numberPolicy, stringPolicy]);
977
978
assert.deepStrictEqual(result, {
979
BooleanPolicy: true,
980
NumberPolicy: 100,
981
StringPolicy: 'test-value'
982
});
983
});
984
985
test('should handle empty policies array', () => {
986
const result = renderJsonPolicies([]);
987
988
assert.deepStrictEqual(result, {});
989
});
990
991
test('should handle null JSON value', () => {
992
const nullPolicy: Policy = {
993
name: 'NullPolicy',
994
type: PolicyType.String,
995
category: mockCategory,
996
minimumVersion: '1.0',
997
renderADMX: () => [],
998
renderADMLStrings: () => [],
999
renderADMLPresentation: () => '',
1000
renderProfile: () => [],
1001
renderProfileManifest: () => '',
1002
renderJsonValue: () => null
1003
};
1004
1005
const result = renderJsonPolicies([nullPolicy]);
1006
1007
assert.deepStrictEqual(result, { NullPolicy: null });
1008
});
1009
1010
test('should handle object JSON value', () => {
1011
const objectPolicy: Policy = {
1012
name: 'ComplexObjectPolicy',
1013
type: PolicyType.Object,
1014
category: mockCategory,
1015
minimumVersion: '1.0',
1016
renderADMX: () => [],
1017
renderADMLStrings: () => [],
1018
renderADMLPresentation: () => '',
1019
renderProfile: () => [],
1020
renderProfileManifest: () => '',
1021
renderJsonValue: () => ({ nested: { value: 123 } })
1022
};
1023
1024
const result = renderJsonPolicies([objectPolicy]);
1025
1026
assert.deepStrictEqual(result, { ComplexObjectPolicy: { nested: { value: 123 } } });
1027
});
1028
});
1029
});
1030
1031