From ff735adf3263826bb54621afe1bacb4132e91b4f Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 25 Oct 2023 06:40:13 +0100 Subject: [PATCH 1/6] Cleanup unimported setup & include test files --- .unimportedrc.json | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/.unimportedrc.json b/.unimportedrc.json index 568b965b8..788220db2 100644 --- a/.unimportedrc.json +++ b/.unimportedrc.json @@ -1,8 +1,23 @@ { - "entry": ["lib/sinon.js", "lib/sinon-esm.js"], - "extensions": [".js"], - "ignorePatterns": ["**/node_modules/**"], + "entry": [ + "lib/sinon.js", + "lib/sinon-esm.js", + "test/**/*-test.js", + "test/webworker/webworker-script.js", + "test/webworker/webworker-support-assessment.js" + ], + "extensions": [ + ".js" + ], + "ignorePatterns": [ + "**/node_modules/**" + ], "ignoreUnresolved": [], - "ignoreUnimported": ["docs/**", "pkg/**", "test/**"], + "ignoreUnimported": [ + "docs/**/*", + "pkg/**/*", + "vendor/**/*", + "test/es2015/check-esm-bundle-is-runnable.js" + ], "ignoreUnused": [] } From dbde8811806ba3753f4c0cffa6499744820bc4b5 Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 25 Oct 2023 08:16:56 +0100 Subject: [PATCH 2/6] Remove redundant assign The 'assert' object is already present on the sandbox --- lib/create-sinon-api.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/create-sinon-api.js b/lib/create-sinon-api.js index 8e9d1ca49..9ef9ec126 100644 --- a/lib/create-sinon-api.js +++ b/lib/create-sinon-api.js @@ -21,7 +21,6 @@ module.exports = function createApi(opts = { sinonXhrLib: nise }) { const apiMethods = { createSandbox: createSandbox, - assert: require("./sinon/assert"), match: require("@sinonjs/samsam").createMatcher, restoreObject: require("./sinon/restore-object"), From 0331e66390bd5bb529083fd0b7bb6f891ef12f50 Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 25 Oct 2023 10:31:12 +0100 Subject: [PATCH 3/6] fix(#2484): add assertion log limit Co-authored-by: Spencer Goossens Co-authored-by: Carl-Erik Kopseng --- lib/sinon/assert.js | 32 ++++++++++++++++++++++++++++++-- test/assert-test.js | 12 ++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/lib/sinon/assert.js b/lib/sinon/assert.js index fc7dbdbe3..567135d51 100644 --- a/lib/sinon/assert.js +++ b/lib/sinon/assert.js @@ -15,12 +15,40 @@ const forEach = arrayProto.forEach; const join = arrayProto.join; const splice = arrayProto.splice; -function createAssertObject() { +function applyDefaults(obj, defaults) { + for (const key of Object.keys(defaults)) { + const val = obj[key]; + if (val === null || typeof val === "undefined") { + obj[key] = defaults[key]; + } + } +} + +/** + * @param {object} [opts] options bag + * @param {boolean} [opts.shouldLimitAssertionLogs] default is false + * @param {number} [opts.assertionLogLimit] default is 10K + * @returns {object} object with multiple assertion methods + */ +function createAssertObject(opts) { + const cleanedAssertOptions = opts || {}; + applyDefaults(cleanedAssertOptions, { + shouldLimitAssertionLogs: false, + assertionLogLimit: 1e4, + }); + const assert = { failException: "AssertError", fail: function fail(message) { - const error = new Error(message); + let msg = message; + if (cleanedAssertOptions.shouldLimitAssertionLogs) { + msg = message.substring( + 0, + cleanedAssertOptions.assertionLogLimit, + ); + } + const error = new Error(msg); error.name = this.failException || assert.failException; throw error; diff --git a/test/assert-test.js b/test/assert-test.js index 036dc2231..69b675017 100644 --- a/test/assert-test.js +++ b/test/assert-test.js @@ -65,6 +65,18 @@ describe("assert", function () { sinonAssert.failException = this.exceptionName; }); + it("can be configured to limit the error message length", function () { + const customAssert = sinonAssert.createAssertObject({ + shouldLimitAssertionLogs: true, + assertionLogLimit: 10, + }); + + assert.exception( + () => customAssert.fail("1234567890--THIS SHOULD NOT SHOW--"), + { message: "1234567890" }, + ); + }); + it("throws exception", function () { assert.exception( function () { From b8215c14a753b2f2f2797c842b5597719fe9e2c9 Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 25 Oct 2023 10:49:16 +0100 Subject: [PATCH 4/6] Document the existing sandbox and create-sandbox --- lib/sinon/create-sandbox.js | 25 +++++++++++++++++++++++++ lib/sinon/sandbox.js | 5 +++++ 2 files changed, 30 insertions(+) diff --git a/lib/sinon/create-sandbox.js b/lib/sinon/create-sandbox.js index b958daf0c..02a531720 100644 --- a/lib/sinon/create-sandbox.js +++ b/lib/sinon/create-sandbox.js @@ -41,6 +41,31 @@ function exposeValue(sandbox, config, key, value) { } } +/** + * Customize the sandbox. + * This is mostly an integration feature most users will not need + * + * @typedef {object} SandboxConfig + * @property {string[]} properties The properties of the API to expose on the sandbox. Examples: ['spy', 'fake', 'restore'] + * @property {(object|null)} injectInto TBD + * @property {boolean} useFakeTimers whether timers are faked by default + * @property {boolean} useFakeServer whether XHR's are faked and the server feature enabled by default + */ + +/** + * A configured sinon sandbox. + * + * @typedef {object} ConfiguredSinonSandboxType + * @augments Sandbox + * @property {string[]} injectedKeys the keys that have been injected (from config.injectInto) + * @property {*} injectInto TBD + * @property {*[]} args the arguments for the sandbox + */ + +/** + * @param config {SandboxConfig} + * @returns {Sandbox} + */ function createSandbox(config) { if (!config) { return new Sandbox(); diff --git a/lib/sinon/sandbox.js b/lib/sinon/sandbox.js index ce25a2240..a3e11f4de 100644 --- a/lib/sinon/sandbox.js +++ b/lib/sinon/sandbox.js @@ -69,6 +69,11 @@ function checkForValidArguments(descriptor, property, replacement) { } } +/** + * A sinon sandbox + * + * @class + */ function Sandbox() { const sandbox = this; let fakeRestorers = []; From 9f43285478038d4397f31fe426947bcdf003af68 Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 25 Oct 2023 18:20:44 +0100 Subject: [PATCH 5/6] Expose opts.assertOptions on createSandbox(opts) --- lib/sinon/assert.js | 15 ++++++++++++--- lib/sinon/create-sandbox.js | 5 ++++- lib/sinon/sandbox.js | 7 +++++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/sinon/assert.js b/lib/sinon/assert.js index 567135d51..43a555804 100644 --- a/lib/sinon/assert.js +++ b/lib/sinon/assert.js @@ -1,4 +1,5 @@ "use strict"; +/** @module */ const arrayProto = require("@sinonjs/commons").prototypes.array; const calledInOrder = require("@sinonjs/commons").calledInOrder; @@ -25,9 +26,17 @@ function applyDefaults(obj, defaults) { } /** - * @param {object} [opts] options bag - * @param {boolean} [opts.shouldLimitAssertionLogs] default is false - * @param {number} [opts.assertionLogLimit] default is 10K + * @typedef {object} CreateAssertOptions + * @global + * + * @property {boolean} [shouldLimitAssertionLogs] default is false + * @property {number} [assertionLogLimit] default is 10K + */ + +/** + * Create an assertion object that exposes several methods to invoke + * + * @param {CreateAssertOptions} [opts] options bag * @returns {object} object with multiple assertion methods */ function createAssertObject(opts) { diff --git a/lib/sinon/create-sandbox.js b/lib/sinon/create-sandbox.js index 02a531720..2d29cf29c 100644 --- a/lib/sinon/create-sandbox.js +++ b/lib/sinon/create-sandbox.js @@ -7,7 +7,7 @@ const forEach = arrayProto.forEach; const push = arrayProto.push; function prepareSandboxFromConfig(config) { - const sandbox = new Sandbox(); + const sandbox = new Sandbox({ assertOptions: config.assertOptions }); if (config.useFakeServer) { if (typeof config.useFakeServer === "object") { @@ -50,7 +50,10 @@ function exposeValue(sandbox, config, key, value) { * @property {(object|null)} injectInto TBD * @property {boolean} useFakeTimers whether timers are faked by default * @property {boolean} useFakeServer whether XHR's are faked and the server feature enabled by default + * @property {object} [assertOptions] see CreateAssertOptions in ./assert */ +// This type def is really suffering from JSDoc not being +// able to reference types in other modules /** * A configured sinon sandbox. diff --git a/lib/sinon/sandbox.js b/lib/sinon/sandbox.js index a3e11f4de..6bab45f96 100644 --- a/lib/sinon/sandbox.js +++ b/lib/sinon/sandbox.js @@ -72,10 +72,13 @@ function checkForValidArguments(descriptor, property, replacement) { /** * A sinon sandbox * + * @param opts + * @param {object} [opts.assertOptions] see the CreateAssertOptions in ./assert * @class */ -function Sandbox() { +function Sandbox(opts = {}) { const sandbox = this; + const assertOptions = opts.assertOptions || {}; let fakeRestorers = []; let promiseLib; @@ -96,7 +99,7 @@ function Sandbox() { } } - sandbox.assert = sinonAssert.createAssertObject(); + sandbox.assert = sinonAssert.createAssertObject(assertOptions); sandbox.serverPrototype = fakeServer; From 3cc346c0cdc95b39a9928197e2f11e78ae8ee184 Mon Sep 17 00:00:00 2001 From: Carl-Erik Kopseng Date: Wed, 25 Oct 2023 19:29:53 +0100 Subject: [PATCH 6/6] Verify options are passed down --- lib/sinon/assert.js | 18 +++++++++++++++++- test/create-sandbox-test.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/create-sandbox-test.js diff --git a/lib/sinon/assert.js b/lib/sinon/assert.js index 43a555804..056af5982 100644 --- a/lib/sinon/assert.js +++ b/lib/sinon/assert.js @@ -333,4 +333,20 @@ function createAssertObject(opts) { } module.exports = createAssertObject(); -module.exports.createAssertObject = createAssertObject; +Object.defineProperty(module.exports, "createAssertObject", { + get() { + return createAssertObject; + }, +}); + +// allow for easy mocking +module.exports.mock = {}; +Object.defineProperty(module.exports.mock, "createAssertObject", { + get() { + return createAssertObject; + }, + set(newImpl) { + // eslint-disable-next-line no-func-assign + createAssertObject = newImpl; + }, +}); diff --git a/test/create-sandbox-test.js b/test/create-sandbox-test.js new file mode 100644 index 000000000..142136a0d --- /dev/null +++ b/test/create-sandbox-test.js @@ -0,0 +1,31 @@ +"use strict"; + +const sinonAssert = require("../lib/sinon/assert"); +const createSandbox = require("../lib/sinon/create-sandbox"); + +describe("create-sandbox", function () { + it("passes on options to the creation of the assert object", function () { + // Arrange + const sb = createSandbox(); + const spy = sb.spy(); + sb.replace.usingAccessor(sinonAssert.mock, "createAssertObject", spy); + + // Act + createSandbox({ + assertOptions: { + shouldLimitAssertionLogs: true, + assertionLogLimit: 1234, + }, + }); + + // Assert + sb.assert.calledWith( + spy, + sb.match({ + shouldLimitAssertionLogs: true, + assertionLogLimit: 1234, + }), + ); + sb.restore(); + }); +});