odac 1.1.0 → 1.2.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.
- package/.agent/rules/coding.md +27 -0
- package/.agent/rules/memory.md +33 -0
- package/.agent/rules/project.md +30 -0
- package/.agent/rules/workflow.md +16 -0
- package/.github/workflows/release.yml +42 -1
- package/.github/workflows/test-coverage.yml +6 -5
- package/.github/workflows/test-publish.yml +36 -0
- package/.husky/pre-commit +10 -0
- package/.husky/pre-push +13 -0
- package/.releaserc.js +3 -3
- package/CHANGELOG.md +67 -0
- package/README.md +16 -0
- package/bin/odac.js +182 -40
- package/client/odac.js +10 -4
- package/docs/backend/01-overview/03-development-server.md +38 -45
- package/docs/backend/02-structure/01-typical-project-layout.md +59 -26
- package/docs/backend/03-config/00-configuration-overview.md +6 -6
- package/docs/backend/03-config/01-database-connection.md +2 -2
- package/docs/backend/03-config/02-static-route-mapping-optional.md +1 -1
- package/docs/backend/03-config/03-request-timeout.md +1 -1
- package/docs/backend/03-config/04-environment-variables.md +4 -4
- package/docs/backend/03-config/05-early-hints.md +2 -2
- package/docs/backend/04-routing/03-api-and-data-routes.md +18 -0
- package/docs/backend/04-routing/07-cron-jobs.md +17 -1
- package/docs/backend/05-controllers/01-how-to-build-a-controller.md +48 -3
- package/docs/backend/05-controllers/03-controller-classes.md +40 -20
- package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +17 -0
- package/docs/backend/07-views/10-styling-and-tailwind.md +93 -0
- package/docs/backend/08-database/01-getting-started.md +2 -2
- package/docs/backend/10-authentication/03-register.md +1 -1
- package/docs/backend/10-authentication/04-odac-register-forms.md +2 -2
- package/docs/backend/10-authentication/05-session-management.md +15 -1
- package/docs/backend/10-authentication/06-odac-login-forms.md +2 -2
- package/docs/backend/10-authentication/07-magic-links.md +1 -1
- package/docs/index.json +5 -1
- package/jest.config.js +1 -1
- package/package.json +9 -5
- package/src/Auth.js +58 -23
- package/src/Config.js +7 -7
- package/src/Env.js +3 -1
- package/src/Ipc.js +7 -0
- package/src/Lang.js +9 -2
- package/src/Odac.js +44 -35
- package/src/Request.js +1 -1
- package/src/Route/Cron.js +58 -17
- package/src/Route/Internal.js +1 -1
- package/src/Route.js +282 -99
- package/src/Server.js +40 -3
- package/src/Storage.js +4 -0
- package/src/Token.js +6 -4
- package/src/Validator.js +1 -1
- package/src/Var.js +22 -6
- package/src/View/EarlyHints.js +43 -33
- package/src/View/Form.js +17 -11
- package/src/View.js +62 -6
- package/template/package.json +3 -1
- package/template/view/content/home.html +3 -3
- package/template/view/head/main.html +2 -2
- package/test/Client.test.js +168 -0
- package/test/Config.test.js +112 -0
- package/test/Lang.test.js +92 -0
- package/test/Odac.test.js +86 -0
- package/test/{framework/middleware.test.js → Route/Middleware.test.js} +2 -2
- package/test/{framework/Route.test.js → Route.test.js} +1 -1
- package/test/{framework/View → View}/EarlyHints.test.js +1 -1
- package/test/{framework/WebSocket.test.js → WebSocket.test.js} +2 -2
- package/test/scripts/check-coverage.js +4 -4
- package/test/cli/Cli.test.js +0 -36
- package/test/core/Commands.test.js +0 -538
- package/test/core/Config.test.js +0 -1432
- package/test/core/Lang.test.js +0 -250
- package/test/core/Odac.test.js +0 -234
- package/test/core/Process.test.js +0 -156
- package/test/server/Api.test.js +0 -647
- package/test/server/DNS.test.js +0 -2050
- package/test/server/DNS.test.js.bak +0 -2084
- package/test/server/Hub.test.js +0 -497
- package/test/server/Log.test.js +0 -73
- package/test/server/Mail.account.test_.js +0 -460
- package/test/server/Mail.init.test_.js +0 -411
- package/test/server/Mail.test_.js +0 -1340
- package/test/server/SSL.test_.js +0 -1491
- package/test/server/Server.test.js +0 -765
- package/test/server/Service.test_.js +0 -1127
- package/test/server/Subdomain.test.js +0 -440
- package/test/server/Web/Firewall.test.js +0 -175
- package/test/server/Web/Proxy.test.js +0 -397
- package/test/server/Web.test.js +0 -1494
- package/test/server/__mocks__/acme-client.js +0 -17
- package/test/server/__mocks__/bcrypt.js +0 -50
- package/test/server/__mocks__/child_process.js +0 -389
- package/test/server/__mocks__/crypto.js +0 -432
- package/test/server/__mocks__/fs.js +0 -450
- package/test/server/__mocks__/globalOdac.js +0 -227
- package/test/server/__mocks__/http.js +0 -575
- package/test/server/__mocks__/https.js +0 -272
- package/test/server/__mocks__/index.js +0 -249
- package/test/server/__mocks__/mail/server.js +0 -100
- package/test/server/__mocks__/mail/smtp.js +0 -31
- package/test/server/__mocks__/mailparser.js +0 -81
- package/test/server/__mocks__/net.js +0 -369
- package/test/server/__mocks__/node-forge.js +0 -328
- package/test/server/__mocks__/os.js +0 -320
- package/test/server/__mocks__/path.js +0 -291
- package/test/server/__mocks__/selfsigned.js +0 -8
- package/test/server/__mocks__/server/src/mail/server.js +0 -100
- package/test/server/__mocks__/server/src/mail/smtp.js +0 -31
- package/test/server/__mocks__/smtp-server.js +0 -106
- package/test/server/__mocks__/sqlite3.js +0 -394
- package/test/server/__mocks__/testFactories.js +0 -299
- package/test/server/__mocks__/testHelpers.js +0 -363
- package/test/server/__mocks__/tls.js +0 -229
- /package/template/{config.json → odac.json} +0 -0
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const mockAcme = {
|
|
2
|
-
directory: {
|
|
3
|
-
letsencrypt: {
|
|
4
|
-
production: 'https://acme-v02.api.letsencrypt.org/directory',
|
|
5
|
-
staging: 'https://acme-staging-v02.api.letsencrypt.org/directory'
|
|
6
|
-
}
|
|
7
|
-
},
|
|
8
|
-
forge: {
|
|
9
|
-
createPrivateKey: jest.fn().mockResolvedValue('mock-private-key'),
|
|
10
|
-
createCsr: jest.fn().mockResolvedValue(['mock-key', 'mock-csr'])
|
|
11
|
-
},
|
|
12
|
-
Client: jest.fn().mockImplementation(() => ({
|
|
13
|
-
auto: jest.fn().mockResolvedValue('mock-certificate')
|
|
14
|
-
}))
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = mockAcme
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mock implementation of bcrypt for server tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const bcrypt = {
|
|
6
|
-
hash: jest.fn((password, rounds, callback) => {
|
|
7
|
-
const mockHash = `$2b$${rounds}$mocksalt${password.substring(0, 10).padEnd(10, '0')}`
|
|
8
|
-
|
|
9
|
-
if (callback) {
|
|
10
|
-
setTimeout(() => callback(null, mockHash), 0)
|
|
11
|
-
} else {
|
|
12
|
-
return Promise.resolve(mockHash)
|
|
13
|
-
}
|
|
14
|
-
}),
|
|
15
|
-
|
|
16
|
-
hashSync: jest.fn((password, rounds) => {
|
|
17
|
-
return `$2b$${rounds}$mocksalt${password.substring(0, 10).padEnd(10, '0')}`
|
|
18
|
-
}),
|
|
19
|
-
|
|
20
|
-
compare: jest.fn((password, hash, callback) => {
|
|
21
|
-
// Simple mock comparison - check if password is in the hash
|
|
22
|
-
const isValid = hash.includes(password.substring(0, 10).padEnd(10, '0'))
|
|
23
|
-
|
|
24
|
-
if (callback) {
|
|
25
|
-
setTimeout(() => callback(null, isValid), 0)
|
|
26
|
-
} else {
|
|
27
|
-
return Promise.resolve(isValid)
|
|
28
|
-
}
|
|
29
|
-
}),
|
|
30
|
-
|
|
31
|
-
compareSync: jest.fn((password, hash) => {
|
|
32
|
-
return hash.includes(password.substring(0, 10).padEnd(10, '0'))
|
|
33
|
-
}),
|
|
34
|
-
|
|
35
|
-
genSalt: jest.fn((rounds, callback) => {
|
|
36
|
-
const mockSalt = `$2b$${rounds}$mocksalt1234567890123456`
|
|
37
|
-
|
|
38
|
-
if (callback) {
|
|
39
|
-
setTimeout(() => callback(null, mockSalt), 0)
|
|
40
|
-
} else {
|
|
41
|
-
return Promise.resolve(mockSalt)
|
|
42
|
-
}
|
|
43
|
-
}),
|
|
44
|
-
|
|
45
|
-
genSaltSync: jest.fn(rounds => {
|
|
46
|
-
return `$2b$${rounds}$mocksalt1234567890123456`
|
|
47
|
-
})
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
module.exports = bcrypt
|
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mock implementation of the child_process module for server tests
|
|
3
|
-
* Provides comprehensive mocking of process spawning and management
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const {createMockEventEmitter} = require('./testHelpers')
|
|
7
|
-
const {createMockChildProcess} = require('./testFactories')
|
|
8
|
-
|
|
9
|
-
// Track active child processes
|
|
10
|
-
const activeProcesses = new Map()
|
|
11
|
-
let nextPid = 1000
|
|
12
|
-
|
|
13
|
-
const createMockChildProcessInstance = (command, args = [], options = {}) => {
|
|
14
|
-
const pid = nextPid++
|
|
15
|
-
const child = createMockEventEmitter()
|
|
16
|
-
|
|
17
|
-
Object.assign(child, {
|
|
18
|
-
// Process properties
|
|
19
|
-
pid,
|
|
20
|
-
killed: false,
|
|
21
|
-
connected: options.stdio !== 'ignore',
|
|
22
|
-
exitCode: null,
|
|
23
|
-
signalCode: null,
|
|
24
|
-
spawnfile: command,
|
|
25
|
-
spawnargs: [command, ...args],
|
|
26
|
-
|
|
27
|
-
// Stdio streams
|
|
28
|
-
stdin: options.stdio === 'ignore' ? null : createMockWritableStream(),
|
|
29
|
-
stdout: options.stdio === 'ignore' ? null : createMockReadableStream(),
|
|
30
|
-
stderr: options.stdio === 'ignore' ? null : createMockReadableStream(),
|
|
31
|
-
|
|
32
|
-
// Methods
|
|
33
|
-
kill: jest.fn((signal = 'SIGTERM') => {
|
|
34
|
-
if (child.killed) return false
|
|
35
|
-
|
|
36
|
-
child.killed = true
|
|
37
|
-
child.signalCode = signal
|
|
38
|
-
|
|
39
|
-
// Simulate process termination
|
|
40
|
-
setTimeout(() => {
|
|
41
|
-
if (signal === 'SIGKILL') {
|
|
42
|
-
child.exitCode = null
|
|
43
|
-
child.signalCode = 'SIGKILL'
|
|
44
|
-
} else {
|
|
45
|
-
child.exitCode = signal === 'SIGTERM' ? 0 : 1
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
child.emit('exit', child.exitCode, child.signalCode)
|
|
49
|
-
child.emit('close', child.exitCode, child.signalCode)
|
|
50
|
-
|
|
51
|
-
activeProcesses.delete(pid)
|
|
52
|
-
}, 0)
|
|
53
|
-
|
|
54
|
-
return true
|
|
55
|
-
}),
|
|
56
|
-
|
|
57
|
-
send: jest.fn((message, sendHandle, options, callback) => {
|
|
58
|
-
if (!child.connected) {
|
|
59
|
-
const error = new Error('Channel closed')
|
|
60
|
-
if (callback) callback(error)
|
|
61
|
-
return false
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (typeof options === 'function') {
|
|
65
|
-
callback = options
|
|
66
|
-
options = {}
|
|
67
|
-
}
|
|
68
|
-
if (typeof sendHandle === 'function') {
|
|
69
|
-
callback = sendHandle
|
|
70
|
-
sendHandle = undefined
|
|
71
|
-
options = {}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Simulate message sending
|
|
75
|
-
setTimeout(() => {
|
|
76
|
-
if (callback) callback(null)
|
|
77
|
-
}, 0)
|
|
78
|
-
|
|
79
|
-
return true
|
|
80
|
-
}),
|
|
81
|
-
|
|
82
|
-
disconnect: jest.fn(() => {
|
|
83
|
-
if (child.connected) {
|
|
84
|
-
child.connected = false
|
|
85
|
-
child.emit('disconnect')
|
|
86
|
-
}
|
|
87
|
-
}),
|
|
88
|
-
|
|
89
|
-
ref: jest.fn(() => child),
|
|
90
|
-
unref: jest.fn(() => child),
|
|
91
|
-
|
|
92
|
-
// Test helpers
|
|
93
|
-
__simulateExit: (code = 0, signal = null) => {
|
|
94
|
-
child.exitCode = code
|
|
95
|
-
child.signalCode = signal
|
|
96
|
-
child.killed = !!signal
|
|
97
|
-
|
|
98
|
-
setTimeout(() => {
|
|
99
|
-
child.emit('exit', code, signal)
|
|
100
|
-
child.emit('close', code, signal)
|
|
101
|
-
activeProcesses.delete(pid)
|
|
102
|
-
}, 0)
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
__simulateError: error => {
|
|
106
|
-
setTimeout(() => {
|
|
107
|
-
child.emit('error', error)
|
|
108
|
-
}, 0)
|
|
109
|
-
},
|
|
110
|
-
|
|
111
|
-
__simulateStdout: data => {
|
|
112
|
-
if (child.stdout) {
|
|
113
|
-
child.stdout.__simulateData(data)
|
|
114
|
-
}
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
__simulateStderr: data => {
|
|
118
|
-
if (child.stderr) {
|
|
119
|
-
child.stderr.__simulateData(data)
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
__simulateMessage: message => {
|
|
124
|
-
if (child.connected) {
|
|
125
|
-
setTimeout(() => {
|
|
126
|
-
child.emit('message', message)
|
|
127
|
-
}, 0)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
activeProcesses.set(pid, child)
|
|
133
|
-
return child
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const createMockReadableStream = () => {
|
|
137
|
-
const stream = createMockEventEmitter()
|
|
138
|
-
|
|
139
|
-
Object.assign(stream, {
|
|
140
|
-
readable: true,
|
|
141
|
-
destroyed: false,
|
|
142
|
-
|
|
143
|
-
read: jest.fn(),
|
|
144
|
-
setEncoding: jest.fn(encoding => {
|
|
145
|
-
stream._encoding = encoding
|
|
146
|
-
return stream
|
|
147
|
-
}),
|
|
148
|
-
pause: jest.fn(() => {
|
|
149
|
-
stream._paused = true
|
|
150
|
-
return stream
|
|
151
|
-
}),
|
|
152
|
-
resume: jest.fn(() => {
|
|
153
|
-
stream._paused = false
|
|
154
|
-
return stream
|
|
155
|
-
}),
|
|
156
|
-
pipe: jest.fn(destination => {
|
|
157
|
-
return destination
|
|
158
|
-
}),
|
|
159
|
-
unpipe: jest.fn(destination => {
|
|
160
|
-
return stream
|
|
161
|
-
}),
|
|
162
|
-
destroy: jest.fn(error => {
|
|
163
|
-
stream.destroyed = true
|
|
164
|
-
if (error) {
|
|
165
|
-
stream.emit('error', error)
|
|
166
|
-
}
|
|
167
|
-
stream.emit('close')
|
|
168
|
-
return stream
|
|
169
|
-
}),
|
|
170
|
-
|
|
171
|
-
// Test helpers
|
|
172
|
-
__simulateData: data => {
|
|
173
|
-
if (!stream.destroyed && stream.readable) {
|
|
174
|
-
stream.emit('data', Buffer.isBuffer(data) ? data : Buffer.from(data))
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
|
|
178
|
-
__simulateEnd: () => {
|
|
179
|
-
if (!stream.destroyed) {
|
|
180
|
-
stream.emit('end')
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
|
|
184
|
-
__simulateError: error => {
|
|
185
|
-
stream.emit('error', error)
|
|
186
|
-
}
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
return stream
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const createMockWritableStream = () => {
|
|
193
|
-
const stream = createMockEventEmitter()
|
|
194
|
-
|
|
195
|
-
Object.assign(stream, {
|
|
196
|
-
writable: true,
|
|
197
|
-
destroyed: false,
|
|
198
|
-
|
|
199
|
-
write: jest.fn((chunk, encoding, callback) => {
|
|
200
|
-
if (stream.destroyed || !stream.writable) {
|
|
201
|
-
const error = new Error('Cannot write to destroyed stream')
|
|
202
|
-
if (callback) callback(error)
|
|
203
|
-
return false
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
if (typeof encoding === 'function') {
|
|
207
|
-
callback = encoding
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (callback) {
|
|
211
|
-
setTimeout(callback, 0)
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
return true
|
|
215
|
-
}),
|
|
216
|
-
|
|
217
|
-
end: jest.fn((chunk, encoding, callback) => {
|
|
218
|
-
if (chunk) {
|
|
219
|
-
stream.write(chunk, encoding)
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (typeof encoding === 'function') {
|
|
223
|
-
callback = encoding
|
|
224
|
-
}
|
|
225
|
-
if (typeof chunk === 'function') {
|
|
226
|
-
callback = chunk
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
stream.writable = false
|
|
230
|
-
|
|
231
|
-
setTimeout(() => {
|
|
232
|
-
stream.emit('finish')
|
|
233
|
-
if (callback) callback()
|
|
234
|
-
}, 0)
|
|
235
|
-
|
|
236
|
-
return stream
|
|
237
|
-
}),
|
|
238
|
-
|
|
239
|
-
destroy: jest.fn(error => {
|
|
240
|
-
stream.destroyed = true
|
|
241
|
-
stream.writable = false
|
|
242
|
-
|
|
243
|
-
if (error) {
|
|
244
|
-
stream.emit('error', error)
|
|
245
|
-
}
|
|
246
|
-
stream.emit('close')
|
|
247
|
-
return stream
|
|
248
|
-
}),
|
|
249
|
-
|
|
250
|
-
// Test helpers
|
|
251
|
-
__simulateError: error => {
|
|
252
|
-
stream.emit('error', error)
|
|
253
|
-
}
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
return stream
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const child_process = {
|
|
260
|
-
// Process spawning
|
|
261
|
-
spawn: jest.fn((command, args = [], options = {}) => {
|
|
262
|
-
const child = createMockChildProcessInstance(command, args, options)
|
|
263
|
-
|
|
264
|
-
// Simulate spawn delay
|
|
265
|
-
setTimeout(() => {
|
|
266
|
-
if (options.detached) {
|
|
267
|
-
child.unref()
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
child.emit('spawn')
|
|
271
|
-
}, 0)
|
|
272
|
-
|
|
273
|
-
return child
|
|
274
|
-
}),
|
|
275
|
-
|
|
276
|
-
exec: jest.fn((command, options, callback) => {
|
|
277
|
-
if (typeof options === 'function') {
|
|
278
|
-
callback = options
|
|
279
|
-
options = {}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const child = createMockChildProcessInstance('/bin/sh', ['-c', command], options)
|
|
283
|
-
|
|
284
|
-
// Simulate execution
|
|
285
|
-
setTimeout(() => {
|
|
286
|
-
const stdout = 'Mock stdout output'
|
|
287
|
-
const stderr = ''
|
|
288
|
-
const error = null
|
|
289
|
-
|
|
290
|
-
if (callback) {
|
|
291
|
-
callback(error, stdout, stderr)
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
child.__simulateExit(0)
|
|
295
|
-
}, 0)
|
|
296
|
-
|
|
297
|
-
return child
|
|
298
|
-
}),
|
|
299
|
-
|
|
300
|
-
execFile: jest.fn((file, args = [], options, callback) => {
|
|
301
|
-
if (typeof args === 'function') {
|
|
302
|
-
callback = args
|
|
303
|
-
args = []
|
|
304
|
-
options = {}
|
|
305
|
-
} else if (typeof options === 'function') {
|
|
306
|
-
callback = options
|
|
307
|
-
options = {}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
const child = createMockChildProcessInstance(file, args, options)
|
|
311
|
-
|
|
312
|
-
// Simulate execution
|
|
313
|
-
setTimeout(() => {
|
|
314
|
-
const stdout = 'Mock execFile output'
|
|
315
|
-
const stderr = ''
|
|
316
|
-
const error = null
|
|
317
|
-
|
|
318
|
-
if (callback) {
|
|
319
|
-
callback(error, stdout, stderr)
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
child.__simulateExit(0)
|
|
323
|
-
}, 0)
|
|
324
|
-
|
|
325
|
-
return child
|
|
326
|
-
}),
|
|
327
|
-
|
|
328
|
-
fork: jest.fn((modulePath, args = [], options = {}) => {
|
|
329
|
-
const child = createMockChildProcessInstance(process.execPath, [modulePath, ...args], {
|
|
330
|
-
...options,
|
|
331
|
-
stdio: ['pipe', 'pipe', 'pipe', 'ipc']
|
|
332
|
-
})
|
|
333
|
-
|
|
334
|
-
child.connected = true
|
|
335
|
-
|
|
336
|
-
// Simulate fork delay
|
|
337
|
-
setTimeout(() => {
|
|
338
|
-
child.emit('spawn')
|
|
339
|
-
}, 0)
|
|
340
|
-
|
|
341
|
-
return child
|
|
342
|
-
}),
|
|
343
|
-
|
|
344
|
-
execSync: jest.fn((command, options = {}) => {
|
|
345
|
-
// Simulate synchronous execution
|
|
346
|
-
if (options.encoding === 'buffer' || !options.encoding) {
|
|
347
|
-
return Buffer.from('Mock execSync output')
|
|
348
|
-
}
|
|
349
|
-
return 'Mock execSync output'
|
|
350
|
-
}),
|
|
351
|
-
|
|
352
|
-
execFileSync: jest.fn((file, args = [], options = {}) => {
|
|
353
|
-
// Simulate synchronous file execution
|
|
354
|
-
if (options.encoding === 'buffer' || !options.encoding) {
|
|
355
|
-
return Buffer.from('Mock execFileSync output')
|
|
356
|
-
}
|
|
357
|
-
return 'Mock execFileSync output'
|
|
358
|
-
}),
|
|
359
|
-
|
|
360
|
-
spawnSync: jest.fn((command, args = [], options = {}) => {
|
|
361
|
-
return {
|
|
362
|
-
pid: nextPid++,
|
|
363
|
-
output: [null, Buffer.from('Mock stdout'), Buffer.from('Mock stderr')],
|
|
364
|
-
stdout: Buffer.from('Mock stdout'),
|
|
365
|
-
stderr: Buffer.from('Mock stderr'),
|
|
366
|
-
status: 0,
|
|
367
|
-
signal: null,
|
|
368
|
-
error: null
|
|
369
|
-
}
|
|
370
|
-
}),
|
|
371
|
-
|
|
372
|
-
// Classes
|
|
373
|
-
ChildProcess: jest.fn(function () {
|
|
374
|
-
return createMockChildProcessInstance('mock-process')
|
|
375
|
-
}),
|
|
376
|
-
|
|
377
|
-
// Test helpers
|
|
378
|
-
__getActiveProcesses: () => new Map(activeProcesses),
|
|
379
|
-
__clearAll: () => {
|
|
380
|
-
activeProcesses.clear()
|
|
381
|
-
nextPid = 1000
|
|
382
|
-
},
|
|
383
|
-
|
|
384
|
-
__setNextPid: pid => {
|
|
385
|
-
nextPid = pid
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
module.exports = child_process
|