import { getErrorSuffix , ZWaveError , ZWaveErrorCodes } from "@zwave-js/core" ; import path from "path" ; import { createSentryContext } from "./sentry" ; describe ( "The Sentry telemetry" , ( ) => { const defaultRootDir = path . join ( __dirname , "../../.." ) ; it ( "should ignore errors that are caused outside zwave-js" , ( ) => { const context = createSentryContext ( defaultRootDir ) ; const event = { exception : { values : [ { type : "SyntaxError" , value : "Unexpected token o in JSON at position 1" , stacktrace : { frames : [ { function : "process._tickCallback" , module : "next_tick" , filename : "internal/process/next_tick.js" , abs_path : "internal/process/next_tick.js" , } , { function : "null.<anonymous>" , module : "node-red-contrib-nextcloud:nextcloud" , filename : "/home/pi/.node-red/node_modules/node-red-contrib-nextcloud/nextcloud.js" , abs_path : "/home/pi/.node-red/node_modules/node-red-contrib-nextcloud/nextcloud.js" , } , { function : "JSON.parse" , in_app : true , } , ] , } , mechanism : { type : "onunhandledrejection" , handled : false , } , } , ] , } , } as any ; expect ( context . shouldIgnore ( event ) ) . toBeTrue ( ) ; } ) ; it ( "should NOT ignore errors that are explicitly whitelisted" , ( ) => { const context = createSentryContext ( "/opt/iobroker/node_modules/zwave-js" ) ; const event = { exception : { values : [ { type : "TypeError" , value : "Cannot read property 'nodeId' of undefined" , stacktrace : { frames : [ { function : "processImmediate" , module : "timers" , filename : "internal/timers.js" , abs_path : "internal/timers.js" , } , { function : "Immediate.<anonymous>" , module : "iobroker.js-controller.lib:adapter" , filename : "/opt/iobroker/node_modules/iobroker.js-controller/lib/adapter.js" , abs_path : "/opt/iobroker/node_modules/iobroker.js-controller/lib/adapter.js" , } , { function : "ZWave2.EventEmitter.emit" , module : "domain" , filename : "domain.js" , abs_path : "domain.js" , } , { function : "ZWave2.emit" , module : "events" , filename : "events.js" , abs_path : "events.js" , } , { function : "ZWave2.onStateChange" , module : "iobroker.zwave2.src:main.ts" , filename : "/opt/iobroker/node_modules/iobroker.zwave2/src/main.ts" , abs_path : "/opt/iobroker/node_modules/iobroker.zwave2/src/main.ts" , } , ] , } , mechanism : { type : "onunhandledrejection" , handled : false , } , } , ] , } , } as any ; expect ( context . shouldIgnore ( event ) ) . toBeFalse ( ) ; } ) ; it ( "should ignore errors that must be handled by the developer" , ( ) => { const context = createSentryContext ( "/home/michel/dashboard/servers/zwave/node_modules/zwave-js" ) ; const event = { exception : { values : [ { type : "ZWaveError" , value : "Node 6 did not respond after 3 attempts, it is presumed dead" , stacktrace : { frames : [ { function : "__awaiter" , module : "devices:powerswitch" , filename : "/home/michel/dashboard/servers/zwave/devices/powerswitch.js" , abs_path : "/home/michel/dashboard/servers/zwave/devices/powerswitch.js" , in_app : true , } , { function : "new Promise" , in_app : true , } , { function : "null.<anonymous>" , module : "devices:powerswitch" , filename : "/home/michel/dashboard/servers/zwave/devices/powerswitch.js" , abs_path : "/home/michel/dashboard/servers/zwave/devices/powerswitch.js" , in_app : true , } , { function : "Generator.next" , in_app : true , } , { function : "PowerSwitch.<anonymous>" , module : "devices:powerswitch" , filename : "/home/michel/dashboard/servers/zwave/devices/powerswitch.js" , abs_path : "/home/michel/dashboard/servers/zwave/devices/powerswitch.js" , } , { function : "new Promise" , in_app : true , } , { function : "null.<anonymous>" , module : "devices:powerswitch" , filename : "/home/michel/dashboard/servers/zwave/devices/powerswitch.js" , abs_path : "/home/michel/dashboard/servers/zwave/devices/powerswitch.js" , } , { function : "Proxy.set" , module : "zwave-js.src.lib.commandclass:BinarySwitchCC.ts" , filename : "/home/michel/dashboard/servers/zwave/node_modules/zwave-js/src/lib/commandclass/BinarySwitchCC.ts" , abs_path : "/home/michel/dashboard/servers/zwave/node_modules/zwave-js/src/lib/commandclass/BinarySwitchCC.ts" , } , { function : "Driver.sendCommand" , module : "zwave-js.src.lib.driver:Driver.ts" , filename : "/home/michel/dashboard/servers/zwave/node_modules/zwave-js/src/lib/driver/Driver.ts" , abs_path : "/home/michel/dashboard/servers/zwave/node_modules/zwave-js/src/lib/driver/Driver.ts" , } , { function : "Driver.sendMessage" , module : "zwave-js.src.lib.driver:Driver.ts" , filename : "/home/michel/dashboard/servers/zwave/node_modules/zwave-js/src/lib/driver/Driver.ts" , abs_path : "/home/michel/dashboard/servers/zwave/node_modules/zwave-js/src/lib/driver/Driver.ts" , } , ] , } , mechanism : { type : "onunhandledrejection" , handled : false , } , } , ] , } , } as any ; const hint = { originalException : new ZWaveError ( "This should be handled by the dev" , ZWaveErrorCodes . Controller_MessageDropped ) , } as any ; expect ( context . shouldIgnore ( event , hint ) ) . toBeTrue ( ) ; } ) ; it ( "should ignore errors that must be handled by the developer, unless whitelisted" , ( ) => { const context = createSentryContext ( "/opt/iobroker/node_modules/zwave-js" ) ; const event = { exception : { values : [ { type : "ZWaveError" , value : "Timeout while waiting for an ACK from the controller" , stacktrace : { frames : [ { function : "processImmediate" , module : "timers" , filename : "internal/timers.js" , abs_path : "internal/timers.js" , } , { function : "Immediate._onImmediate" , module : "@iobroker.db-states-redis.lib.states:statesInRedisClient" , filename : "/opt/iobroker/node_modules/@iobroker/db-states-redis/lib/states/statesInRedisClient.js" , abs_path : "/opt/iobroker/node_modules/@iobroker/db-states-redis/lib/states/statesInRedisClient.js" , } , { function : "change" , module : "iobroker.js-controller.lib:adapter" , filename : "/opt/iobroker/node_modules/iobroker.js-controller/lib/adapter.js" , abs_path : "/opt/iobroker/node_modules/iobroker.js-controller/lib/adapter.js" , } , { function : "ZWave2.EventEmitter.emit" , module : "domain" , filename : "domain.js" , abs_path : "domain.js" , } , { function : "ZWave2.emit" , module : "events" , filename : "events.js" , abs_path : "events.js" , } , { function : "ZWave2.onMessage" , module : "iobroker.zwave2.src:main.ts" , filename : "/opt/iobroker/node_modules/iobroker.zwave2/src/main.ts" , abs_path : "/opt/iobroker/node_modules/iobroker.zwave2/src/main.ts" , } , { function : "Array.map" , in_app : true } , { function : "null.<anonymous>" , module : "iobroker.zwave2.src:main.ts" , filename : "/opt/iobroker/node_modules/iobroker.zwave2/src/main.ts" , abs_path : "/opt/iobroker/node_modules/iobroker.zwave2/src/main.ts" , } , { function : "ZWaveController.getNodeNeighbors" , module : "zwave-js.src.lib.controller:Controller.ts" , filename : "/opt/iobroker/node_modules/zwave-js/src/lib/controller/Controller.ts" , abs_path : "/opt/iobroker/node_modules/zwave-js/src/lib/controller/Controller.ts" , } , { function : "Driver.sendMessage" , module : "zwave-js.src.lib.driver:Driver.ts" , filename : "/opt/iobroker/node_modules/zwave-js/src/lib/driver/Driver.ts" , abs_path : "/opt/iobroker/node_modules/zwave-js/src/lib/driver/Driver.ts" , } , ] , } , mechanism : { type : "onunhandledrejection" , handled : false , } , } , ] , } , } as any ; const hint = { originalException : new ZWaveError ( "This should be handled by the dev" , ZWaveErrorCodes . Controller_MessageDropped ) , } as any ; expect ( context . shouldIgnore ( event , hint ) ) . toBeFalse ( ) ; } ) ; describe ( "regression tests for ignored errors" , ( ) => { it ( "test 1: testing in the REPL" , ( ) => { const context = createSentryContext ( "/Users/ross/code/temp/zwave/node_modules/zwave-js" ) ; const event = { culprit : "Map.<anonymous>(zwave-js.src.lib.controller:Controller.ts)" , exception : { values : [ { type : "ZWaveError" , value : "Node 255 was not found!" , stacktrace : { frames : [ { function : "REPLServer.runBound [as eval]" , module : "domain" , filename : "domain.js" , abs_path : "domain.js" , in_app : false , } , { function : "bound" , module : "domain" , filename : "domain.js" , abs_path : "domain.js" , in_app : false , } , { function : "REPLServer.defaultEval" , module : "repl" , filename : "repl.js" , abs_path : "repl.js" , in_app : false , } , { function : "Script.runInContext" , module : "vm" , filename : "vm.js" , abs_path : "vm.js" , in_app : false , } , { function : "null.<anonymous>" , module : "REPL1" , filename : "REPL1" , abs_path : "REPL1" , in_app : false , } , { function : "ZWaveController.addAssociations" , module : "zwave-js.src.lib.controller:Controller.ts" , filename : "/Users/ross/code/temp/zwave/node_modules/zwave-js/src/lib/controller/Controller.ts" , abs_path : "/Users/ross/code/temp/zwave/node_modules/zwave-js/src/lib/controller/Controller.ts" , in_app : false , } , { function : "Array.filter" , in_app : true } , { function : "null.<anonymous>" , module : "zwave-js.src.lib.controller:Controller.ts" , filename : "/Users/ross/code/temp/zwave/node_modules/zwave-js/src/lib/controller/Controller.ts" , abs_path : "/Users/ross/code/temp/zwave/node_modules/zwave-js/src/lib/controller/Controller.ts" , in_app : false , } , { function : "ZWaveController.isAssociationAllowed" , module : "zwave-js.src.lib.controller:Controller.ts" , filename : "/Users/ross/code/temp/zwave/node_modules/zwave-js/src/lib/controller/Controller.ts" , abs_path : "/Users/ross/code/temp/zwave/node_modules/zwave-js/src/lib/controller/Controller.ts" , in_app : false , } , { function : "Map.<anonymous>" , module : "zwave-js.src.lib.controller:Controller.ts" , filename : "/Users/ross/code/temp/zwave/node_modules/zwave-js/src/lib/controller/Controller.ts" , abs_path : "/Users/ross/code/temp/zwave/node_modules/zwave-js/src/lib/controller/Controller.ts" , in_app : false , } , ] , } , mechanism : { type : "onunhandledrejection" , handled : false , } , } , ] , } , } as any ; expect ( context . shouldIgnore ( event ) ) . toBeTrue ( ) ; } ) ; it ( "test 2: clearly a connection issue" , ( ) => { const context = createSentryContext ( "/home/pi/zwave/node_modules/zwave-js" ) ; const event = { culprit : "Map.<anonymous>(zwave-js.src.lib.controller:Controller.ts)" , exception : { values : [ { type : "ZWaveError" , value : "Failed to send the message after 3 attempts" , stacktrace : { frames : [ { function : "__awaiter" , module : "fn" , filename : "/home/pi/zwave/build/fn.js" , abs_path : "/home/pi/zwave/build/fn.js" , in_app : true , } , { function : "new Promise" , in_app : true , } , { function : "null.<anonymous>" , module : "fn" , filename : "/home/pi/zwave/build/fn.js" , abs_path : "/home/pi/zwave/build/fn.js" , in_app : true , } , { function : "Generator.next" , in_app : true , } , { function : "null.<anonymous>" , module : "fn.ts" , filename : "/home/pi/zwave/fn.ts" , abs_path : "/home/pi/zwave/fn.ts" , in_app : true , } , { function : "ZWaveNode.setValue" , module : "zwave-js.src.lib.node:Node.ts" , filename : "/home/pi/zwave/node_modules/zwave-js/src/lib/node/Node.ts" , abs_path : "/home/pi/zwave/node_modules/zwave-js/src/lib/node/Node.ts" , in_app : false , } , { function : "Proxy.ConfigurationCCAPI.<computed>" , module : "zwave-js.src.lib.commandclass:ConfigurationCC.ts" , filename : "/home/pi/zwave/node_modules/zwave-js/src/lib/commandclass/ConfigurationCC.ts" , abs_path : "/home/pi/zwave/node_modules/zwave-js/src/lib/commandclass/ConfigurationCC.ts" , in_app : false , } , { function : "ConfigurationCCAPI.set" , module : "zwave-js.src.lib.commandclass:ConfigurationCC.ts" , filename : "/home/pi/zwave/node_modules/zwave-js/src/lib/commandclass/ConfigurationCC.ts" , abs_path : "/home/pi/zwave/node_modules/zwave-js/src/lib/commandclass/ConfigurationCC.ts" , in_app : false , } , { function : "Driver.sendCommand" , module : "zwave-js.src.lib.driver:Driver.ts" , filename : "/home/pi/zwave/node_modules/zwave-js/src/lib/driver/Driver.ts" , abs_path : "/home/pi/zwave/node_modules/zwave-js/src/lib/driver/Driver.ts" , in_app : false , } , { function : "Driver.sendMessage" , module : "zwave-js.src.lib.driver:Driver.ts" , filename : "/home/pi/zwave/node_modules/zwave-js/src/lib/driver/Driver.ts" , abs_path : "/home/pi/zwave/node_modules/zwave-js/src/lib/driver/Driver.ts" , in_app : false , } , ] , } , mechanism : { type : "onunhandledrejection" , handled : false , } , } , ] , } , } as any ; const hint = { originalException : `Failed to send the message after 3 attempts (${ getErrorSuffix ( ZWaveErrorCodes . Controller_MessageDropped ) })` , } as any ; expect ( context . shouldIgnore ( event , hint ) ) . toBeTrue ( ) ; } ) ; } ) ; } ) ;