@@ -2,15 +2,10 @@ import { jest } from '@jest/globals'
2
2
3
3
import type { networkInterfaces } from 'node:os'
4
4
import type { inspect } from 'node:util'
5
- import type { PeerCertificate , TLSSocket } from 'node:tls'
6
5
7
6
import type axios from 'axios'
8
- import { AxiosError } from 'axios'
9
7
import stripAnsi from 'strip-ansi'
10
8
11
- import type { Authenticator } from '@smartthings/core-sdk'
12
-
13
- import type { HostVerifier , DriverInfo , LiveLogClientConfig } from '../../lib/live-logging.js'
14
9
import type { LiveLogMessage } from '../../lib/sse-io.js'
15
10
import type { fatalError } from '../../lib/util.js'
16
11
@@ -27,8 +22,6 @@ jest.unstable_mockModule('node:util', () => ({
27
22
inspect : inspectMock ,
28
23
} ) )
29
24
30
- const { debugMock, getLoggerMock, isDebugEnabledMock } = await import ( '../test-lib/logger-mock.js' )
31
-
32
25
const requestMock = jest . fn < typeof axios . request > ( )
33
26
jest . unstable_mockModule ( 'axios' , ( ) => ( {
34
27
default : {
@@ -46,20 +39,20 @@ const {
46
39
handleConnectionErrors,
47
40
liveLogMessageFormatter,
48
41
logLevels,
49
- newLiveLogClient,
50
42
parseIpAndPort,
51
43
} = await import ( '../../lib/live-logging.js' )
52
44
53
45
54
- /* eslint-disable @typescript-eslint/naming-convention */
55
46
describe ( 'liveLogMessageFormatter' , ( ) => {
47
+ /* eslint-disable @typescript-eslint/naming-convention */
56
48
const errorEvent : LiveLogMessage = {
57
49
timestamp : 'event timestamp' ,
58
50
driver_id : 'driver-id' ,
59
51
driver_name : 'Driver' ,
60
52
log_level : logLevels . error . value ,
61
53
message : 'Something bad happened.' ,
62
54
}
55
+ /* eslint-enable @typescript-eslint/naming-convention */
63
56
64
57
it ( 'returns timestamp in event format' , ( ) => {
65
58
const format = liveLogMessageFormatter ( errorEvent )
@@ -138,160 +131,3 @@ describe('handleConnectionErrors', () => {
138
131
expect ( ( ) => handleConnectionErrors ( '192.168.0.1' , error ) ) . not . toThrow ( )
139
132
} )
140
133
} )
141
-
142
- describe ( 'newLiveLogClient' , ( ) => {
143
- const authority = '192.168.222.1:9495'
144
- const authHeaders = { 'Auth-Header' : 'header-value' }
145
- const authenticateMock = jest . fn < Authenticator [ 'authenticate' ] > ( ) . mockResolvedValue ( authHeaders )
146
- const authenticatorMock = { authenticate : authenticateMock } as unknown as Authenticator
147
- const baseConfig : LiveLogClientConfig = {
148
- authority,
149
- authenticator : authenticatorMock ,
150
- timeout : 1000 ,
151
- userAgent : 'user-agent' ,
152
- }
153
-
154
- const driver1 : DriverInfo = { driver_id : 'driver-id-1' , driver_name : 'Driver 1' , status : 'some-status' }
155
- const driver2 : DriverInfo = { driver_id : 'driver-id-2' , driver_name : 'Driver 2' , status : 'other-status' }
156
- const hubDriverList = [ driver1 , driver2 ]
157
- const certificate = { valid_from : 'yesterday about 3 a.m.' } as PeerCertificate
158
-
159
- it ( 'generates populated LiveLogClient' , ( ) => {
160
- expect ( newLiveLogClient ( baseConfig ) ) . toStrictEqual ( {
161
- getDrivers : expect . any ( Function ) ,
162
- getLogSource : expect . any ( Function ) ,
163
- } )
164
-
165
- expect ( getLoggerMock ) . toHaveBeenCalledExactlyOnceWith ( 'cli' )
166
- } )
167
-
168
- describe ( 'getDrivers' , ( ) => {
169
- it ( 'returns driver list' , async ( ) => {
170
- const client = newLiveLogClient ( baseConfig )
171
- requestMock . mockResolvedValueOnce ( { data : hubDriverList } )
172
-
173
- expect ( await client . getDrivers ( ) ) . toBe ( hubDriverList )
174
-
175
- expect ( authenticateMock ) . toHaveBeenCalledExactlyOnceWith ( )
176
-
177
- expect ( requestMock ) . toHaveBeenCalledExactlyOnceWith ( {
178
- url : 'https://192.168.222.1:9495/drivers' ,
179
- method : 'GET' ,
180
- httpsAgent : expect . anything ( ) , // TODO
181
- timeout : 1000 ,
182
- headers : { 'User-Agent' : 'user-agent' , ...authHeaders } ,
183
- transitional : {
184
- silentJSONParsing : true ,
185
- forcedJSONParsing : true ,
186
- clarifyTimeoutError : true ,
187
- } ,
188
- } )
189
-
190
- expect ( isDebugEnabledMock ) . not . toHaveBeenCalled ( )
191
- expect ( debugMock ) . not . toHaveBeenCalled ( )
192
- } )
193
-
194
- it ( 'verifies once an only once' , async ( ) => {
195
- const verifierMock = jest . fn < HostVerifier > ( )
196
- const config = { ...baseConfig , verifier : verifierMock }
197
- const client = newLiveLogClient ( config )
198
- const getPeerCertificateMock = jest . fn < typeof TLSSocket . prototype . getPeerCertificate > ( ) . mockReturnValue ( certificate )
199
- requestMock . mockResolvedValue ( { data : hubDriverList , request : { socket : { getPeerCertificate : getPeerCertificateMock } } } )
200
-
201
- expect ( await client . getDrivers ( ) ) . toBe ( hubDriverList )
202
- expect ( verifierMock ) . toHaveBeenCalledExactlyOnceWith ( certificate )
203
- expect ( getPeerCertificateMock ) . toHaveBeenCalledExactlyOnceWith ( )
204
- expect ( requestMock ) . toHaveBeenCalledTimes ( 1 )
205
-
206
- // Still once even though another request has been made!
207
- expect ( await client . getDrivers ( ) ) . toBe ( hubDriverList )
208
- expect ( verifierMock ) . toHaveBeenCalledExactlyOnceWith ( certificate )
209
- expect ( getPeerCertificateMock ) . toHaveBeenCalledExactlyOnceWith ( )
210
- expect ( requestMock ) . toHaveBeenCalledTimes ( 2 )
211
- } )
212
-
213
- it . each ( [
214
- { code : 'ECONNREFUSED' , message : 'Unable to connect to 192.168.222.1:9495' } ,
215
- { code : 'EHOSTUNREACH' , message : 'Unable to connect to 192.168.222.1:9495' } ,
216
- { code : 'ETIMEDOUT' , message : 'Connection to 192.168.222.1:9495 timed out' } ,
217
- { code : 'EHOSTDOWN' , message : 'The host at 192.168.222.1:9495 is down' } ,
218
- ] ) ( 'handles %s axios error with user facing message' , async ( { code, message } ) => {
219
- const axiosError = { code, isAxiosError : true } as AxiosError
220
- const client = newLiveLogClient ( baseConfig )
221
- requestMock . mockRejectedValueOnce ( axiosError )
222
-
223
- await expect ( client . getDrivers ( ) ) . rejects . toThrow ( `${ message } . Ensure hub address is correct and try again` )
224
- } )
225
-
226
- const jsonError = {
227
- request : {
228
- headers : {
229
- Authorization : 'Bearer 8a25775d-0e67-4dce-bbc9-0601ba6589ca' ,
230
- } ,
231
- } ,
232
- }
233
- it ( 'logs axios error at debug level, scrubbing auth token' , async ( ) => {
234
- isDebugEnabledMock . mockReturnValueOnce ( true )
235
- const toJSONMock = jest . fn < typeof AxiosError . prototype . toJSON > ( ) . mockReturnValue ( jsonError )
236
- const axiosError = { code : 'ECONNREFUSED' , isAxiosError : true } as AxiosError
237
- axiosError . toJSON = toJSONMock
238
- const client = newLiveLogClient ( baseConfig )
239
- requestMock . mockRejectedValueOnce ( axiosError )
240
- inspectMock . mockReturnValueOnce ( 'inspected axios.toJSON Bearer 8a25775d-0e67-4dce-bbc9-0601ba6589ca' )
241
- inspectMock . mockReturnValueOnce ( 'inspected network interfaces' )
242
-
243
- await expect ( client . getDrivers ( ) ) . rejects . toThrow ( )
244
-
245
- expect ( isDebugEnabledMock ) . toHaveBeenCalledExactlyOnceWith ( )
246
- expect ( inspectMock ) . toHaveBeenCalledTimes ( 2 )
247
- expect ( inspectMock ) . toHaveBeenCalledWith ( jsonError )
248
- expect ( inspectMock ) . toHaveBeenCalledWith ( interfaces )
249
- expect ( debugMock ) . toHaveBeenCalledWith ( 'Error connecting to live-logging: inspected axios.toJSON' +
250
- ' Bearer 8a25775d-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\n' +
251
- 'Local network interfaces: inspected network interfaces' )
252
- } )
253
-
254
- it ( 'scrubs alternate auth token format' , async ( ) => {
255
- isDebugEnabledMock . mockReturnValueOnce ( true )
256
- const toJSONMock = jest . fn < typeof AxiosError . prototype . toJSON > ( ) . mockReturnValue ( jsonError )
257
- const axiosError = { code : 'ECONNREFUSED' , isAxiosError : true } as AxiosError
258
- axiosError . toJSON = toJSONMock
259
- const client = newLiveLogClient ( baseConfig )
260
- requestMock . mockRejectedValueOnce ( axiosError )
261
- inspectMock . mockReturnValueOnce ( 'inspected axios.toJSON Authorization: some-other-token-format' )
262
- inspectMock . mockReturnValueOnce ( 'inspected network interfaces' )
263
-
264
- await expect ( client . getDrivers ( ) ) . rejects . toThrow ( )
265
-
266
- expect ( isDebugEnabledMock ) . toHaveBeenCalledExactlyOnceWith ( )
267
- expect ( inspectMock ) . toHaveBeenCalledTimes ( 2 )
268
- expect ( inspectMock ) . toHaveBeenCalledWith ( jsonError )
269
- expect ( inspectMock ) . toHaveBeenCalledWith ( interfaces )
270
- expect ( debugMock ) . toHaveBeenCalledWith ( 'Error connecting to live-logging: inspected axios.toJSON' +
271
- ' Authorization: (redacted)\n\n' +
272
- 'Local network interfaces: inspected network interfaces' )
273
- } )
274
-
275
- it ( 'rethrows non-axios errors unchanged' , async ( ) => {
276
- const error = Error ( 'other error' )
277
- const client = newLiveLogClient ( baseConfig )
278
- requestMock . mockRejectedValueOnce ( error )
279
-
280
- await expect ( client . getDrivers ( ) ) . rejects . toThrow ( error )
281
- } )
282
- } )
283
-
284
- describe ( 'getLogSource' , ( ) => {
285
- const client = newLiveLogClient ( baseConfig )
286
-
287
- it ( 'returns URL with no query parameters for all drivers' , ( ) => {
288
- expect ( client . getLogSource ( ) ) . toBe ( 'https://192.168.222.1:9495/drivers/logs' )
289
- } )
290
-
291
- it ( 'includes query parameter for a specific driver' , ( ) => {
292
- expect ( client . getLogSource ( 'my-driver-id' ) )
293
- . toBe ( 'https://192.168.222.1:9495/drivers/logs?driver_id=my-driver-id' )
294
- } )
295
- } )
296
- } )
297
- /* eslint-enable @typescript-eslint/naming-convention */
0 commit comments