UNPKG

inventoresed

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

519 lines (511 loc) 15.9 kB
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(); }); }); });