From a6c0499a121a9159a0f66bada8f962ba3a3661af Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Fri, 3 May 2024 00:51:30 +0100 Subject: [PATCH 1/7] Amend error-handling tests to account for error.code Minimal formatting as appropriate. --- test/serialize.js | 132 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 102 insertions(+), 30 deletions(-) diff --git a/test/serialize.js b/test/serialize.js index 80d0c48..5de4563 100644 --- a/test/serialize.js +++ b/test/serialize.js @@ -18,8 +18,20 @@ describe('cookie.serialize(name, value)', function () { }) it('should throw for invalid name', function () { - assert.throws(cookie.serialize.bind(cookie, 'foo\n', 'bar'), /argument name is invalid/) - assert.throws(cookie.serialize.bind(cookie, 'foo\u280a', 'bar'), /argument name is invalid/) + assert.throws( + cookie.serialize.bind(cookie, 'foo\n', 'bar'), + { + message: 'argument name is invalid', + code: 'ERR_INVALID_ARG_VALUE', + } + ) + assert.throws( + cookie.serialize.bind(cookie, 'foo\u280a', 'bar'), + { + message: 'argument name is invalid', + code: 'ERR_INVALID_ARG_VALUE', + } + ) }) }) @@ -31,15 +43,25 @@ describe('cookie.serialize(name, value, options)', function () { }) it('should throw for invalid value', function () { - assert.throws(cookie.serialize.bind(cookie, 'foo', 'bar', { domain: 'example.com\n' }), - /option domain is invalid/) + assert.throws( + cookie.serialize.bind(cookie, 'foo', 'bar', { domain: 'example.com\n' }), + { + message: 'option domain is invalid', + code: 'ERR_INVALID_ARG_VALUE', + } + ) }) }) describe('with "encode" option', function () { it('should throw on non-function value', function () { - assert.throws(cookie.serialize.bind(cookie, 'foo', 'bar', { encode: 42 }), - /option encode is invalid/) + assert.throws( + cookie.serialize.bind(cookie, 'foo', 'bar', { encode: 42 }), + { + message: 'option encode is invalid', + code: 'ERR_INVALID_ARG_TYPE', + } + ) }) it('should specify alternative value encoder', function () { @@ -49,21 +71,37 @@ describe('cookie.serialize(name, value, options)', function () { }) it('should throw when returned value is invalid', function () { - assert.throws(cookie.serialize.bind(cookie, 'foo', '+ \n', { - encode: function (v) { return v } - }), /argument val is invalid/) + assert.throws( + cookie.serialize.bind(cookie, 'foo', '+ \n', { + encode: function (v) { return v } + }), + { + message: 'argument val is invalid', + code: 'ERR_INVALID_RETURN_VALUE', + } + ) }) }) describe('with "expires" option', function () { it('should throw on non-Date value', function () { - assert.throws(cookie.serialize.bind(cookie, 'foo', 'bar', { expires: 42 }), - /option expires is invalid/) + assert.throws( + cookie.serialize.bind(cookie, 'foo', 'bar', { expires: 42 }), + { + message: 'option expires is invalid', + code: 'ERR_INVALID_ARG_TYPE', + } + ) }) it('should throw on invalid date', function () { - assert.throws(cookie.serialize.bind(cookie, 'foo', 'bar', { expires: new Date(NaN) }), - /option expires is invalid/) + assert.throws( + cookie.serialize.bind(cookie, 'foo', 'bar', { expires: new Date(NaN) }), + { + message: 'option expires is invalid', + code: 'ERR_INVALID_ARG_VALUE', + } + ) }) it('should set expires to given date', function () { @@ -85,15 +123,27 @@ describe('cookie.serialize(name, value, options)', function () { describe('with "maxAge" option', function () { it('should throw when not a number', function () { - assert.throws(function () { - cookie.serialize('foo', 'bar', { maxAge: 'buzz' }) - }, /option maxAge is invalid/) + assert.throws( + function () { + cookie.serialize('foo', 'bar', { maxAge: 'buzz' }) + }, + { + message: 'option maxAge is invalid', + code: 'ERR_INVALID_ARG_VALUE', + } + ) }) it('should throw when Infinity', function () { - assert.throws(function () { - cookie.serialize('foo', 'bar', { maxAge: Infinity }) - }, /option maxAge is invalid/) + assert.throws( + function () { + cookie.serialize('foo', 'bar', { maxAge: Infinity }) + }, + { + message: 'option maxAge is invalid', + code: 'ERR_INVALID_ARG_VALUE', + } + ) }) it('should set max-age to value', function () { @@ -133,22 +183,38 @@ describe('cookie.serialize(name, value, options)', function () { }) it('should throw for invalid value', function () { - assert.throws(cookie.serialize.bind(cookie, 'foo', 'bar', { path: '/\n' }), - /option path is invalid/) + assert.throws( + cookie.serialize.bind(cookie, 'foo', 'bar', { path: '/\n' }), + { + message: 'option path is invalid', + code: 'ERR_INVALID_ARG_VALUE', + } ) }) }) describe('with "priority" option', function () { it('should throw on invalid priority', function () { - assert.throws(function () { - cookie.serialize('foo', 'bar', { priority: 'foo' }) - }, /option priority is invalid/) + assert.throws( + function () { + cookie.serialize('foo', 'bar', { priority: 'foo' }) + }, + { + message: 'option priority is invalid', + code: 'ERR_INVALID_ARG_VALUE', + } + ) }) it('should throw on non-string', function () { - assert.throws(function () { - cookie.serialize('foo', 'bar', { priority: 42 }) - }, /option priority is invalid/) + assert.throws( + function () { + cookie.serialize('foo', 'bar', { priority: 42 }) + }, + { + message: 'option priority is invalid', + code: 'ERR_INVALID_ARG_TYPE', + } + ) }) it('should set priority low', function () { @@ -169,9 +235,15 @@ describe('cookie.serialize(name, value, options)', function () { describe('with "sameSite" option', function () { it('should throw on invalid sameSite', function () { - assert.throws(function () { - cookie.serialize('foo', 'bar', { sameSite: 'foo' }) - }, /option sameSite is invalid/) + assert.throws( + function () { + cookie.serialize('foo', 'bar', { sameSite: 'foo' }) + }, + { + message: 'option sameSite is invalid', + code: 'ERR_INVALID_ARG_VALUE', + } + ) }) it('should set sameSite strict', function () { From 1193c13368a89ebd15057ec1098c732ccd2767bc Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Fri, 3 May 2024 01:15:46 +0100 Subject: [PATCH 2/7] Add invalid sameSite arge type test --- test/serialize.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/serialize.js b/test/serialize.js index 5de4563..aa699bc 100644 --- a/test/serialize.js +++ b/test/serialize.js @@ -246,6 +246,18 @@ describe('cookie.serialize(name, value, options)', function () { ) }) + it('should throw on non-string/non-true', function () { + assert.throws( + function () { + cookie.serialize('foo', 'bar', { sameSite: 42 }) + }, + { + message: 'option sameSite is invalid', + code: 'ERR_INVALID_ARG_TYPE', + } + ) + }) + it('should set sameSite strict', function () { assert.equal(cookie.serialize('foo', 'bar', { sameSite: 'Strict' }), 'foo=bar; SameSite=Strict') assert.equal(cookie.serialize('foo', 'bar', { sameSite: 'strict' }), 'foo=bar; SameSite=Strict') From 8ff89bf703bb9a5e8a663188cf9df6d63b0eb4ca Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Fri, 3 May 2024 01:16:14 +0100 Subject: [PATCH 3/7] Add .code properties to all serialize errors --- index.js | 54 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/index.js b/index.js index 7506a79..9746dde 100644 --- a/index.js +++ b/index.js @@ -113,17 +113,23 @@ function serialize(name, val, options) { var enc = opt.encode || encode; if (typeof enc !== 'function') { - throw new TypeError('option encode is invalid'); + var encodeError = new TypeError('option encode is invalid') + encodeError.code = 'ERR_INVALID_ARG_TYPE' + throw encodeError } if (!fieldContentRegExp.test(name)) { - throw new TypeError('argument name is invalid'); + var nameError = new TypeError('argument name is invalid') + nameError.code = 'ERR_INVALID_ARG_VALUE' + throw nameError; } var value = enc(val); if (value && !fieldContentRegExp.test(value)) { - throw new TypeError('argument val is invalid'); + var returnError = new TypeError('argument val is invalid') + returnError.code = 'ERR_INVALID_RETURN_VALUE' + throw returnError; } var str = name + '=' + value; @@ -132,7 +138,9 @@ function serialize(name, val, options) { var maxAge = opt.maxAge - 0; if (isNaN(maxAge) || !isFinite(maxAge)) { - throw new TypeError('option maxAge is invalid') + var maxAgeError = new TypeError('option maxAge is invalid') + maxAgeError.code = 'ERR_INVALID_ARG_VALUE' + throw maxAgeError; } str += '; Max-Age=' + Math.floor(maxAge); @@ -140,7 +148,9 @@ function serialize(name, val, options) { if (opt.domain) { if (!fieldContentRegExp.test(opt.domain)) { - throw new TypeError('option domain is invalid'); + var domainError = new TypeError('option domain is invalid') + domainError.code = 'ERR_INVALID_ARG_VALUE' + throw domainError; } str += '; Domain=' + opt.domain; @@ -148,7 +158,9 @@ function serialize(name, val, options) { if (opt.path) { if (!fieldContentRegExp.test(opt.path)) { - throw new TypeError('option path is invalid'); + var pathError = new TypeError('option path is invalid') + pathError.code = 'ERR_INVALID_ARG_VALUE' + throw pathError; } str += '; Path=' + opt.path; @@ -156,9 +168,14 @@ function serialize(name, val, options) { if (opt.expires) { var expires = opt.expires - - if (!isDate(expires) || isNaN(expires.valueOf())) { - throw new TypeError('option expires is invalid'); + var expiresError = new TypeError('option expires is invalid') + + if (!isDate(expires)) { + expiresError.code = 'ERR_INVALID_ARG_TYPE' + throw expiresError; + } else if (isNaN(expires.valueOf())) { + expiresError.code = 'ERR_INVALID_ARG_VALUE' + throw expiresError; } str += '; Expires=' + expires.toUTCString() @@ -177,9 +194,13 @@ function serialize(name, val, options) { } if (opt.priority) { - var priority = typeof opt.priority === 'string' - ? opt.priority.toLowerCase() - : opt.priority + var priorityError = new TypeError('option priority is invalid') + if (typeof opt.priority !== 'string') { + priorityError.code = 'ERR_INVALID_ARG_TYPE' + throw priorityError; + } + + var priority = opt.priority.toLowerCase() switch (priority) { case 'low': @@ -192,7 +213,8 @@ function serialize(name, val, options) { str += '; Priority=High' break default: - throw new TypeError('option priority is invalid') + priorityError.code = 'ERR_INVALID_ARG_VALUE' + throw priorityError; } } @@ -214,7 +236,11 @@ function serialize(name, val, options) { str += '; SameSite=None'; break; default: - throw new TypeError('option sameSite is invalid'); + var sameSiteError = new TypeError('option sameSite is invalid') + sameSiteError.code = typeof opt.sameSite === 'string' + ? 'ERR_INVALID_ARG_VALUE' + : 'ERR_INVALID_ARG_TYPE' + throw sameSiteError; } } From 6abe0fc428c142af49feb79278e54ade6bf3e075 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Fri, 3 May 2024 01:53:16 +0100 Subject: [PATCH 4/7] Amend tests for parse function with error codes --- test/parse.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/test/parse.js b/test/parse.js index 76229ca..c0c05fb 100644 --- a/test/parse.js +++ b/test/parse.js @@ -6,11 +6,23 @@ var cookie = require('..'); describe('cookie.parse(str)', function () { it('should throw with no arguments', function () { - assert.throws(cookie.parse.bind(), /argument str must be a string/) + assert.throws( + cookie.parse.bind(), + { + message: 'argument str must be a string', + code: 'ERR_INVALID_ARG_TYPE', + } + ) }) it('should throw when not a string', function () { - assert.throws(cookie.parse.bind(null, 42), /argument str must be a string/) + assert.throws( + cookie.parse.bind(null, 42), + { + message: 'argument str must be a string', + code: 'ERR_INVALID_ARG_TYPE', + } + ) }) it('should parse cookie string to object', function () { From 2e660ac8f9e0ffed82507f1020d80f9208e0c164 Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Fri, 3 May 2024 01:55:00 +0100 Subject: [PATCH 5/7] Add .code property to parse function TypeError --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 9746dde..ac3bb0d 100644 --- a/index.js +++ b/index.js @@ -46,7 +46,9 @@ var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; function parse(str, options) { if (typeof str !== 'string') { - throw new TypeError('argument str must be a string'); + var parseError = new TypeError('argument str must be a string') + parseError.code = 'ERR_INVALID_ARG_TYPE' + throw parseError } var obj = {} From e618fd1006a40f2758ace8d9e5d1fbe4d038d4df Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Sun, 5 May 2024 21:28:17 +0100 Subject: [PATCH 6/7] Use callback for throw assertion matching Passing a POJO is only compatible with Node v8.0+ For backwards compatibility, a custom callback has been passed instead. All tests now pass even with Node v0.8 and Mocha v2.5.3 --- test/compare-error.js | 13 ++++++++++ test/parse.js | 9 ++++--- test/serialize.js | 58 ++++++++++++++++++++++--------------------- 3 files changed, 48 insertions(+), 32 deletions(-) create mode 100644 test/compare-error.js diff --git a/test/compare-error.js b/test/compare-error.js new file mode 100644 index 0000000..5f03547 --- /dev/null +++ b/test/compare-error.js @@ -0,0 +1,13 @@ +function compareError(errorProperties) { + return function(error) { + if ( + error instanceof Error && + error.message === errorProperties.message && + error.code === errorProperties.code + ) { + return true; + } + } + } + + module.exports = compareError; \ No newline at end of file diff --git a/test/parse.js b/test/parse.js index c0c05fb..ccd0476 100644 --- a/test/parse.js +++ b/test/parse.js @@ -1,6 +1,7 @@ var assert = require('assert'); var Buffer = require('safe-buffer').Buffer +var compareError = require('./compare-error'); var cookie = require('..'); @@ -8,20 +9,20 @@ describe('cookie.parse(str)', function () { it('should throw with no arguments', function () { assert.throws( cookie.parse.bind(), - { + compareError({ message: 'argument str must be a string', code: 'ERR_INVALID_ARG_TYPE', - } + }) ) }) it('should throw when not a string', function () { assert.throws( cookie.parse.bind(null, 42), - { + compareError({ message: 'argument str must be a string', code: 'ERR_INVALID_ARG_TYPE', - } + }) ) }) diff --git a/test/serialize.js b/test/serialize.js index aa699bc..4d96b2f 100644 --- a/test/serialize.js +++ b/test/serialize.js @@ -1,6 +1,7 @@ var assert = require('assert'); var Buffer = require('safe-buffer').Buffer +var compareError = require('./compare-error'); var cookie = require('..'); @@ -20,17 +21,17 @@ describe('cookie.serialize(name, value)', function () { it('should throw for invalid name', function () { assert.throws( cookie.serialize.bind(cookie, 'foo\n', 'bar'), - { + compareError({ message: 'argument name is invalid', code: 'ERR_INVALID_ARG_VALUE', - } + }) ) assert.throws( cookie.serialize.bind(cookie, 'foo\u280a', 'bar'), - { + compareError({ message: 'argument name is invalid', code: 'ERR_INVALID_ARG_VALUE', - } + }) ) }) }) @@ -45,10 +46,10 @@ describe('cookie.serialize(name, value, options)', function () { it('should throw for invalid value', function () { assert.throws( cookie.serialize.bind(cookie, 'foo', 'bar', { domain: 'example.com\n' }), - { + compareError({ message: 'option domain is invalid', code: 'ERR_INVALID_ARG_VALUE', - } + }) ) }) }) @@ -57,10 +58,10 @@ describe('cookie.serialize(name, value, options)', function () { it('should throw on non-function value', function () { assert.throws( cookie.serialize.bind(cookie, 'foo', 'bar', { encode: 42 }), - { + compareError({ message: 'option encode is invalid', code: 'ERR_INVALID_ARG_TYPE', - } + }) ) }) @@ -75,10 +76,10 @@ describe('cookie.serialize(name, value, options)', function () { cookie.serialize.bind(cookie, 'foo', '+ \n', { encode: function (v) { return v } }), - { + compareError({ message: 'argument val is invalid', code: 'ERR_INVALID_RETURN_VALUE', - } + }) ) }) }) @@ -87,20 +88,20 @@ describe('cookie.serialize(name, value, options)', function () { it('should throw on non-Date value', function () { assert.throws( cookie.serialize.bind(cookie, 'foo', 'bar', { expires: 42 }), - { + compareError({ message: 'option expires is invalid', code: 'ERR_INVALID_ARG_TYPE', - } + }) ) }) it('should throw on invalid date', function () { assert.throws( cookie.serialize.bind(cookie, 'foo', 'bar', { expires: new Date(NaN) }), - { + compareError({ message: 'option expires is invalid', code: 'ERR_INVALID_ARG_VALUE', - } + }) ) }) @@ -127,10 +128,10 @@ describe('cookie.serialize(name, value, options)', function () { function () { cookie.serialize('foo', 'bar', { maxAge: 'buzz' }) }, - { + compareError({ message: 'option maxAge is invalid', code: 'ERR_INVALID_ARG_VALUE', - } + }) ) }) @@ -139,10 +140,10 @@ describe('cookie.serialize(name, value, options)', function () { function () { cookie.serialize('foo', 'bar', { maxAge: Infinity }) }, - { + compareError({ message: 'option maxAge is invalid', code: 'ERR_INVALID_ARG_VALUE', - } + }) ) }) @@ -185,10 +186,11 @@ describe('cookie.serialize(name, value, options)', function () { it('should throw for invalid value', function () { assert.throws( cookie.serialize.bind(cookie, 'foo', 'bar', { path: '/\n' }), - { + compareError({ message: 'option path is invalid', code: 'ERR_INVALID_ARG_VALUE', - } ) + }) + ) }) }) @@ -198,10 +200,10 @@ describe('cookie.serialize(name, value, options)', function () { function () { cookie.serialize('foo', 'bar', { priority: 'foo' }) }, - { + compareError({ message: 'option priority is invalid', code: 'ERR_INVALID_ARG_VALUE', - } + }) ) }) @@ -210,10 +212,10 @@ describe('cookie.serialize(name, value, options)', function () { function () { cookie.serialize('foo', 'bar', { priority: 42 }) }, - { + compareError({ message: 'option priority is invalid', code: 'ERR_INVALID_ARG_TYPE', - } + }) ) }) @@ -239,10 +241,10 @@ describe('cookie.serialize(name, value, options)', function () { function () { cookie.serialize('foo', 'bar', { sameSite: 'foo' }) }, - { + compareError({ message: 'option sameSite is invalid', code: 'ERR_INVALID_ARG_VALUE', - } + }) ) }) @@ -251,10 +253,10 @@ describe('cookie.serialize(name, value, options)', function () { function () { cookie.serialize('foo', 'bar', { sameSite: 42 }) }, - { + compareError({ message: 'option sameSite is invalid', code: 'ERR_INVALID_ARG_TYPE', - } + }) ) }) From b745b78801e96e6e9bda57b764d2b4a97acdc0ff Mon Sep 17 00:00:00 2001 From: MaoShizhong <122839503+MaoShizhong@users.noreply.github.com> Date: Mon, 6 May 2024 14:32:13 +0100 Subject: [PATCH 7/7] Fix indent lint errors --- test/compare-error.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/compare-error.js b/test/compare-error.js index 5f03547..39f99a1 100644 --- a/test/compare-error.js +++ b/test/compare-error.js @@ -1,13 +1,13 @@ function compareError(errorProperties) { - return function(error) { - if ( - error instanceof Error && - error.message === errorProperties.message && - error.code === errorProperties.code - ) { - return true; - } + return function (error) { + if ( + error instanceof Error && + error.message === errorProperties.message && + error.code === errorProperties.code + ) { + return true; } - } + }; +} - module.exports = compareError; \ No newline at end of file +module.exports = compareError;