webext-schema 6.0.0 → 7.0.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.
@@ -0,0 +1,1022 @@
1
+ /* api */
2
+ import { strict as assert } from 'node:assert';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import process from 'node:process';
6
+ import sinon from 'sinon';
7
+ import { afterEach, beforeEach, describe, it } from 'mocha';
8
+ import { MockAgent, getGlobalDispatcher, setGlobalDispatcher } from 'undici';
9
+
10
+ /* test */
11
+ import {
12
+ createUnifiedSchema, fetchText, getAllSchemaData, getChannelUrl, getFileList,
13
+ getListedSchemaData, getMailExtSchemaData, getSchemaData, saveSchemaFile,
14
+ updateSchemas
15
+ } from '../modules/update.js';
16
+
17
+ describe('fetch text', () => {
18
+ const globalDispatcher = getGlobalDispatcher();
19
+ const mockAgent = new MockAgent();
20
+ beforeEach(() => {
21
+ setGlobalDispatcher(mockAgent);
22
+ mockAgent.disableNetConnect();
23
+ });
24
+ afterEach(() => {
25
+ mockAgent.enableNetConnect();
26
+ setGlobalDispatcher(globalDispatcher);
27
+ });
28
+
29
+ it('should throw', async () => {
30
+ await fetchText().catch(e => {
31
+ assert.deepStrictEqual(e,
32
+ new TypeError('Expected String but got Undefined.'));
33
+ });
34
+ });
35
+
36
+ it('should throw', async () => {
37
+ const url = new URL('https://example.com');
38
+ mockAgent.get(url.origin).intercept({ path: url.pathname, method: 'GET' })
39
+ .reply(404, {
40
+ ok: false,
41
+ status: 404
42
+ });
43
+ await fetchText('https://example.com').catch(e => {
44
+ assert.deepStrictEqual(e,
45
+ new Error('Network response was not ok. status: 404'));
46
+ });
47
+ });
48
+
49
+ it('should get result', async () => {
50
+ const url = new URL('https://example.com');
51
+ mockAgent.get(url.origin).intercept({ path: url.pathname, method: 'GET' })
52
+ .reply(200, 'foo');
53
+ const res = await fetchText('https://example.com');
54
+ assert.strictEqual(res, 'foo', 'result');
55
+ });
56
+ });
57
+
58
+ describe('get channel url', () => {
59
+ it('should get result', () => {
60
+ const res = getChannelUrl();
61
+ assert.strictEqual(
62
+ res, 'https://hg.mozilla.org/releases/mozilla-beta/raw-file/tip/',
63
+ 'result'
64
+ );
65
+ });
66
+
67
+ it('should get result', () => {
68
+ const res = getChannelUrl('beta');
69
+ assert.strictEqual(
70
+ res, 'https://hg.mozilla.org/releases/mozilla-beta/raw-file/tip/',
71
+ 'result'
72
+ );
73
+ });
74
+
75
+ it('should get result', () => {
76
+ const res = getChannelUrl('central');
77
+ assert.strictEqual(
78
+ res, 'https://hg.mozilla.org/mozilla-central/raw-file/tip/',
79
+ 'result'
80
+ );
81
+ });
82
+
83
+ it('should get result', () => {
84
+ const res = getChannelUrl('mail');
85
+ assert.strictEqual(
86
+ res, 'https://hg.mozilla.org/comm-central/raw-file/tip/',
87
+ 'result'
88
+ );
89
+ });
90
+ });
91
+
92
+ describe('get schema data', () => {
93
+ const globalDispatcher = getGlobalDispatcher();
94
+ const mockAgent = new MockAgent();
95
+ beforeEach(() => {
96
+ setGlobalDispatcher(mockAgent);
97
+ mockAgent.disableNetConnect();
98
+ });
99
+ afterEach(() => {
100
+ mockAgent.enableNetConnect();
101
+ setGlobalDispatcher(globalDispatcher);
102
+ });
103
+
104
+ it('should throw', async () => {
105
+ await getSchemaData().catch(e => {
106
+ assert.deepStrictEqual(e,
107
+ new TypeError('Expected String but got Undefined.'));
108
+ });
109
+ });
110
+
111
+ it('should throw', async () => {
112
+ await getSchemaData('foo').catch(e => {
113
+ assert.deepStrictEqual(e,
114
+ new TypeError('Expected String but got Undefined.'));
115
+ });
116
+ });
117
+
118
+ it('should get object', async () => {
119
+ const url = new URL('https://example.com/foo.json');
120
+ mockAgent.get(url.origin).intercept({ path: url.pathname, method: 'GET' })
121
+ .reply(200, '{ "foo": [ "bar" ] }');
122
+ const res = await getSchemaData('foo.json', 'https://example.com');
123
+ assert.deepEqual(res, {
124
+ file: 'foo.json',
125
+ schema: {
126
+ foo: ['bar']
127
+ }
128
+ }, 'result');
129
+ });
130
+ });
131
+
132
+ describe('get schema file list from jar manifest', () => {
133
+ const globalDispatcher = getGlobalDispatcher();
134
+ const mockAgent = new MockAgent();
135
+ beforeEach(() => {
136
+ setGlobalDispatcher(mockAgent);
137
+ mockAgent.disableNetConnect();
138
+ });
139
+ afterEach(() => {
140
+ mockAgent.enableNetConnect();
141
+ setGlobalDispatcher(globalDispatcher);
142
+ });
143
+
144
+ it('should throw', async () => {
145
+ await getFileList().catch(e => {
146
+ assert.deepStrictEqual(e,
147
+ new TypeError('Expected String but got Undefined.'));
148
+ });
149
+ });
150
+
151
+ it('should get array', async () => {
152
+ const url = new URL('https://example.com/jar.mn');
153
+ mockAgent.get(url.origin).intercept({ path: url.pathname, method: 'GET' })
154
+ .reply(200, '# comment\n\ntoolkit.jar:\n% content extensions %content/extensions/\n content/extensions/schemas/alarms.json\n content/extensions/schemas/browser_settings.json\n#ifndef ANDROID\n content/extensions/schemas/geckoProfiler.json\n#endif\n content/extensions/schemas/i18n.json\n');
155
+ const res = await getFileList('https://example.com');
156
+ assert.deepEqual(res, [
157
+ 'alarms.json',
158
+ 'browser_settings.json',
159
+ 'geckoProfiler.json',
160
+ 'i18n.json'
161
+ ], 'result');
162
+ });
163
+ });
164
+
165
+ describe('get all schema data', () => {
166
+ const globalDispatcher = getGlobalDispatcher();
167
+ const mockAgent = new MockAgent();
168
+ beforeEach(() => {
169
+ setGlobalDispatcher(mockAgent);
170
+ mockAgent.disableNetConnect();
171
+ });
172
+ afterEach(() => {
173
+ mockAgent.enableNetConnect();
174
+ setGlobalDispatcher(globalDispatcher);
175
+ });
176
+
177
+ it('should throw', async () => {
178
+ await getAllSchemaData().catch(e => {
179
+ assert.deepStrictEqual(e,
180
+ new TypeError('Expected String but got Undefined.'));
181
+ });
182
+ });
183
+
184
+ it('should get array', async () => {
185
+ const stubInfo = sinon.stub(console, 'info');
186
+ const url = new URL('https://example.com');
187
+ const mockPool = mockAgent.get(url.origin);
188
+ mockPool.intercept({ path: '/jar.mn', method: 'GET' })
189
+ .reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
190
+ mockPool.intercept({ path: '/foo.json', method: 'GET' })
191
+ .reply(200, '{ "foo": "foobar" }');
192
+ mockPool.intercept({ path: '/bar.json', method: 'GET' })
193
+ .reply(200, '{ "baz": "qux" }');
194
+ const res = await getAllSchemaData('https://example.com/');
195
+ assert.strictEqual(stubInfo.called, false, 'info');
196
+ stubInfo.restore();
197
+ assert.deepEqual(res, [
198
+ {
199
+ file: 'foo.json',
200
+ schema: {
201
+ foo: 'foobar'
202
+ }
203
+ },
204
+ {
205
+ file: 'bar.json',
206
+ schema: {
207
+ baz: 'qux'
208
+ }
209
+ }
210
+ ], 'result');
211
+ });
212
+
213
+ it('should get array', async () => {
214
+ const stubInfo = sinon.stub(console, 'info');
215
+ const url = new URL('https://example.com');
216
+ const mockPool = mockAgent.get(url.origin);
217
+ mockPool.intercept({ path: '/jar.mn', method: 'GET' })
218
+ .reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
219
+ mockPool.intercept({ path: '/foo.json', method: 'GET' })
220
+ .reply(200, '{ "foo": "foobar" }');
221
+ mockPool.intercept({ path: '/bar.json', method: 'GET' })
222
+ .reply(200, '{ "baz": "qux" }');
223
+ const res = await getAllSchemaData('https://example.com/', true);
224
+ assert.strictEqual(stubInfo.called, true, 'info');
225
+ stubInfo.restore();
226
+ assert.deepEqual(res, [
227
+ {
228
+ file: 'foo.json',
229
+ schema: {
230
+ foo: 'foobar'
231
+ }
232
+ },
233
+ {
234
+ file: 'bar.json',
235
+ schema: {
236
+ baz: 'qux'
237
+ }
238
+ }
239
+ ], 'result');
240
+ });
241
+ });
242
+
243
+ describe('get listed schema data', () => {
244
+ const globalDispatcher = getGlobalDispatcher();
245
+ const mockAgent = new MockAgent();
246
+ beforeEach(() => {
247
+ setGlobalDispatcher(mockAgent);
248
+ mockAgent.disableNetConnect();
249
+ });
250
+ afterEach(() => {
251
+ mockAgent.enableNetConnect();
252
+ setGlobalDispatcher(globalDispatcher);
253
+ });
254
+
255
+ it('should throw', async () => {
256
+ await getListedSchemaData().catch(e => {
257
+ assert.deepStrictEqual(e,
258
+ new TypeError('Expected String but got Undefined.'));
259
+ });
260
+ });
261
+
262
+ it('should throw', async () => {
263
+ await getListedSchemaData('foo').catch(e => {
264
+ assert.deepStrictEqual(e,
265
+ new TypeError('Expected Array but got Undefined.'));
266
+ });
267
+ });
268
+
269
+ it('should get array', async () => {
270
+ const stubInfo = sinon.stub(console, 'info');
271
+ const url = new URL('https://example.com');
272
+ const mockPool = mockAgent.get(url.origin);
273
+ mockPool.intercept({ path: '/foo.json', method: 'GET' })
274
+ .reply(200, '{ "foo": "foobar" }');
275
+ mockPool.intercept({ path: '/bar.json', method: 'GET' })
276
+ .reply(200, '{ "baz": "qux" }');
277
+ const res = await getListedSchemaData('https://example.com/',
278
+ ['foo.json', 'bar.json']);
279
+ assert.strictEqual(stubInfo.called, false, 'info');
280
+ stubInfo.restore();
281
+ assert.deepEqual(res, [
282
+ {
283
+ file: 'foo.json',
284
+ schema: {
285
+ foo: 'foobar'
286
+ }
287
+ },
288
+ {
289
+ file: 'bar.json',
290
+ schema: {
291
+ baz: 'qux'
292
+ }
293
+ }
294
+ ], 'result');
295
+ });
296
+
297
+ it('should get array', async () => {
298
+ const stubInfo = sinon.stub(console, 'info');
299
+ const url = new URL('https://example.com');
300
+ const mockPool = mockAgent.get(url.origin);
301
+ mockPool.intercept({ path: '/foo.json', method: 'GET' })
302
+ .reply(200, '{ "foo": "foobar" }');
303
+ mockPool.intercept({ path: '/bar.json', method: 'GET' })
304
+ .reply(200, '{ "baz": "qux" }');
305
+ const res = await getListedSchemaData('https://example.com/',
306
+ ['foo.json', 'bar.json'], true);
307
+ assert.strictEqual(stubInfo.called, true, 'info');
308
+ stubInfo.restore();
309
+ assert.deepEqual(res, [
310
+ {
311
+ file: 'foo.json',
312
+ schema: {
313
+ foo: 'foobar'
314
+ }
315
+ },
316
+ {
317
+ file: 'bar.json',
318
+ schema: {
319
+ baz: 'qux'
320
+ }
321
+ }
322
+ ], 'result');
323
+ });
324
+ });
325
+
326
+ describe('get MailExtensions schema data', () => {
327
+ const globalDispatcher = getGlobalDispatcher();
328
+ const mockAgent = new MockAgent();
329
+ beforeEach(() => {
330
+ setGlobalDispatcher(mockAgent);
331
+ mockAgent.disableNetConnect();
332
+ });
333
+ afterEach(() => {
334
+ mockAgent.enableNetConnect();
335
+ setGlobalDispatcher(globalDispatcher);
336
+ });
337
+
338
+ it('should throw', async () => {
339
+ await getMailExtSchemaData().catch(e => {
340
+ assert.deepStrictEqual(e,
341
+ new TypeError('Expected String but got Undefined.'));
342
+ });
343
+ });
344
+
345
+ it('should get array', async () => {
346
+ const stubInfo = sinon.stub(console, 'info');
347
+ const url = new URL('https://example.com');
348
+ const mockPool = mockAgent.get(url.origin);
349
+ mockPool.intercept({ path: '/jar.mn', method: 'GET' })
350
+ .reply(200, '# comment\n\nmessenger.jar:\n% content/messenger/ext-mail.json\n content/messenger/schemas/accounts.json\n content/messenger/schemas/browserAction.json\n content/messenger/schemas/commands.json\n content/messenger/schemas/pkcs11.json\n');
351
+ mockPool.intercept({ path: '/schemas/accounts.json', method: 'GET' })
352
+ .reply(200, '{ "foo": "foobar" }');
353
+ mockPool.intercept({ path: '/schemas/browserAction.json', method: 'GET' })
354
+ .reply(200, '{ "bar": "baz" }');
355
+ const res = await getMailExtSchemaData('https://example.com/');
356
+ assert.strictEqual(stubInfo.called, false, 'info');
357
+ stubInfo.restore();
358
+ assert.deepEqual(res, [
359
+ {
360
+ file: 'accounts.json',
361
+ schema: {
362
+ foo: 'foobar'
363
+ }
364
+ },
365
+ {
366
+ file: 'browserAction.json',
367
+ schema: {
368
+ bar: 'baz'
369
+ }
370
+ }
371
+ ], 'result');
372
+ });
373
+
374
+ it('should get array', async () => {
375
+ const stubInfo = sinon.stub(console, 'info');
376
+ const url = new URL('https://example.com');
377
+ const mockPool = mockAgent.get(url.origin);
378
+ mockPool.intercept({ path: '/jar.mn', method: 'GET' })
379
+ .reply(200, '# comment\n\nmessenger.jar:\n% content/messenger/ext-mail.json\n content/messenger/schemas/accounts.json\n content/messenger/schemas/browserAction.json\n content/messenger/schemas/commands.json\n content/messenger/schemas/pkcs11.json\n');
380
+ mockPool.intercept({ path: '/schemas/accounts.json', method: 'GET' })
381
+ .reply(200, '{ "foo": "foobar" }');
382
+ mockPool.intercept({ path: '/schemas/browserAction.json', method: 'GET' })
383
+ .reply(200, '{ "bar": "baz" }');
384
+ const res = await getMailExtSchemaData('https://example.com/', true);
385
+ assert.strictEqual(stubInfo.called, true, 'info');
386
+ stubInfo.restore();
387
+ assert.deepEqual(res, [
388
+ {
389
+ file: 'accounts.json',
390
+ schema: {
391
+ foo: 'foobar'
392
+ }
393
+ },
394
+ {
395
+ file: 'browserAction.json',
396
+ schema: {
397
+ bar: 'baz'
398
+ }
399
+ }
400
+ ], 'result');
401
+ });
402
+ });
403
+
404
+ describe('create unified schema', () => {
405
+ const globalDispatcher = getGlobalDispatcher();
406
+ const mockAgent = new MockAgent();
407
+ beforeEach(() => {
408
+ setGlobalDispatcher(mockAgent);
409
+ mockAgent.disableNetConnect();
410
+ });
411
+ afterEach(() => {
412
+ mockAgent.enableNetConnect();
413
+ setGlobalDispatcher(globalDispatcher);
414
+ });
415
+
416
+ it('should get object', async () => {
417
+ const stubInfo = sinon.stub(console, 'info');
418
+ const url = new URL('https://hg.mozilla.org');
419
+ const mockPool = mockAgent.get(url.origin);
420
+ const basePath = '/releases/mozilla-beta/raw-file/tip/';
421
+ const browserUrl =
422
+ `${url.origin}${basePath}browser/components/extensions/schemas/`;
423
+ const toolkitUrl =
424
+ `${url.origin}${basePath}toolkit/components/extensions/schemas/`;
425
+ mockPool.intercept({ path: `${browserUrl}jar.mn`, method: 'GET' })
426
+ .reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
427
+ mockPool.intercept({ path: `${browserUrl}foo.json`, method: 'GET' })
428
+ .reply(200, '{ "foo": "Foo" }');
429
+ mockPool.intercept({ path: `${browserUrl}bar.json`, method: 'GET' })
430
+ .reply(200, '{ "bar": "Bar" }');
431
+ mockPool.intercept({ path: `${toolkitUrl}jar.mn`, method: 'GET' })
432
+ .reply(200, 'content/extensions/schemas/baz.json\ncontent/extensions/schemas/qux.json\n');
433
+ mockPool.intercept({ path: `${toolkitUrl}baz.json`, method: 'GET' })
434
+ .reply(200, '{ "baz": "Baz" }');
435
+ mockPool.intercept({ path: `${toolkitUrl}qux.json`, method: 'GET' })
436
+ .reply(200, '{ "qux": "Qux" }');
437
+ const res = await createUnifiedSchema();
438
+ assert.strictEqual(stubInfo.called, false, 'info');
439
+ stubInfo.restore();
440
+ assert.deepEqual(res, {
441
+ 'foo.json': {
442
+ foo: 'Foo'
443
+ },
444
+ 'bar.json': {
445
+ bar: 'Bar'
446
+ },
447
+ 'baz.json': {
448
+ baz: 'Baz'
449
+ },
450
+ 'qux.json': {
451
+ qux: 'Qux'
452
+ }
453
+ }, 'result');
454
+ });
455
+
456
+ it('should get object', async () => {
457
+ const stubInfo = sinon.stub(console, 'info');
458
+ const url = new URL('https://hg.mozilla.org');
459
+ const mockPool = mockAgent.get(url.origin);
460
+ const basePath = '/mozilla-central/raw-file/tip/';
461
+ const browserUrl =
462
+ `${url.origin}${basePath}browser/components/extensions/schemas/`;
463
+ const toolkitUrl =
464
+ `${url.origin}${basePath}toolkit/components/extensions/schemas/`;
465
+ mockPool.intercept({ path: `${browserUrl}jar.mn`, method: 'GET' })
466
+ .reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
467
+ mockPool.intercept({ path: `${browserUrl}foo.json`, method: 'GET' })
468
+ .reply(200, '{ "foo": "Foo" }');
469
+ mockPool.intercept({ path: `${browserUrl}bar.json`, method: 'GET' })
470
+ .reply(200, '{ "bar": "Bar" }');
471
+ mockPool.intercept({ path: `${toolkitUrl}jar.mn`, method: 'GET' })
472
+ .reply(200, 'content/extensions/schemas/baz.json\ncontent/extensions/schemas/qux.json\n');
473
+ mockPool.intercept({ path: `${toolkitUrl}baz.json`, method: 'GET' })
474
+ .reply(200, '{ "baz": "Baz" }');
475
+ mockPool.intercept({ path: `${toolkitUrl}qux.json`, method: 'GET' })
476
+ .reply(200, '{ "qux": "Qux" }');
477
+ const res = await createUnifiedSchema('central', true);
478
+ assert.strictEqual(stubInfo.called, true, 'info');
479
+ stubInfo.restore();
480
+ assert.deepEqual(res, {
481
+ 'foo.json': {
482
+ foo: 'Foo'
483
+ },
484
+ 'bar.json': {
485
+ bar: 'Bar'
486
+ },
487
+ 'baz.json': {
488
+ baz: 'Baz'
489
+ },
490
+ 'qux.json': {
491
+ qux: 'Qux'
492
+ }
493
+ }, 'result');
494
+ });
495
+
496
+ it('should get object', async () => {
497
+ const stubInfo = sinon.stub(console, 'info');
498
+ const url = new URL('https://hg.mozilla.org');
499
+ const mockPool = mockAgent.get(url.origin);
500
+ const basePath = '/mozilla-central/raw-file/tip/';
501
+ const mailBasePath = '/comm-central/raw-file/tip/';
502
+ const browserUrl =
503
+ `${url.origin}${basePath}browser/components/extensions/schemas/`;
504
+ const toolkitUrl =
505
+ `${url.origin}${basePath}toolkit/components/extensions/schemas/`;
506
+ const mailBaseUrl =
507
+ `${url.origin}${mailBasePath}mail/components/extensions/`;
508
+ const mailUrl = `${mailBaseUrl}schemas/`;
509
+ mockPool.intercept({ path: `${browserUrl}commands.json`, method: 'GET' })
510
+ .reply(200, '{ "commands": "Commands" }');
511
+ mockPool.intercept({ path: `${browserUrl}pkcs11.json`, method: 'GET' })
512
+ .reply(200, '{ "pkcs11": "Pkcs11" }');
513
+ mockPool.intercept({
514
+ path: `${toolkitUrl}content_scripts.json`,
515
+ method: 'GET'
516
+ }).reply(200, '{ "content_scripts": "ContentScripts" }');
517
+ mockPool.intercept({ path: `${toolkitUrl}experiments.json`, method: 'GET' })
518
+ .reply(200, '{ "experiments": "Experiments" }');
519
+ mockPool.intercept({ path: `${toolkitUrl}extension.json`, method: 'GET' })
520
+ .reply(200, '{ "extension": "Extension" }');
521
+ mockPool.intercept({ path: `${toolkitUrl}i18n.json`, method: 'GET' })
522
+ .reply(200, '{ "i18n": "I18n" }');
523
+ mockPool.intercept({ path: `${toolkitUrl}management.json`, method: 'GET' })
524
+ .reply(200, '{ "management": "Management" }');
525
+ mockPool.intercept({ path: `${toolkitUrl}permissions.json`, method: 'GET' })
526
+ .reply(200, '{ "permissions": "Permissions" }');
527
+ mockPool.intercept({ path: `${toolkitUrl}runtime.json`, method: 'GET' })
528
+ .reply(200, '{ "runtime": "Runtime" }');
529
+ mockPool.intercept({ path: `${toolkitUrl}theme.json`, method: 'GET' })
530
+ .reply(200, '{ "theme": "Theme" }');
531
+ mockPool.intercept({ path: `${mailBaseUrl}jar.mn`, method: 'GET' })
532
+ .reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
533
+ mockPool.intercept({ path: `${mailUrl}foo.json`, method: 'GET' })
534
+ .reply(200, '{ "foo": "Foo" }');
535
+ mockPool.intercept({ path: `${mailUrl}bar.json`, method: 'GET' })
536
+ .reply(200, '{ "bar": "Bar" }');
537
+ const res = await createUnifiedSchema('mail', true);
538
+ assert.strictEqual(stubInfo.called, true, 'info');
539
+ stubInfo.restore();
540
+ assert.deepEqual(res, {
541
+ 'commands.json': {
542
+ commands: 'Commands'
543
+ },
544
+ 'pkcs11.json': {
545
+ pkcs11: 'Pkcs11'
546
+ },
547
+ 'content_scripts.json': {
548
+ content_scripts: 'ContentScripts'
549
+ },
550
+ 'experiments.json': {
551
+ experiments: 'Experiments'
552
+ },
553
+ 'extension.json': {
554
+ extension: 'Extension'
555
+ },
556
+ 'i18n.json': {
557
+ i18n: 'I18n'
558
+ },
559
+ 'management.json': {
560
+ management: 'Management'
561
+ },
562
+ 'permissions.json': {
563
+ permissions: 'Permissions'
564
+ },
565
+ 'runtime.json': {
566
+ runtime: 'Runtime'
567
+ },
568
+ 'theme.json': {
569
+ theme: 'Theme'
570
+ },
571
+ 'foo.json': {
572
+ foo: 'Foo'
573
+ },
574
+ 'bar.json': {
575
+ bar: 'Bar'
576
+ }
577
+ }, 'result');
578
+ });
579
+ });
580
+
581
+ describe('save schema file', () => {
582
+ const globalDispatcher = getGlobalDispatcher();
583
+ const mockAgent = new MockAgent();
584
+ beforeEach(() => {
585
+ setGlobalDispatcher(mockAgent);
586
+ mockAgent.disableNetConnect();
587
+ });
588
+ afterEach(() => {
589
+ mockAgent.enableNetConnect();
590
+ setGlobalDispatcher(globalDispatcher);
591
+ });
592
+
593
+ it('should throw', async () => {
594
+ await saveSchemaFile().catch(e => {
595
+ assert.deepStrictEqual(e,
596
+ new TypeError('Expected String but got Undefined.'));
597
+ });
598
+ });
599
+
600
+ it('should create file', async () => {
601
+ const url = new URL('https://hg.mozilla.org/mozilla-central/raw-file/tip/');
602
+ const mockPool = mockAgent.get(url.origin);
603
+ const browserItems = [
604
+ 'commands.json',
605
+ 'pkcs11.json'
606
+ ];
607
+ for (const item of browserItems) {
608
+ mockPool.intercept({
609
+ path: `${url.pathname}browser/components/extensions/schemas/${item}`,
610
+ method: 'GET'
611
+ }).reply(200, `{ "browser": "${item}" }`);
612
+ }
613
+ const toolkitItems = [
614
+ 'content_scripts.json', 'experiments.json', 'extension.json', 'i18n.json',
615
+ 'management.json', 'permissions.json', 'runtime.json', 'theme.json'
616
+ ];
617
+ for (const item of toolkitItems) {
618
+ mockPool.intercept({
619
+ path: `${url.pathname}toolkit/components/extensions/schemas/${item}`,
620
+ method: 'GET'
621
+ }).reply(200, `{ "toolkit": "${item}" }`);
622
+ }
623
+ mockPool.intercept({
624
+ path: '/comm-central/raw-file/tip/mail/components/extensions/jar.mn',
625
+ method: 'GET'
626
+ }).reply(200, '# comment\n\nmessenger.jar:\n% content/messenger/ext-mail.json\n content/messenger/schemas/accounts.json\n');
627
+ mockPool.intercept({
628
+ path: '/comm-central/raw-file/tip/mail/components/extensions/schemas/accounts.json',
629
+ method: 'GET'
630
+ }).reply(200, '{ "mail": "accounts.json" }');
631
+ const stubWrite = sinon.stub(fs.promises, 'writeFile');
632
+ const stubInfo = sinon.stub(console, 'info');
633
+ const i = stubWrite.callCount;
634
+ const j = stubInfo.callCount;
635
+ const filePath =
636
+ path.join(process.cwd(), 'schemas', 'mail', 'mailext.json');
637
+ const res = await saveSchemaFile('mail');
638
+ const { callCount: writeCallCount } = stubWrite;
639
+ const { callCount: infoCallCount } = stubInfo;
640
+ stubInfo.restore();
641
+ stubWrite.restore();
642
+ assert.strictEqual(writeCallCount, i + 1, 'write');
643
+ assert.strictEqual(infoCallCount, j, 'info');
644
+ assert.strictEqual(res, filePath, 'result');
645
+ });
646
+
647
+ it('should create file', async () => {
648
+ const url = new URL('https://hg.mozilla.org/mozilla-central/raw-file/tip/');
649
+ const mockPool = mockAgent.get(url.origin);
650
+ const browserItems = [
651
+ 'commands.json',
652
+ 'pkcs11.json'
653
+ ];
654
+ for (const item of browserItems) {
655
+ mockPool.intercept({
656
+ path: `${url.pathname}browser/components/extensions/schemas/${item}`,
657
+ method: 'GET'
658
+ }).reply(200, `{ "browser": "${item}" }`);
659
+ }
660
+ const toolkitItems = [
661
+ 'content_scripts.json', 'experiments.json', 'extension.json', 'i18n.json',
662
+ 'management.json', 'permissions.json', 'runtime.json', 'theme.json'
663
+ ];
664
+ for (const item of toolkitItems) {
665
+ mockPool.intercept({
666
+ path: `${url.pathname}toolkit/components/extensions/schemas/${item}`,
667
+ method: 'GET'
668
+ }).reply(200, `{ "toolkit": "${item}" }`);
669
+ }
670
+ mockPool.intercept({
671
+ path: '/comm-central/raw-file/tip/mail/components/extensions/jar.mn',
672
+ method: 'GET'
673
+ }).reply(200, '# comment\n\nmessenger.jar:\n% content/messenger/ext-mail.json\n content/messenger/schemas/accounts.json\n');
674
+ mockPool.intercept({
675
+ path: '/comm-central/raw-file/tip/mail/components/extensions/schemas/accounts.json',
676
+ method: 'GET'
677
+ }).reply(200, '{ "mail": "accounts.json" }');
678
+ const stubWrite = sinon.stub(fs.promises, 'writeFile');
679
+ const stubInfo = sinon.stub(console, 'info');
680
+ const i = stubWrite.callCount;
681
+ const j = stubInfo.callCount;
682
+ const filePath =
683
+ path.join(process.cwd(), 'schemas', 'mail', 'mailext.json');
684
+ const res = await saveSchemaFile('mail', true);
685
+ const { callCount: writeCallCount } = stubWrite;
686
+ const { callCount: infoCallCount } = stubInfo;
687
+ stubInfo.restore();
688
+ stubWrite.restore();
689
+ assert.strictEqual(writeCallCount, i + 1, 'write');
690
+ assert.strictEqual(infoCallCount, j + 12, 'info');
691
+ assert.strictEqual(res, filePath, 'result');
692
+ });
693
+
694
+ it('should create file', async () => {
695
+ const url =
696
+ new URL('https://hg.mozilla.org/releases/mozilla-beta/raw-file/tip/');
697
+ const mockPool = mockAgent.get(url.origin);
698
+ mockPool.intercept({
699
+ path: `${url.pathname}browser/components/extensions/schemas/jar.mn`,
700
+ method: 'GET'
701
+ }).reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
702
+ mockPool.intercept({
703
+ path: `${url.pathname}browser/components/extensions/schemas/foo.json`,
704
+ method: 'GET'
705
+ }).reply(200, '{ "browser": "foo.json" }');
706
+ mockPool.intercept({
707
+ path: `${url.pathname}browser/components/extensions/schemas/bar.json`,
708
+ method: 'GET'
709
+ }).reply(200, '{ "browser": "bar.json" }');
710
+ mockPool.intercept({
711
+ path: `${url.pathname}toolkit/components/extensions/schemas/jar.mn`,
712
+ method: 'GET'
713
+ }).reply(200, 'content/extensions/schemas/baz.json\ncontent/extensions/schemas/qux.json\n');
714
+ mockPool.intercept({
715
+ path: `${url.pathname}toolkit/components/extensions/schemas/baz.json`,
716
+ method: 'GET'
717
+ }).reply(200, '{ "toolkit": "baz.json" }');
718
+ mockPool.intercept({
719
+ path: `${url.pathname}toolkit/components/extensions/schemas/qux.json`,
720
+ method: 'GET'
721
+ }).reply(200, '{ "toolkit": "qux.json" }');
722
+ const stubWrite = sinon.stub(fs.promises, 'writeFile');
723
+ const stubInfo = sinon.stub(console, 'info');
724
+ const i = stubWrite.callCount;
725
+ const j = stubInfo.callCount;
726
+ const filePath =
727
+ path.join(process.cwd(), 'schemas', 'beta', 'webext.json');
728
+ const res = await saveSchemaFile('beta');
729
+ const { callCount: writeCallCount } = stubWrite;
730
+ const { callCount: infoCallCount } = stubInfo;
731
+ stubInfo.restore();
732
+ stubWrite.restore();
733
+ assert.strictEqual(writeCallCount, i + 1, 'write');
734
+ assert.strictEqual(infoCallCount, j, 'info');
735
+ assert.strictEqual(res, filePath, 'result');
736
+ });
737
+
738
+ it('should create file', async () => {
739
+ const url =
740
+ new URL('https://hg.mozilla.org/releases/mozilla-beta/raw-file/tip/');
741
+ const mockPool = mockAgent.get(url.origin);
742
+ mockPool.intercept({
743
+ path: `${url.pathname}browser/components/extensions/schemas/jar.mn`,
744
+ method: 'GET'
745
+ }).reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
746
+ mockPool.intercept({
747
+ path: `${url.pathname}browser/components/extensions/schemas/foo.json`,
748
+ method: 'GET'
749
+ }).reply(200, '{ "browser": "foo.json" }');
750
+ mockPool.intercept({
751
+ path: `${url.pathname}browser/components/extensions/schemas/bar.json`,
752
+ method: 'GET'
753
+ }).reply(200, '{ "browser": "bar.json" }');
754
+ mockPool.intercept({
755
+ path: `${url.pathname}toolkit/components/extensions/schemas/jar.mn`,
756
+ method: 'GET'
757
+ }).reply(200, 'content/extensions/schemas/baz.json\ncontent/extensions/schemas/qux.json\n');
758
+ mockPool.intercept({
759
+ path: `${url.pathname}toolkit/components/extensions/schemas/baz.json`,
760
+ method: 'GET'
761
+ }).reply(200, '{ "toolkit": "baz.json" }');
762
+ mockPool.intercept({
763
+ path: `${url.pathname}toolkit/components/extensions/schemas/qux.json`,
764
+ method: 'GET'
765
+ }).reply(200, '{ "toolkit": "qux.json" }');
766
+ const stubWrite = sinon.stub(fs.promises, 'writeFile');
767
+ const stubInfo = sinon.stub(console, 'info');
768
+ const i = stubWrite.callCount;
769
+ const j = stubInfo.callCount;
770
+ const filePath =
771
+ path.join(process.cwd(), 'schemas', 'beta', 'webext.json');
772
+ const res = await saveSchemaFile('beta', true);
773
+ const { callCount: writeCallCount } = stubWrite;
774
+ const { callCount: infoCallCount } = stubInfo;
775
+ stubInfo.restore();
776
+ stubWrite.restore();
777
+ assert.strictEqual(writeCallCount, i + 1, 'write');
778
+ assert.strictEqual(infoCallCount, j + 5, 'info');
779
+ assert.strictEqual(res, filePath, 'result');
780
+ });
781
+ });
782
+
783
+ describe('update schemas files', () => {
784
+ const globalDispatcher = getGlobalDispatcher();
785
+ const mockAgent = new MockAgent();
786
+ beforeEach(() => {
787
+ setGlobalDispatcher(mockAgent);
788
+ mockAgent.disableNetConnect();
789
+ });
790
+ afterEach(() => {
791
+ mockAgent.enableNetConnect();
792
+ setGlobalDispatcher(globalDispatcher);
793
+ });
794
+
795
+ it('should not call function', async () => {
796
+ const url = new URL('https://hg.mozilla.org/mozilla-central/raw-file/tip/');
797
+ const centralPath = url.pathname;
798
+ const betaPath = '/releases/mozilla-beta/raw-file/tip/';
799
+ const mailPath = '/comm-central/raw-file/tip/';
800
+ const mockPool = mockAgent.get(url.origin);
801
+ for (const item of [centralPath, betaPath]) {
802
+ mockPool.intercept({
803
+ path: `${item}browser/components/extensions/schemas/jar.mn`,
804
+ method: 'GET'
805
+ }).reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
806
+ mockPool.intercept({
807
+ path: `${item}browser/components/extensions/schemas/foo.json`,
808
+ method: 'GET'
809
+ }).reply(200, '{ "browser": "foo.json" }');
810
+ mockPool.intercept({
811
+ path: `${item}browser/components/extensions/schemas/bar.json`,
812
+ method: 'GET'
813
+ }).reply(200, '{ "browser": "bar.json" }');
814
+ mockPool.intercept({
815
+ path: `${item}toolkit/components/extensions/schemas/jar.mn`,
816
+ method: 'GET'
817
+ }).reply(200, 'content/extensions/schemas/baz.json\ncontent/extensions/schemas/qux.json\n');
818
+ mockPool.intercept({
819
+ path: `${item}toolkit/components/extensions/schemas/baz.json`,
820
+ method: 'GET'
821
+ }).reply(200, '{ "toolkit": "baz.json" }');
822
+ mockPool.intercept({
823
+ path: `${item}toolkit/components/extensions/schemas/qux.json`,
824
+ method: 'GET'
825
+ }).reply(200, '{ "toolkit": "qux.json" }');
826
+ }
827
+ const browserItems = [
828
+ 'commands.json',
829
+ 'pkcs11.json'
830
+ ];
831
+ for (const item of browserItems) {
832
+ mockPool.intercept({
833
+ path: `${centralPath}browser/components/extensions/schemas/${item}`,
834
+ method: 'GET'
835
+ }).reply(200, `{ "browser": "${item}" }`);
836
+ }
837
+ const toolkitItems = [
838
+ 'content_scripts.json', 'experiments.json', 'extension.json', 'i18n.json',
839
+ 'management.json', 'permissions.json', 'runtime.json', 'theme.json'
840
+ ];
841
+ for (const item of toolkitItems) {
842
+ mockPool.intercept({
843
+ path: `${centralPath}toolkit/components/extensions/schemas/${item}`,
844
+ method: 'GET'
845
+ }).reply(200, `{ "toolkit": "${item}" }`);
846
+ }
847
+ mockPool.intercept({
848
+ path: `${mailPath}mail/components/extensions/jar.mn`,
849
+ method: 'GET'
850
+ }).reply(200, 'content/messenger/schemas/quux.json\n');
851
+ mockPool.intercept({
852
+ path: `${mailPath}mail/components/extensions/schemas/quux.json`,
853
+ method: 'GET'
854
+ }).reply(200, '{ "mail": "quux.json" }');
855
+ const stubWrite = sinon.stub(fs.promises, 'writeFile');
856
+ const stubTrace = sinon.stub(console, 'trace');
857
+ const i = stubTrace.callCount;
858
+ const stubInfo = sinon.stub(console, 'info');
859
+ await updateSchemas();
860
+ const { callCount: traceCallCount } = stubTrace;
861
+ stubWrite.restore();
862
+ stubTrace.restore();
863
+ stubInfo.restore();
864
+ assert.strictEqual(traceCallCount, i, 'trace not called');
865
+ });
866
+
867
+ it('should not call function', async () => {
868
+ const url = new URL('https://hg.mozilla.org/mozilla-central/raw-file/tip/');
869
+ const centralPath = url.pathname;
870
+ const betaPath = '/releases/mozilla-beta/raw-file/tip/';
871
+ const mailPath = '/comm-central/raw-file/tip/';
872
+ const mockPool = mockAgent.get(url.origin);
873
+ for (const item of [centralPath, betaPath]) {
874
+ mockPool.intercept({
875
+ path: `${item}browser/components/extensions/schemas/jar.mn`,
876
+ method: 'GET'
877
+ }).reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
878
+ mockPool.intercept({
879
+ path: `${item}browser/components/extensions/schemas/foo.json`,
880
+ method: 'GET'
881
+ }).reply(200, '{ "browser": "foo.json" }');
882
+ mockPool.intercept({
883
+ path: `${item}browser/components/extensions/schemas/bar.json`,
884
+ method: 'GET'
885
+ }).reply(200, '{ "browser": "bar.json" }');
886
+ mockPool.intercept({
887
+ path: `${item}toolkit/components/extensions/schemas/jar.mn`,
888
+ method: 'GET'
889
+ }).reply(200, 'content/extensions/schemas/baz.json\ncontent/extensions/schemas/qux.json\n');
890
+ mockPool.intercept({
891
+ path: `${item}toolkit/components/extensions/schemas/baz.json`,
892
+ method: 'GET'
893
+ }).reply(200, '{ "toolkit": "baz.json" }');
894
+ mockPool.intercept({
895
+ path: `${item}toolkit/components/extensions/schemas/qux.json`,
896
+ method: 'GET'
897
+ }).reply(200, '{ "toolkit": "qux.json" }');
898
+ }
899
+ const browserItems = [
900
+ 'commands.json',
901
+ 'pkcs11.json'
902
+ ];
903
+ for (const item of browserItems) {
904
+ mockPool.intercept({
905
+ path: `${centralPath}browser/components/extensions/schemas/${item}`,
906
+ method: 'GET'
907
+ }).reply(200, `{ "browser": "${item}" }`);
908
+ }
909
+ const toolkitItems = [
910
+ 'content_scripts.json', 'experiments.json', 'extension.json', 'i18n.json',
911
+ 'management.json', 'permissions.json', 'runtime.json', 'theme.json'
912
+ ];
913
+ for (const item of toolkitItems) {
914
+ mockPool.intercept({
915
+ path: `${centralPath}toolkit/components/extensions/schemas/${item}`,
916
+ method: 'GET'
917
+ }).reply(200, `{ "toolkit": "${item}" }`);
918
+ }
919
+ mockPool.intercept({
920
+ path: `${mailPath}mail/components/extensions/jar.mn`,
921
+ method: 'GET'
922
+ }).reply(200, 'content/messenger/schemas/quux.json\n');
923
+ mockPool.intercept({
924
+ path: `${mailPath}mail/components/extensions/schemas/quux.json`,
925
+ method: 'GET'
926
+ }).reply(400, '{ "ok": false, "status": 400 }');
927
+ const stubWrite = sinon.stub(fs.promises, 'writeFile');
928
+ const stubTrace = sinon.stub(console, 'trace');
929
+ const i = stubTrace.callCount;
930
+ const stubInfo = sinon.stub(console, 'info');
931
+ await updateSchemas();
932
+ const { callCount: traceCallCount } = stubTrace;
933
+ stubWrite.restore();
934
+ stubTrace.restore();
935
+ stubInfo.restore();
936
+ assert.strictEqual(traceCallCount, i + 1, 'trace called');
937
+ });
938
+
939
+ it('should not call function', async () => {
940
+ const url =
941
+ new URL('https://hg.mozilla.org/releases/mozilla-beta/raw-file/tip/');
942
+ const mockPool = mockAgent.get(url.origin);
943
+ mockPool.intercept({
944
+ path: `${url.pathname}browser/components/extensions/schemas/jar.mn`,
945
+ method: 'GET'
946
+ }).reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
947
+ mockPool.intercept({
948
+ path: `${url.pathname}browser/components/extensions/schemas/foo.json`,
949
+ method: 'GET'
950
+ }).reply(200, '{ "browser": "foo.json" }');
951
+ mockPool.intercept({
952
+ path: `${url.pathname}browser/components/extensions/schemas/bar.json`,
953
+ method: 'GET'
954
+ }).reply(200, '{ "browser": "bar.json" }');
955
+ mockPool.intercept({
956
+ path: `${url.pathname}toolkit/components/extensions/schemas/jar.mn`,
957
+ method: 'GET'
958
+ }).reply(200, 'content/extensions/schemas/baz.json\ncontent/extensions/schemas/qux.json\n');
959
+ mockPool.intercept({
960
+ path: `${url.pathname}toolkit/components/extensions/schemas/baz.json`,
961
+ method: 'GET'
962
+ }).reply(200, '{ "toolkit": "baz.json" }');
963
+ mockPool.intercept({
964
+ path: `${url.pathname}toolkit/components/extensions/schemas/qux.json`,
965
+ method: 'GET'
966
+ }).reply(200, '{ "toolkit": "qux.json" }');
967
+ const stubWrite = sinon.stub(fs.promises, 'writeFile');
968
+ const stubTrace = sinon.stub(console, 'trace');
969
+ const i = stubTrace.callCount;
970
+ const stubInfo = sinon.stub(console, 'info');
971
+ await updateSchemas({
972
+ channel: 'beta'
973
+ });
974
+ const { callCount: traceCallCount } = stubTrace;
975
+ stubWrite.restore();
976
+ stubTrace.restore();
977
+ stubInfo.restore();
978
+ assert.strictEqual(traceCallCount, i, 'trace not called');
979
+ });
980
+
981
+ it('should not call function', async () => {
982
+ const url =
983
+ new URL('https://hg.mozilla.org/releases/mozilla-beta/raw-file/tip/');
984
+ const mockPool = mockAgent.get(url.origin);
985
+ mockPool.intercept({
986
+ path: `${url.pathname}browser/components/extensions/schemas/jar.mn`,
987
+ method: 'GET'
988
+ }).reply(200, 'content/extensions/schemas/foo.json\ncontent/extensions/schemas/bar.json\n');
989
+ mockPool.intercept({
990
+ path: `${url.pathname}browser/components/extensions/schemas/foo.json`,
991
+ method: 'GET'
992
+ }).reply(200, '{ "browser": "foo.json" }');
993
+ mockPool.intercept({
994
+ path: `${url.pathname}browser/components/extensions/schemas/bar.json`,
995
+ method: 'GET'
996
+ }).reply(200, '{ "browser": "bar.json" }');
997
+ mockPool.intercept({
998
+ path: `${url.pathname}toolkit/components/extensions/schemas/jar.mn`,
999
+ method: 'GET'
1000
+ }).reply(200, 'content/extensions/schemas/baz.json\ncontent/extensions/schemas/qux.json\n');
1001
+ mockPool.intercept({
1002
+ path: `${url.pathname}toolkit/components/extensions/schemas/baz.json`,
1003
+ method: 'GET'
1004
+ }).reply(200, '{ "toolkit": "baz.json" }');
1005
+ mockPool.intercept({
1006
+ path: `${url.pathname}toolkit/components/extensions/schemas/qux.json`,
1007
+ method: 'GET'
1008
+ }).reply(400, '{ "ok": false, "status": 400 }');
1009
+ const stubWrite = sinon.stub(fs.promises, 'writeFile');
1010
+ const stubTrace = sinon.stub(console, 'trace');
1011
+ const i = stubTrace.callCount;
1012
+ const stubInfo = sinon.stub(console, 'info');
1013
+ await updateSchemas({
1014
+ channel: 'beta'
1015
+ });
1016
+ const { callCount: traceCallCount } = stubTrace;
1017
+ stubWrite.restore();
1018
+ stubTrace.restore();
1019
+ stubInfo.restore();
1020
+ assert.strictEqual(traceCallCount, i + 1, 'trace called');
1021
+ });
1022
+ });