UNPKG

zwave-js

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

106 lines 4.52 kB
import { fs } from "@zwave-js/core/bindings/fs/node"; import { copyFilesRecursive, noop } from "@zwave-js/shared"; import { wait } from "alcalzone-shared/async"; import crypto from "node:crypto"; import fsp from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { test } from "vitest"; import { prepareDriver, prepareMocks } from "./integrationTestSuiteShared.js"; function suite(name, options, modifier) { const { controllerCapabilities, nodeCapabilities, customSetup, testBody, debug = false, provisioningDirectory, clearMessageStatsBeforeTest = true, additionalDriverOptions, } = options; let driver; let mockPort; let serial; let continueStartup; let mockController; let mockNodes; let nodes; const cacheDir = path.join(os.tmpdir(), `zjs_test_cache_${crypto.randomBytes(4).toString("hex")}`); async function prepareTest() { if (debug) { console.log(`Running integration test in directory ${cacheDir}`); } // Make sure every test is starting fresh await fsp.rm(cacheDir, { recursive: true, force: true }).catch(noop); await fsp.mkdir(cacheDir, { recursive: true }); // And potentially provision the cache if (provisioningDirectory) { await copyFilesRecursive(fs, provisioningDirectory, cacheDir); } ({ driver, continueStartup, mockPort, serial } = await prepareDriver(cacheDir, debug, additionalDriverOptions)); ({ mockController, mockNodes } = await prepareMocks(mockPort, serial, { capabilities: controllerCapabilities, securityKeys: driver.options.securityKeys, }, // TODO: This isn't ideal as it requires us to provide the // node capabilities in addition to the provisioning directory nodeCapabilities)); if (customSetup) { await customSetup(driver, mockController, mockNodes); } // Wait for all nodes to be ready return new Promise((resolve) => { driver.once("driver ready", async () => { const promises = []; nodes = []; for (const mockNode of mockNodes) { const node = driver.controller.nodes.getOrThrow(mockNode.id); nodes.push(node); const onReady = (resolve) => { if (clearMessageStatsBeforeTest) { mockNode.clearReceivedControllerFrames(); mockNode.clearSentControllerFrames(); } process.nextTick(resolve); }; promises.push(new Promise((resolve) => { if (options.additionalDriverOptions?.testingHooks ?.skipNodeInterview) { onReady(resolve); } else { node.once("ready", () => onReady(resolve)); } })); } await Promise.all(promises); if (clearMessageStatsBeforeTest) { mockController.clearReceivedHostMessages(); } process.nextTick(resolve); }); continueStartup(); }); } // Integration tests need to run in serial, or they might block the serial port on CI const fn = modifier === "only" ? test.sequential.only : modifier === "skip" ? test.sequential.skip : test.sequential; fn(name, async (t) => { t.onTestFinished(async () => { // Give everything a chance to settle before destroying the driver. await wait(100); await driver.destroy(); if (!debug) { await fsp.rm(cacheDir, { recursive: true, force: true }) .catch(noop); } }); await prepareTest(); await testBody(t, driver, nodes, mockController, mockNodes); }, 30000); } /** Performs an integration test with a real driver using a mock controller and one mock node */ export const integrationTest = ((name, options) => { suite(name, options); }); integrationTest.only = (name, options) => { suite(name, options, "only"); }; integrationTest.skip = (name, options) => { suite(name, options, "skip"); }; //# sourceMappingURL=integrationTestSuiteMulti.js.map