From 5698c804c56ff0630b80c6a8eaab8eba74c3527c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignas=20Vy=C5=A1niauskas?= Date: Wed, 28 Jan 2026 16:16:29 +0200 Subject: [PATCH 1/3] Run tests on macOS in CI --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3008a83..0c4e342 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,7 @@ jobs: - uses: DeterminateSystems/magic-nix-cache-action@v11 - run: nix develop --command make crossbuild - crossbuild-mac: + test-and-crossbuild-mac: runs-on: macos-latest steps: - uses: actions/checkout@v4 @@ -35,5 +35,7 @@ jobs: with: github_access_token: ${{ secrets.GITHUB_TOKEN }} - uses: DeterminateSystems/magic-nix-cache-action@v11 + - run: nix develop --command make build + - run: nix develop --command make test - run: nix develop --command make crossbuild_mac - run: nix develop --command make crossbuild_mac_bundles From a03a0ab35b432aebce3806255d2e816b61fc0465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignas=20Vy=C5=A1niauskas?= Date: Thu, 5 Feb 2026 12:00:06 +0200 Subject: [PATCH 2/3] Replace a fixed time wait of driver with a retry loop in all tests This should eliminate flakiness if Driver takes longer than expected to start. --- test/cors.js | 4 ++-- test/flex/helpers.js | 16 ---------------- test/flex/index.js | 3 +-- test/general.js | 4 ++-- test/rfid/index.js | 5 ++--- test/senso/index.js | 5 ++--- test/utils.js | 16 ++++++++++++++++ 7 files changed, 25 insertions(+), 28 deletions(-) diff --git a/test/cors.js b/test/cors.js index 7e835a2..444cbcf 100644 --- a/test/cors.js +++ b/test/cors.js @@ -1,6 +1,6 @@ /* eslint-env mocha */ -const { wait, getJSON, startDriver, connectWS } = require('./utils') +const { wait, getJSON, startDriver, connectWS, waitForEndpoint } = require('./utils') const expect = require('chai').expect const httpEndpoints = [ @@ -24,7 +24,7 @@ beforeEach(async () => { driver = startDriver(...permissibleOrigins.flatMap(origin => [ '--permissible-origin', origin ])).on('exit', (c) => { code = c }) - await wait(500) + await waitForEndpoint('http://127.0.0.1:8382/'); expect(code).to.be.equal(0) driver.removeAllListeners() }) diff --git a/test/flex/helpers.js b/test/flex/helpers.js index cf798fa..0384f15 100644 --- a/test/flex/helpers.js +++ b/test/flex/helpers.js @@ -1,20 +1,5 @@ const { wait } = require("../utils"); -async function waitForEndpoint(url, maxAttempts = 5, delay = 100) { - let lastError = null; - for (let i = 0; i < maxAttempts; i++) { - try { - // note: not connecting to websocket to avoid messing with test state by having a client - const res = await fetch(url); - return; - } catch (e) { - lastError = e; - await wait(delay); - } - } - throw new Error(`Endpoint ${url} not available after ${maxAttempts} attempts, last error: ${e}`); -} - /** * Generate a single synthetic Flex serial data frame. * @@ -135,7 +120,6 @@ function splitBufferRandomly(buffer, minChunkSize = 1, maxChunkSize = 10) { } module.exports = { - waitForEndpoint, generateFlexSerialFrame, generateSensitronicsFrame, generateRandomSensitronicsFrame, diff --git a/test/flex/index.js b/test/flex/index.js index 0c55618..8786727 100644 --- a/test/flex/index.js +++ b/test/flex/index.js @@ -1,9 +1,8 @@ -const { wait, startDriver, connectWS, expectEvent } = require("../utils"); +const { wait, startDriver, connectWS, expectEvent, waitForEndpoint } = require("../utils"); const expect = require("chai").expect; const VirtualDevice = require("./mock/VirtualDevice"); const path = require("path"); const { - waitForEndpoint, generateFlexSerialFrame, generateRandomSensitronicsFrame, splitBufferRandomly, diff --git a/test/general.js b/test/general.js index 899d403..8130c64 100644 --- a/test/general.js +++ b/test/general.js @@ -1,6 +1,6 @@ /* eslint-env mocha */ -const { wait, getJSON, startDriver } = require('./utils') +const { wait, getJSON, startDriver, waitForEndpoint } = require('./utils') const expect = require('chai').expect var driver @@ -10,7 +10,7 @@ beforeEach(async () => { driver = startDriver().on('exit', (c) => { code = c }) - await wait(500) + await waitForEndpoint('http://127.0.0.1:8382'); expect(code).to.be.equal(0) driver.removeAllListeners() }) diff --git a/test/rfid/index.js b/test/rfid/index.js index 4a66055..c0d24e6 100644 --- a/test/rfid/index.js +++ b/test/rfid/index.js @@ -1,5 +1,5 @@ /* eslint-env mocha */ -const { wait, startDriver, connectWS, getJSON, expectEvent } = require('../utils') +const { wait, startDriver, connectWS, getJSON, expectEvent, waitForEndpoint } = require('../utils') const expect = require('chai').expect // TESTS @@ -14,8 +14,7 @@ describe('Basic functionality', () => { driver = startDriver().on('exit', (c) => { code = c }) - // Give driver 500ms to start up - await wait(500) + await waitForEndpoint('http://127.0.0.1:8382/rfid'); expect(code).to.be.equal(0) driver.removeAllListeners() }) diff --git a/test/senso/index.js b/test/senso/index.js index b0c864e..d780b93 100644 --- a/test/senso/index.js +++ b/test/senso/index.js @@ -1,5 +1,5 @@ /* eslint-env mocha */ -const { wait, startDriver, connectWS, expectEvent } = require('../utils') +const { wait, startDriver, connectWS, expectEvent, waitForEndpoint } = require('../utils') const expect = require('chai').expect const mock = require('./mock') @@ -16,8 +16,7 @@ describe('Basic functionality', () => { driver = startDriver().on('exit', (c) => { code = c }) - // Give driver 500ms to start up - await wait(500) + await waitForEndpoint('http://127.0.0.1:8382/senso'); expect(code).to.be.equal(0) driver.removeAllListeners() diff --git a/test/utils.js b/test/utils.js index 7774cba..6742d3e 100644 --- a/test/utils.js +++ b/test/utils.js @@ -48,5 +48,21 @@ module.exports = { } }) }) + }, + + // Checks whether a connection can be established via HTTP to URL, regardless + // of status code. + waitForEndpoint: async function(url, maxAttempts = 10, delay = 100) { + let lastError = null + for (let i = 0; i < maxAttempts; i++) { + try { + const res = await fetch(url) + return + } catch (e) { + lastError = e + await module.exports.wait(delay) + } + } + throw new Error(`Endpoint ${url} not available after ${maxAttempts} attempts, last error: ${e}`) } } From a1ed855d7096e4156a80aacd7ea0c635a2d84814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignas=20Vy=C5=A1niauskas?= Date: Thu, 5 Feb 2026 11:30:43 +0200 Subject: [PATCH 3/3] Skip Senso Discover tests on macOS runners in Github Actions For mysterious reasons mDNS / bonjour does not work. Tried several workarounds, but it's just too annoying to debug. --- test/senso/index.js | 4 +++- test/utils.js | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/test/senso/index.js b/test/senso/index.js index d780b93..62ee16b 100644 --- a/test/senso/index.js +++ b/test/senso/index.js @@ -1,5 +1,5 @@ /* eslint-env mocha */ -const { wait, startDriver, connectWS, expectEvent, waitForEndpoint } = require('../utils') +const { wait, startDriver, connectWS, expectEvent, waitForEndpoint, skipTestOnMacOSinCI } = require('../utils') const expect = require('chai').expect const mock = require('./mock') @@ -212,6 +212,8 @@ describe('Basic functionality', () => { }) it('Can discover mock Senso', async function () { + // bonjour / mDNS does not seem to work on Github's macOS runners + skipTestOnMacOSinCI(this) this.timeout(6000) // connect with Senso WS diff --git a/test/utils.js b/test/utils.js index 6742d3e..53b79c6 100644 --- a/test/utils.js +++ b/test/utils.js @@ -64,5 +64,14 @@ module.exports = { } } throw new Error(`Endpoint ${url} not available after ${maxAttempts} attempts, last error: ${e}`) + }, + + skipTestOnMacOSinCI: function (test) { + const isMac = process.platform === 'darwin' + const isGitHubActions = process.env.GITHUB_ACTIONS === 'true' + + if (isMac && isGitHubActions) { + test.skip() + } } }