webext-schema 7.0.0 → 7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/node.js.yml +2 -2
- package/.prettierignore +8 -0
- package/README.md +37 -6
- package/SECURITY.md +30 -0
- package/eslint.config.mjs +27 -19
- package/index.js +9 -3
- package/modules/browser.js +81 -25
- package/modules/commander.js +8 -5
- package/modules/common.js +1 -1
- package/modules/file-util.js +23 -10
- package/modules/schema.js +21 -14
- package/modules/update.js +34 -23
- package/package.json +25 -24
- package/prettier.config.mjs +14 -0
- package/schemas/beta/webext.json +902 -204
- package/schemas/central/webext.json +902 -204
- package/schemas/mail/mailext.json +552 -17
- package/test/browser.test.js +1045 -495
- package/test/commander.test.js +7 -21
- package/test/common.test.js +7 -1
- package/test/file-util.test.js +65 -35
- package/test/index.test.js +55 -1
- package/test/schema.test.js +839 -430
- package/test/update.test.js +872 -511
- package/types/index.d.ts +8 -1
- package/types/modules/browser.d.ts +61 -61
- package/types/modules/commander.d.ts +3 -3
- package/types/modules/common.d.ts +7 -7
- package/types/modules/constant.d.ts +3 -3
- package/types/modules/file-util.d.ts +16 -16
- package/types/modules/schema.d.ts +6 -6
- package/types/modules/update.d.ts +10 -10
package/test/commander.test.js
CHANGED
|
@@ -7,7 +7,9 @@ import { describe, it } from 'mocha';
|
|
|
7
7
|
|
|
8
8
|
/* test */
|
|
9
9
|
import {
|
|
10
|
-
commander,
|
|
10
|
+
commander,
|
|
11
|
+
cleanDirectory,
|
|
12
|
+
parseCommand
|
|
11
13
|
} from '../modules/commander.js';
|
|
12
14
|
|
|
13
15
|
describe('clean directory', () => {
|
|
@@ -67,11 +69,7 @@ describe('parse command', () => {
|
|
|
67
69
|
it('should not parse', () => {
|
|
68
70
|
const stubParse = sinon.stub(commander, 'parse');
|
|
69
71
|
const i = stubParse.callCount;
|
|
70
|
-
parseCommand([
|
|
71
|
-
'foo',
|
|
72
|
-
'bar',
|
|
73
|
-
'baz'
|
|
74
|
-
]);
|
|
72
|
+
parseCommand(['foo', 'bar', 'baz']);
|
|
75
73
|
assert.strictEqual(stubParse.callCount, i, 'not called');
|
|
76
74
|
stubParse.restore();
|
|
77
75
|
});
|
|
@@ -81,11 +79,7 @@ describe('parse command', () => {
|
|
|
81
79
|
const stubVer = sinon.stub(commander, 'version');
|
|
82
80
|
const i = stubParse.callCount;
|
|
83
81
|
const j = stubVer.callCount;
|
|
84
|
-
parseCommand([
|
|
85
|
-
'foo',
|
|
86
|
-
'bar',
|
|
87
|
-
'-v'
|
|
88
|
-
]);
|
|
82
|
+
parseCommand(['foo', 'bar', '-v']);
|
|
89
83
|
assert.strictEqual(stubParse.callCount, i + 1, 'called');
|
|
90
84
|
assert.strictEqual(stubVer.callCount, j + 1, 'called');
|
|
91
85
|
stubParse.restore();
|
|
@@ -99,11 +93,7 @@ describe('parse command', () => {
|
|
|
99
93
|
const i = stubParse.callCount;
|
|
100
94
|
const j = stubVer.callCount;
|
|
101
95
|
const k = spyCmd.callCount;
|
|
102
|
-
parseCommand([
|
|
103
|
-
'foo',
|
|
104
|
-
'bar',
|
|
105
|
-
'clean'
|
|
106
|
-
]);
|
|
96
|
+
parseCommand(['foo', 'bar', 'clean']);
|
|
107
97
|
assert.strictEqual(stubParse.callCount, i + 1, 'called');
|
|
108
98
|
assert.strictEqual(stubVer.callCount, j + 1, 'called');
|
|
109
99
|
assert.strictEqual(spyCmd.callCount, k + 1, 'called');
|
|
@@ -119,11 +109,7 @@ describe('parse command', () => {
|
|
|
119
109
|
const i = stubParse.callCount;
|
|
120
110
|
const j = stubVer.callCount;
|
|
121
111
|
const k = spyCmd.callCount;
|
|
122
|
-
parseCommand([
|
|
123
|
-
'foo',
|
|
124
|
-
'bar',
|
|
125
|
-
'update'
|
|
126
|
-
]);
|
|
112
|
+
parseCommand(['foo', 'bar', 'update']);
|
|
127
113
|
assert.strictEqual(stubParse.callCount, i + 1, 'called');
|
|
128
114
|
assert.strictEqual(stubVer.callCount, j + 1, 'called');
|
|
129
115
|
assert.strictEqual(spyCmd.callCount, k + 1, 'called');
|
package/test/common.test.js
CHANGED
|
@@ -5,7 +5,13 @@ import { describe, it } from 'mocha';
|
|
|
5
5
|
|
|
6
6
|
/* test */
|
|
7
7
|
import {
|
|
8
|
-
getType,
|
|
8
|
+
getType,
|
|
9
|
+
isObjectNotEmpty,
|
|
10
|
+
isString,
|
|
11
|
+
logErr,
|
|
12
|
+
logMsg,
|
|
13
|
+
logWarn,
|
|
14
|
+
throwErr
|
|
9
15
|
} from '../modules/common.js';
|
|
10
16
|
|
|
11
17
|
describe('getType', () => {
|
package/test/file-util.test.js
CHANGED
|
@@ -9,17 +9,28 @@ import { IS_WIN } from '../modules/constant.js';
|
|
|
9
9
|
|
|
10
10
|
/* test */
|
|
11
11
|
import {
|
|
12
|
-
convertUriToFilePath,
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
convertUriToFilePath,
|
|
13
|
+
createDirectory,
|
|
14
|
+
createFile,
|
|
15
|
+
getAbsPath,
|
|
16
|
+
getFileNameFromFilePath,
|
|
17
|
+
getFileTimestamp,
|
|
18
|
+
getStat,
|
|
19
|
+
isDir,
|
|
20
|
+
isExecutable,
|
|
21
|
+
isFile,
|
|
22
|
+
isSubDir,
|
|
23
|
+
removeDir,
|
|
24
|
+
removeDirectory,
|
|
25
|
+
readFile
|
|
15
26
|
} from '../modules/file-util.js';
|
|
16
27
|
|
|
17
28
|
/* constants */
|
|
18
29
|
const DIR_CWD = process.cwd();
|
|
19
30
|
const PERM_EXEC = 0o700;
|
|
20
31
|
const PERM_FILE = 0o600;
|
|
21
|
-
const TMPDIR =
|
|
22
|
-
|
|
32
|
+
const TMPDIR =
|
|
33
|
+
process.env.TMP || process.env.TMPDIR || process.env.TEMP || os.tmpdir();
|
|
23
34
|
|
|
24
35
|
describe('convertUriToFilePath', () => {
|
|
25
36
|
it('should get string', () => {
|
|
@@ -71,8 +82,11 @@ describe('convertUriToFilePath', () => {
|
|
|
71
82
|
});
|
|
72
83
|
|
|
73
84
|
it('should throw if string is not given', () => {
|
|
74
|
-
assert.throws(
|
|
75
|
-
|
|
85
|
+
assert.throws(
|
|
86
|
+
() => convertUriToFilePath(),
|
|
87
|
+
TypeError,
|
|
88
|
+
'Expected String but got Undefined'
|
|
89
|
+
);
|
|
76
90
|
});
|
|
77
91
|
|
|
78
92
|
it('should get null if protocol does not match', () => {
|
|
@@ -92,15 +106,19 @@ describe('createDirectory', () => {
|
|
|
92
106
|
|
|
93
107
|
it('should throw if given argument is not a string', async () => {
|
|
94
108
|
await createDirectory().catch(e => {
|
|
95
|
-
assert.deepStrictEqual(
|
|
96
|
-
|
|
109
|
+
assert.deepStrictEqual(
|
|
110
|
+
e,
|
|
111
|
+
new TypeError('Expected String but got Undefined.')
|
|
112
|
+
);
|
|
97
113
|
});
|
|
98
114
|
});
|
|
99
115
|
|
|
100
116
|
it('should throw if given second argument is not a number', async () => {
|
|
101
117
|
await createDirectory('/foo/bar', 'baz').catch(e => {
|
|
102
|
-
assert.deepStrictEqual(
|
|
103
|
-
|
|
118
|
+
assert.deepStrictEqual(
|
|
119
|
+
e,
|
|
120
|
+
new TypeError('Expected Number but got String.')
|
|
121
|
+
);
|
|
104
122
|
});
|
|
105
123
|
});
|
|
106
124
|
});
|
|
@@ -112,7 +130,9 @@ describe('createFile', () => {
|
|
|
112
130
|
const filePath = path.join(dirPath, 'test.txt');
|
|
113
131
|
const value = 'test file.\n';
|
|
114
132
|
const file = await createFile(filePath, value, {
|
|
115
|
-
encoding: 'utf8',
|
|
133
|
+
encoding: 'utf8',
|
|
134
|
+
flag: 'w',
|
|
135
|
+
mode: PERM_FILE
|
|
116
136
|
});
|
|
117
137
|
assert.strictEqual(file, filePath);
|
|
118
138
|
fs.unlinkSync(file);
|
|
@@ -121,21 +141,22 @@ describe('createFile', () => {
|
|
|
121
141
|
|
|
122
142
|
it('should throw if first argument is not a string', () => {
|
|
123
143
|
createFile().catch(e => {
|
|
124
|
-
assert.deepStrictEqual(
|
|
125
|
-
|
|
144
|
+
assert.deepStrictEqual(
|
|
145
|
+
e,
|
|
146
|
+
new TypeError('Expected String but got Undefined.')
|
|
147
|
+
);
|
|
126
148
|
});
|
|
127
149
|
});
|
|
128
150
|
|
|
129
|
-
it(
|
|
130
|
-
|
|
131
|
-
() => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
);
|
|
151
|
+
it('should throw if second argument is not string, buffer, uint8array', () => {
|
|
152
|
+
const file = path.join(TMPDIR, 'webext-schema', 'test.txt');
|
|
153
|
+
createFile(file).catch(e => {
|
|
154
|
+
assert.deepStrictEqual(
|
|
155
|
+
e,
|
|
156
|
+
new TypeError('Expected String, Buffer, Uint8Array but got Undefined.')
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
139
160
|
});
|
|
140
161
|
|
|
141
162
|
describe('removeDir', () => {
|
|
@@ -147,7 +168,9 @@ describe('removeDir', () => {
|
|
|
147
168
|
const filePath = path.join(subDirPath, 'test.txt');
|
|
148
169
|
const value = 'test file.\n';
|
|
149
170
|
await createFile(filePath, value, {
|
|
150
|
-
encoding: 'utf8',
|
|
171
|
+
encoding: 'utf8',
|
|
172
|
+
flag: 'w',
|
|
173
|
+
mode: PERM_FILE
|
|
151
174
|
});
|
|
152
175
|
const res1 = await Promise.all([
|
|
153
176
|
fs.existsSync(dirPath),
|
|
@@ -175,8 +198,11 @@ describe('removeDir', () => {
|
|
|
175
198
|
const foo = path.join(TMPDIR, 'foo');
|
|
176
199
|
await fs.mkdirSync(dirPath);
|
|
177
200
|
await fs.mkdirSync(foo);
|
|
178
|
-
assert.throws(
|
|
179
|
-
|
|
201
|
+
assert.throws(
|
|
202
|
+
() => removeDir(foo, dirPath),
|
|
203
|
+
Error,
|
|
204
|
+
`${foo} is not a subdirectory of ${dirPath}.`
|
|
205
|
+
);
|
|
180
206
|
await fs.rmdirSync(dirPath);
|
|
181
207
|
await fs.rmdirSync(foo);
|
|
182
208
|
});
|
|
@@ -191,7 +217,9 @@ describe('removeDirectory', () => {
|
|
|
191
217
|
const filePath = path.join(subDirPath, 'test.txt');
|
|
192
218
|
const value = 'test file.\n';
|
|
193
219
|
await createFile(filePath, value, {
|
|
194
|
-
encoding: 'utf8',
|
|
220
|
+
encoding: 'utf8',
|
|
221
|
+
flag: 'w',
|
|
222
|
+
mode: PERM_FILE
|
|
195
223
|
});
|
|
196
224
|
const res1 = await Promise.all([
|
|
197
225
|
fs.existsSync(dirPath),
|
|
@@ -222,8 +250,10 @@ describe('removeDirectory', () => {
|
|
|
222
250
|
await fs.mkdirSync(dirPath);
|
|
223
251
|
await fs.mkdirSync(foo);
|
|
224
252
|
await removeDirectory(foo, dirPath).catch(e => {
|
|
225
|
-
assert.deepStrictEqual(
|
|
226
|
-
|
|
253
|
+
assert.deepStrictEqual(
|
|
254
|
+
e,
|
|
255
|
+
new Error(`${foo} is not a subdirectory of ${dirPath}.`)
|
|
256
|
+
);
|
|
227
257
|
});
|
|
228
258
|
await fs.rmdirSync(dirPath);
|
|
229
259
|
await fs.rmdirSync(foo);
|
|
@@ -250,8 +280,7 @@ describe('getAbsPath', () => {
|
|
|
250
280
|
});
|
|
251
281
|
|
|
252
282
|
it('should throw', () => {
|
|
253
|
-
assert.throws(() => getAbsPath(),
|
|
254
|
-
'Expected String but got Undefined');
|
|
283
|
+
assert.throws(() => getAbsPath(), 'Expected String but got Undefined');
|
|
255
284
|
});
|
|
256
285
|
});
|
|
257
286
|
|
|
@@ -309,9 +338,10 @@ describe('isDir', () => {
|
|
|
309
338
|
|
|
310
339
|
describe('isExecutable', () => {
|
|
311
340
|
it('should get true if file is executable', () => {
|
|
312
|
-
const p = path.resolve(
|
|
313
|
-
|
|
314
|
-
|
|
341
|
+
const p = path.resolve(
|
|
342
|
+
IS_WIN
|
|
343
|
+
? path.join('test', 'file', 'test.cmd')
|
|
344
|
+
: path.join('test', 'file', 'test.sh')
|
|
315
345
|
);
|
|
316
346
|
fs.chmodSync(p, PERM_EXEC);
|
|
317
347
|
assert.strictEqual(isExecutable(p), true);
|
package/test/index.test.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/* api */
|
|
2
2
|
import { strict as assert } from 'node:assert';
|
|
3
|
-
import
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import { describe, it, beforeEach, afterEach } from 'mocha';
|
|
5
|
+
import sinon from 'sinon';
|
|
4
6
|
|
|
5
7
|
/* test */
|
|
6
8
|
import { Schema } from '../index.js';
|
|
@@ -11,3 +13,55 @@ describe('Schema', () => {
|
|
|
11
13
|
assert.strictEqual(schema instanceof Schema, true);
|
|
12
14
|
});
|
|
13
15
|
});
|
|
16
|
+
|
|
17
|
+
describe('Process Error Handlers', () => {
|
|
18
|
+
let sandbox;
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
sandbox = sinon.createSandbox();
|
|
21
|
+
sandbox.stub(console, 'error');
|
|
22
|
+
sandbox.stub(process, 'exit');
|
|
23
|
+
});
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
sandbox.restore();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should handle uncaughtException', () => {
|
|
29
|
+
const listeners = process.listeners('uncaughtException');
|
|
30
|
+
const targetListener = listeners.find(fn =>
|
|
31
|
+
fn.toString().includes('Fatal Error (Uncaught Exception)')
|
|
32
|
+
);
|
|
33
|
+
assert.ok(
|
|
34
|
+
targetListener,
|
|
35
|
+
'Target listener for uncaughtException should be found'
|
|
36
|
+
);
|
|
37
|
+
const testError = new Error('Test Uncaught Exception');
|
|
38
|
+
targetListener(testError);
|
|
39
|
+
assert.strictEqual(console.error.calledOnce, true);
|
|
40
|
+
assert.strictEqual(
|
|
41
|
+
console.error.firstCall.args[0],
|
|
42
|
+
'Fatal Error (Uncaught Exception):'
|
|
43
|
+
);
|
|
44
|
+
assert.strictEqual(console.error.firstCall.args[1], testError);
|
|
45
|
+
assert.strictEqual(process.exit.calledOnceWithExactly(1), true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should handle unhandledRejection', () => {
|
|
49
|
+
const listeners = process.listeners('unhandledRejection');
|
|
50
|
+
const targetListener = listeners.find(fn =>
|
|
51
|
+
fn.toString().includes('Fatal Error (Unhandled Rejection)')
|
|
52
|
+
);
|
|
53
|
+
assert.ok(
|
|
54
|
+
targetListener,
|
|
55
|
+
'Target listener for unhandledRejection should be found'
|
|
56
|
+
);
|
|
57
|
+
const testReason = 'Test Unhandled Rejection';
|
|
58
|
+
targetListener(testReason);
|
|
59
|
+
assert.strictEqual(console.error.calledOnce, true);
|
|
60
|
+
assert.strictEqual(
|
|
61
|
+
console.error.firstCall.args[0],
|
|
62
|
+
'Fatal Error (Unhandled Rejection):'
|
|
63
|
+
);
|
|
64
|
+
assert.strictEqual(console.error.firstCall.args[1], testReason);
|
|
65
|
+
assert.strictEqual(process.exit.calledOnceWithExactly(1), true);
|
|
66
|
+
});
|
|
67
|
+
});
|