Repository: saucelabs/node-saucelabs
Pull request #283 (2025-02-05 13:05:44)

Fix release process
## Description
The release process relies on node 16 which is no longer supported. Node 16 is missing `fetch` function which is crucial for running healthchecks.

## Types of Changes
_What types of changes does your code introduce? Keep the ones that apply:_

- Bug fix (non-breaking change which fixes an issue)




Patch:
diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml
index 6a243e7..39390cc 100644
--- a/.github/workflows/npm-publish.yml
+++ b/.github/workflows/npm-publish.yml
@@ -22,14 +22,14 @@ jobs:
       - name: Setup Node version
         uses: actions/setup-node@v3
         with:
-          node-version: 16
+          node-version: 22
       - name: Install dependencies
         run: npm ci
       - run: npm run build
       - name: Run tests
         run: npm test
       - name: Upload built package
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         with:
           name: compiled-package
           path: build/
@@ -43,7 +43,7 @@ jobs:
       - name: Setup Node version
         uses: actions/setup-node@v3
         with:
-          node-version: 16
+          node-version: 22
           registry-url: https://registry.npmjs.org/
       - name: Setup Git
         run: |
diff --git a/src/constants.js b/src/constants.js
index b3344c9..0b65f4c 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -329,6 +329,6 @@ export const SC_PARAMS_TO_STRIP = [
   ...SAUCE_CONNECT_CLI_PARAM_ALIASES,
 ];
 
-export const SC_CLOSE_TIMEOUT = 5000;
-export const SC_READY_TIMEOUT = 30000;
+export const SC_CLOSE_TIMEOUT = 10000;
+export const SC_READY_TIMEOUT = 60000;
 export const SC_HEALTHCHECK_TIMEOUT = 1000;
diff --git a/src/sauceConnectHealthcheck.js b/src/sauceConnectHealthcheck.js
index 0c1d79a..ae5cd83 100644
--- a/src/sauceConnectHealthcheck.js
+++ b/src/sauceConnectHealthcheck.js
@@ -6,7 +6,7 @@ export default class SauceConnectHealthCheck {
       signal: AbortSignal.timeout(SC_HEALTHCHECK_TIMEOUT),
     });
     if (response.status !== 200) {
-      throw new Error(`response status code ${response.status} != 200`);
+      throw new TypeError(`response status code ${response.status} != 200`);
     }
   }
 }
diff --git a/src/sauceConnectManager.js b/src/sauceConnectManager.js
index f775f96..8b1fd7d 100644
--- a/src/sauceConnectManager.js
+++ b/src/sauceConnectManager.js
@@ -6,10 +6,10 @@ import {
 import SauceConnectHealthCheck from './sauceConnectHealthcheck';
 
 export class SauceConnectManager {
-  constructor(cp, logger) {
+  constructor(cp, logger, healthcheck) {
     this.cp = cp;
     this.logger = logger || (() => {});
-    this.healthcheck = new SauceConnectHealthCheck();
+    this.healthcheck = healthcheck || new SauceConnectHealthCheck();
     this._healthcheckInterval = null;
     this._readyTimeout = null;
   }
@@ -41,10 +41,18 @@ export class SauceConnectManager {
 
         this.healthcheck
           .perform(apiAddress)
-          .then(() => clearInterval(this._healthcheckInterval))
-          .then(() => clearTimeout(this._readyTimeout))
-          .then(resolve)
-          .catch(() => {});
+          .then(() => {
+            clearInterval(this._healthcheckInterval);
+            clearTimeout(this._readyTimeout);
+            resolve();
+          })
+          .catch((err) => {
+            if (err.name !== 'TypeError') {
+              clearInterval(this._healthcheckInterval);
+              clearTimeout(this._readyTimeout);
+              reject(err);
+            }
+          });
       }, SC_HEALTHCHECK_TIMEOUT);
 
       this._readyTimeout = setTimeout(() => {


Test patch:
diff --git a/e2e/sc.test.js b/e2e/sc.test.js
index 3b351e4..6dff781 100644
--- a/e2e/sc.test.js
+++ b/e2e/sc.test.js
@@ -5,7 +5,7 @@ const ID = process.env.GITHUB_RUN_ID ?? '(local)';
 // in GitHub Actions, otherwise it fails for untrusted PRs
 const SKIP_TEST = process.env.GITHUB_RUN_ID && !process.env.SAUCE_USERNAME;
 
-jest.setTimeout(60 * 1000); // 60s should be sufficient to boot SC
+jest.setTimeout(120 * 1000); // 120s should be sufficient to run all SC tests
 
 /**
  * unmock
@@ -77,9 +77,3 @@ test('should be able to run Sauce Connect', async () => {
   console.log('Sauce Connect started successfully, shutting down...');
   await sc.close();
 });
-
-afterAll(async () => {
-  // this is here because for whatever reason, we're logging output from
-  // sc _after_ sc.close() has fulfilled. this is disallowed by jest, for whatever reason
-  await new Promise((resolve) => setTimeout(resolve, 5000));
-});
diff --git a/tests/sauceConnectManager.test.js b/tests/sauceConnectManager.test.js
index 158bb61..0367e32 100644
--- a/tests/sauceConnectManager.test.js
+++ b/tests/sauceConnectManager.test.js
@@ -19,6 +19,27 @@ describe('SauceConnectManager', () => {
       );
     });
 
+    test('error when requesting healthcheck', async () => {
+      const manager = new SauceConnectManager(
+        {
+          stderr: {
+            on: jest.fn(),
+          },
+          stdout: {
+            on: jest.fn(),
+          },
+        },
+        undefined,
+        {
+          async perform() {
+            throw new Error('custom error');
+          },
+        }
+      );
+      const error = await manager.waitForReady(':8042').catch((err) => err);
+      expect(error.message).toBe('custom error');
+    });
+
     describe('waiting too long for healthcheck', () => {
       let origTimeout = constants.SC_READY_TIMEOUT;
       beforeEach(() => {