Commit 38819ab for jssip.net

commit 38819ab1ad3b08a293a2dddbde1ac31d4c00e245
Author: José Luis Millán <jmillan@aliax.net>
Date:   Fri Jan 9 16:49:18 2026 +0100

    WIP: start using jest for tests

diff --git a/eslint.config.js b/eslint.config.js
index ab33e21..aaf9247 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -16,9 +16,27 @@ const compat = new FlatCompat({
     allConfig: js.configs.all
 });

-module.exports = defineConfig([{
-    languageOptions: {
-        globals: {
+module.exports = defineConfig([
+    {
+        files: ['test/**/*.js'], // Apply these settings only to test files
+        languageOptions: {
+            globals: {
+                jest: true, // Enables Jest global variables like `test`, `describe`, and `expect`
+                describe: true, // TMP: explicitly enable globally.
+                test: true, // TMP: explicitly enable globally.
+                expect: true, // TMP: explicitly enable globally.
+            },
+        },
+        plugins: {
+            jest: require('eslint-plugin-jest'), // Load the Jest plugin
+        },
+        rules: {
+            ...require('eslint-plugin-jest').configs.recommended.rules, // Use Jest's recommended rules
+        },
+    },
+    {
+        languageOptions: {
+            globals: {
             ...globals.browser,
             ...globals.node,
         },
diff --git a/gulpfile.js b/gulpfile.js
index 3284fba..7a1df08 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -15,14 +15,11 @@ const EXPECT_OPTIONS = {

 gulp.task('test', function()
 {
-  // var src = 'test/*.js';
   const src = [
-    'test/test-classes.js',
     'test/test-normalizeTarget.js',
     'test/test-parser.js',
     'test/test-properties.js',
-    'test/test-UA-no-WebRTC.js',
-    'test/test-digestAuthentication.js'
+    'test/test-UA-no-WebRTC.js'
   ];

   return gulp.src(src)
diff --git a/npm-scripts.js b/npm-scripts.js
index 946c676..70d307c 100644
--- a/npm-scripts.js
+++ b/npm-scripts.js
@@ -26,8 +26,12 @@ switch (task)
   }

   case 'test': {
+    executeCmd('jest test/test-classes.js');
+    executeCmd('jest test/test-digestAuthentication.js');
     executeCmd('gulp test');

+    // executeCmd(jest);
+
     break;
   }

diff --git a/package.json b/package.json
index 31e86e7..3ccf049 100644
--- a/package.json
+++ b/package.json
@@ -37,10 +37,12 @@
     "@eslint/eslintrc": "^3.3.3",
     "@eslint/js": "^9.39.2",
     "eslint": "^9.39.1",
+    "eslint-plugin-jest": "^29.12.1",
     "globals": "^17.0.0",
     "gulp": "^4.0.2",
     "gulp-expect-file": "^1.0.2",
     "gulp-nodeunit-runner": "^0.2.2",
+    "jest": "^30.2.0",
     "pegjs": "^0.7.0"
   },
   "scripts": {
diff --git a/test/test-classes.js b/test/test-classes.js
index aafff18..02d9002 100644
--- a/test/test-classes.js
+++ b/test/test-classes.js
@@ -1,163 +1,156 @@
 require('./include/common');
 const JsSIP = require('../');

-
-module.exports = {
-
-  'new URI' : function(test)
+describe('URI Tests', () =>
+{
+  test('new URI', () =>
   {
     const uri = new JsSIP.URI(null, 'alice', 'jssip.net', 6060);

-    test.strictEqual(uri.scheme, 'sip');
-    test.strictEqual(uri.user, 'alice');
-    test.strictEqual(uri.host, 'jssip.net');
-    test.strictEqual(uri.port, 6060);
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net:6060');
-    test.strictEqual(uri.toAor(), 'sip:alice@jssip.net');
-    test.strictEqual(uri.toAor(false), 'sip:alice@jssip.net');
-    test.strictEqual(uri.toAor(true), 'sip:alice@jssip.net:6060');
+    expect(uri.scheme).toBe('sip');
+    expect(uri.user).toBe('alice');
+    expect(uri.host).toBe('jssip.net');
+    expect(uri.port).toBe(6060);
+    expect(uri.toString()).toBe('sip:alice@jssip.net:6060');
+    expect(uri.toAor()).toBe('sip:alice@jssip.net');
+    expect(uri.toAor(false)).toBe('sip:alice@jssip.net');
+    expect(uri.toAor(true)).toBe('sip:alice@jssip.net:6060');

     uri.scheme = 'SIPS';
-    test.strictEqual(uri.scheme, 'sips');
-    test.strictEqual(uri.toAor(), 'sips:alice@jssip.net');
+    expect(uri.scheme).toBe('sips');
+    expect(uri.toAor()).toBe('sips:alice@jssip.net');
     uri.scheme = 'sip';

     uri.user = 'Iñaki ðđ';
-    test.strictEqual(uri.user, 'Iñaki ðđ');
-    test.strictEqual(uri.toString(), 'sip:I%C3%B1aki%20%C3%B0%C4%91@jssip.net:6060');
-    test.strictEqual(uri.toAor(), 'sip:I%C3%B1aki%20%C3%B0%C4%91@jssip.net');
+    expect(uri.user).toBe('Iñaki ðđ');
+    expect(uri.toString()).toBe('sip:I%C3%B1aki%20%C3%B0%C4%91@jssip.net:6060');
+    expect(uri.toAor()).toBe('sip:I%C3%B1aki%20%C3%B0%C4%91@jssip.net');

     uri.user = '%61lice';
-    test.strictEqual(uri.toAor(), 'sip:alice@jssip.net');
+    expect(uri.toAor()).toBe('sip:alice@jssip.net');

     uri.user = null;
-    test.strictEqual(uri.user, null);
-    test.strictEqual(uri.toAor(), 'sip:jssip.net');
+    expect(uri.user).toBeNull();
+    expect(uri.toAor()).toBe('sip:jssip.net');
     uri.user = 'alice';

-    test.throws(
-      function()
-      {
-        uri.host = null;
-      },
-      TypeError
-    );
-    test.throws(
-      function()
-      {
-        uri.host = { bar: 'foo' };
-      },
-      TypeError
-    );
-    test.strictEqual(uri.host, 'jssip.net');
+    expect(() =>
+    {
+      uri.host = null;
+    }).toThrow(TypeError);
+
+    expect(() =>
+    {
+      uri.host = { bar: 'foo' };
+    }).toThrow(TypeError);
+
+    expect(uri.host).toBe('jssip.net');

     uri.host = 'VERSATICA.com';
-    test.strictEqual(uri.host, 'versatica.com');
+    expect(uri.host).toBe('versatica.com');
     uri.host = 'jssip.net';

     uri.port = null;
-    test.strictEqual(uri.port, null);
+    expect(uri.port).toBeNull();

     uri.port = undefined;
-    test.strictEqual(uri.port, null);
+    expect(uri.port).toBeNull();

     uri.port = 'ABCD'; // Should become null.
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net');
+    expect(uri.toString()).toBe('sip:alice@jssip.net');

     uri.port = '123ABCD'; // Should become 123.
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net:123');
+    expect(uri.toString()).toBe('sip:alice@jssip.net:123');

     uri.port = 0;
-    test.strictEqual(uri.port, 0);
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net:0');
+    expect(uri.port).toBe(0);
+    expect(uri.toString()).toBe('sip:alice@jssip.net:0');
     uri.port = null;

-    test.strictEqual(uri.hasParam('foo'), false);
+    expect(uri.hasParam('foo')).toBe(false);

     uri.setParam('Foo', null);
-    test.strictEqual(uri.hasParam('FOO'), true);
+    expect(uri.hasParam('FOO')).toBe(true);

     uri.setParam('Baz', 123);
-    test.strictEqual(uri.getParam('baz'), '123');
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net;foo;baz=123');
+    expect(uri.getParam('baz')).toBe('123');
+    expect(uri.toString()).toBe('sip:alice@jssip.net;foo;baz=123');

     uri.setParam('zero', 0);
-    test.strictEqual(uri.hasParam('ZERO'), true);
-    test.strictEqual(uri.getParam('ZERO'), '0');
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net;foo;baz=123;zero=0');
-    test.strictEqual(uri.deleteParam('ZERO'), '0');
+    expect(uri.hasParam('ZERO')).toBe(true);
+    expect(uri.getParam('ZERO')).toBe('0');
+    expect(uri.toString()).toBe('sip:alice@jssip.net;foo;baz=123;zero=0');
+    expect(uri.deleteParam('ZERO')).toBe('0');

-    test.strictEqual(uri.deleteParam('baZ'), '123');
-    test.strictEqual(uri.deleteParam('NOO'), undefined);
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net;foo');
+    expect(uri.deleteParam('baZ')).toBe('123');
+    expect(uri.deleteParam('NOO')).toBeUndefined();
+    expect(uri.toString()).toBe('sip:alice@jssip.net;foo');

     uri.clearParams();
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net');
+    expect(uri.toString()).toBe('sip:alice@jssip.net');

-    test.strictEqual(uri.hasHeader('foo'), false);
+    expect(uri.hasHeader('foo')).toBe(false);

     uri.setHeader('Foo', 'LALALA');
-    test.strictEqual(uri.hasHeader('FOO'), true);
-    test.deepEqual(uri.getHeader('FOO'), [ 'LALALA' ]);
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net?Foo=LALALA');
+    expect(uri.hasHeader('FOO')).toBe(true);
+    expect(uri.getHeader('FOO')).toEqual([ 'LALALA' ]);
+    expect(uri.toString()).toBe('sip:alice@jssip.net?Foo=LALALA');

     uri.setHeader('bAz', [ 'ABC-1', 'ABC-2' ]);
-    test.deepEqual(uri.getHeader('baz'), [ 'ABC-1', 'ABC-2' ]);
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net?Foo=LALALA&Baz=ABC-1&Baz=ABC-2');
+    expect(uri.getHeader('baz')).toEqual([ 'ABC-1', 'ABC-2' ]);
+    expect(uri.toString()).toBe('sip:alice@jssip.net?Foo=LALALA&Baz=ABC-1&Baz=ABC-2');

-    test.deepEqual(uri.deleteHeader('baZ'), [ 'ABC-1', 'ABC-2' ]);
-    test.deepEqual(uri.deleteHeader('NOO'), undefined);
+    expect(uri.deleteHeader('baZ')).toEqual([ 'ABC-1', 'ABC-2' ]);
+    expect(uri.deleteHeader('NOO')).toBeUndefined();

     uri.clearHeaders();
-    test.strictEqual(uri.toString(), 'sip:alice@jssip.net');
+    expect(uri.toString()).toBe('sip:alice@jssip.net');

     const uri2 = uri.clone();

-    test.strictEqual(uri2.toString(), uri.toString());
+    expect(uri2.toString()).toBe(uri.toString());
     uri2.user = 'popo';
-    test.strictEqual(uri2.user, 'popo');
-    test.strictEqual(uri.user, 'alice');
-
-    test.done();
-  },
-
-  'new NameAddr' : function(test)
+    expect(uri2.user).toBe('popo');
+    expect(uri.user).toBe('alice');
+  });
+});
+
+describe('NameAddr Tests', () =>
+{
+  test('new NameAddr', () =>
   {
     const uri = new JsSIP.URI('sip', 'alice', 'jssip.net');
     const name = new JsSIP.NameAddrHeader(uri, 'Alice æßð');

-    test.strictEqual(name.display_name, 'Alice æßð');
-    test.strictEqual(name.toString(), '"Alice æßð" <sip:alice@jssip.net>');
+    expect(name.display_name).toBe('Alice æßð');
+    expect(name.toString()).toBe('"Alice æßð" <sip:alice@jssip.net>');

     name.display_name = null;
-    test.strictEqual(name.toString(), '<sip:alice@jssip.net>');
+    expect(name.toString()).toBe('<sip:alice@jssip.net>');

     name.display_name = 0;
-    test.strictEqual(name.toString(), '"0" <sip:alice@jssip.net>');
+    expect(name.toString()).toBe('"0" <sip:alice@jssip.net>');

     name.display_name = '';
-    test.strictEqual(name.toString(), '<sip:alice@jssip.net>');
+    expect(name.toString()).toBe('<sip:alice@jssip.net>');

     name.setParam('Foo', null);
-    test.strictEqual(name.hasParam('FOO'), true);
+    expect(name.hasParam('FOO')).toBe(true);

     name.setParam('Baz', 123);
-    test.strictEqual(name.getParam('baz'), '123');
-    test.strictEqual(name.toString(), '<sip:alice@jssip.net>;foo;baz=123');
+    expect(name.getParam('baz')).toBe('123');
+    expect(name.toString()).toBe('<sip:alice@jssip.net>;foo;baz=123');

-    test.strictEqual(name.deleteParam('bAz'), '123');
+    expect(name.deleteParam('bAz')).toBe('123');

     name.clearParams();
-    test.strictEqual(name.toString(), '<sip:alice@jssip.net>');
+    expect(name.toString()).toBe('<sip:alice@jssip.net>');

     const name2 = name.clone();

-    test.strictEqual(name2.toString(), name.toString());
+    expect(name2.toString()).toBe(name.toString());
     name2.display_name = '@ł€';
-    test.strictEqual(name2.display_name, '@ł€');
-    test.strictEqual(name.user, undefined);
-
-    test.done();
-  }
-
-};
+    expect(name2.display_name).toBe('@ł€');
+    expect(name.user).toBeUndefined();
+  });
+});
diff --git a/test/test-digestAuthentication.js b/test/test-digestAuthentication.js
index f0cb10e..83d4a46 100644
--- a/test/test-digestAuthentication.js
+++ b/test/test-digestAuthentication.js
@@ -4,8 +4,9 @@ const DigestAuthentication = require('../src/DigestAuthentication.js');
 // Results of this tests originally obtained from RFC 2617 and:
 // 'https://pernau.at/kd/sipdigest.php'

-module.exports = {
-  'parse no auth testrealm@host.com -RFC 2617-' : function(test)
+describe('DigestAuthentication', () =>
+{
+  test('parse no auth testrealm@host.com -RFC 2617-', () =>
   {
     const method = 'GET';
     const ruri = '/dir/index.html';
@@ -31,17 +32,14 @@ module.exports = {

     digest.authenticate({ method, ruri }, challenge, cnonce);

-    test.strictEqual(digest._response, '6629fae49393a05397450978507c4ef1');
+    expect(digest._response).toBe('6629fae49393a05397450978507c4ef1');
+  });

-    test.done();
-  },
-
-  'digest authenticate qop = null' : function(test)
+  test('digest authenticate qop = null', () =>
   {
     const method = 'REGISTER';
     const ruri = 'sip:testrealm@host.com';
-    const credentials =
-    {
+    const credentials = {
       username : 'testuser',
       password : 'testpassword',
       realm    : 'testrealm@host.com',
@@ -61,12 +59,10 @@ module.exports = {

     digest.authenticate({ method, ruri }, challenge);

-    test.strictEqual(digest._response, 'f99e05f591f147facbc94ff23b4b1dee');
-
-    test.done();
-  },
+    expect(digest._response).toBe('f99e05f591f147facbc94ff23b4b1dee');
+  });

-  'digest authenticate qop = auth' : function(test)
+  test('digest authenticate qop = auth', () =>
   {
     const method = 'REGISTER';
     const ruri = 'sip:testrealm@host.com';
@@ -92,12 +88,10 @@ module.exports = {

     digest.authenticate({ method, ruri }, challenge, cnonce);

-    test.strictEqual(digest._response, 'a69b9c2ea0dea1437a21df6ddc9b05e4');
+    expect(digest._response).toBe('a69b9c2ea0dea1437a21df6ddc9b05e4');
+  });

-    test.done();
-  },
-
-  'digest authenticate qop = auth-int and empty body' : function(test)
+  test('digest authenticate qop = auth-int and empty body', () =>
   {
     const method = 'REGISTER';
     const ruri = 'sip:testrealm@host.com';
@@ -123,12 +117,10 @@ module.exports = {

     digest.authenticate({ method, ruri }, challenge, cnonce);

-    test.strictEqual(digest._response, '82b3cab8b1c4df404434db6a0581650c');
-
-    test.done();
-  },
+    expect(digest._response).toBe('82b3cab8b1c4df404434db6a0581650c');
+  });

-  'digest authenticate qop = auth-int and non-empty body' : function(test)
+  test('digest authenticate qop = auth-int and non-empty body', () =>
   {
     const method = 'REGISTER';
     const ruri = 'sip:testrealm@host.com';
@@ -155,8 +147,6 @@ module.exports = {

     digest.authenticate({ method, ruri, body }, challenge, cnonce);

-    test.strictEqual(digest._response, '7bf0e9de3fbb5da121974509d617f532');
-
-    test.done();
-  }
-};
+    expect(digest._response).toBe('7bf0e9de3fbb5da121974509d617f532');
+  });
+});