From 340607946be3670d9111da0292fe99c9f20551e2 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 14:52:43 -0500 Subject: [PATCH 01/31] created spec directory with underpants.spec.js file --- spec/underpants.spec.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 spec/underpants.spec.js diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js new file mode 100644 index 0000000..e69de29 From 31c986b17c4672331b13f9ca460eb4fbe7915f22 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 15:04:48 -0500 Subject: [PATCH 02/31] updated spec/underpants.spec.js tests for identity, typeOf, first, last, and indexOf --- index.html | 230 +++++----------------------------------- spec/underpants.spec.js | 82 ++++++++++++++ underpants.js | 7 +- 3 files changed, 115 insertions(+), 204 deletions(-) diff --git a/index.html b/index.html index b613a3b..5f2c2f9 100644 --- a/index.html +++ b/index.html @@ -1,204 +1,32 @@ - - - Underpants Library - - - - - -
- - - + + + Underpants Library + + + + + + + + + +
+ + + + + diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index e69de29..3c1e495 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -0,0 +1,82 @@ +describe("underpants library", () => { + describe("_.identity()", () => { + it('should return input value unchanged', () => { + assert.strictEqual( _.identity(14), 14); + assert.deepEqual( _.identity({a: "one"}), {a: "one"}); + assert.strictEqual(_.identity("hello there"), "hello there"); + assert.deepEqual(_.identity([1,2,3]), [1,2,3]); + }); + }); + + describe("_.typeof()", () => { + it('should handle simple datatypes', () => { + assert.strictEqual(_.typeOf("a"), "string"); + assert.strictEqual(_.typeOf(10), "number"); + assert.strictEqual(_.typeOf(false), "boolean"); + assert.strictEqual(_.typeOf(undefined), "undefined"); + assert.strictEqual(_.typeOf(function(){}), "function"); + }); + it('should return `object` for objects intended as as collections', () => { + assert.strictEqual(_.typeOf({a: "one"}), "object", "Should handle objects."); + }); + it('should return `array` for array inputs', () => { + assert.strictEqual(_.typeOf([1,3]), "array"); + }); + it('should return `null` for null inputs', () => { + assert.strictEqual(_.typeOf(null), "null"); + }); + it('should return `function` for function inputs', () => { + assert.strictEqual(_.typeOf(function(){}), "function"); + }); + }); + + describe("_.first()", () => { + it('should accept an argument representing the number of items to include in the output', () => { + assert.deepEqual(_.first(["a","b","c"],2) ,["a","b"]); + }); + it('should return the first element if no numerical argument is given', () => { + assert.deepEqual(_.first(["a","b","c"]) ,"a"); + }); + it('should return empty array if numerical argument is not a positive number', () => { + assert.deepEqual(_.first(["a","b","c"], -1) ,[], "Should return empty list if numerical argument is not a positive number."); + }); + it('should return empty array if the array param is not an an array', () => { + assert.deepEqual(_.first({a:"b"}, 2), [], "Should return empty array if the array param is not an array."); + }); + }); + + describe("_.last()", () => { + it('should accept an argument representing the number of items to include in the output', () => { + assert.deepEqual(_.last(["a","b","c"],2) ,["b","c"]); + }); + it('should return the last element if no numerical argument is given', () => { + assert.deepEqual(_.last(["a","b","c"]) ,"c"); + }); + it('should return empty array if numerical argument is not a positive number', () => { + assert.deepEqual(_.last(["a","b","c"], -1) ,[]); + }); + it("shoud return the array if the numerical argument is greater than the array's length", () => { + assert.deepEqual(_.last(["a","b","c"], 5) ,["a","b","c"]); + }); + it('should return empty array if array param is not an array', () => { + assert.deepEqual(_.last({a:"b"}, 2), []); + }); + }); + + describe("_.indexOf()", () => { + const inputData = ["a","b","c","d","b"]; + it('should return the correct index when an element is found', () => { + assert.deepEqual(_.indexOf(inputData, "b") , 1); + }); + it('should return the index of the first occurance of a found element if there are duplicates', () => { + assert.deepEqual(_.indexOf(inputData, "b"), 1); + }); + it('should return -1 if the element is not found', () => { + assert.deepEqual(_.indexOf(inputData, "e") , -1); + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, ["a","b","c","d", "b"]); + }); + }); + +}); \ No newline at end of file diff --git a/underpants.js b/underpants.js index fc531b4..a13ce60 100644 --- a/underpants.js +++ b/underpants.js @@ -22,6 +22,7 @@ var _ = {}; */ + /** _.typeOf * Arguments: * 1) Any value @@ -301,9 +302,9 @@ var _ = {}; * _.extend(data, {a:"two"}); -> data now equals {a:"two"} */ -////////////////////////////////////////////////////////////////////// -// DON'T REMOVE THIS CODE //////////////////////////////////////////// -////////////////////////////////////////////////////////////////////// +//////////////////////////// +// DON'T REMOVE THIS CODE // +//////////////////////////// if((typeof process !== 'undefined') && (typeof process.versions.node !== 'undefined')) { From 072d46d3d9cffd3cb230dfd2676bdf4d34c30239 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 15:07:19 -0500 Subject: [PATCH 03/31] added assert, expect, should script to index.html --- index.html | 7 +++++++ underpants.js | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/index.html b/index.html index 5f2c2f9..7a764fe 100644 --- a/index.html +++ b/index.html @@ -25,6 +25,13 @@ + + + diff --git a/underpants.js b/underpants.js index a13ce60..1e2daa5 100644 --- a/underpants.js +++ b/underpants.js @@ -43,6 +43,17 @@ var _ = {}; * _.typeOf([1,2,3]) -> "array" */ +_.typeOf = (value) => { + if (typeof value !== 'object'){ + return typeof value; + } else if (Array.isArray(value)){ + return 'array'; + } else if (value === null){ + return 'null'; + } else { + return 'object'; + } +} /** _.first * Arguments: From a3d15e2df33fbb793fd2a31a68bb834d6cc43ab5 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 15:16:55 -0500 Subject: [PATCH 04/31] updated edge cases in _.first instructions, updated var _ declaration to const, updated spec/underpants.spec.js to reflect additional edge cases --- spec/underpants.spec.js | 3 +++ underpants.js | 23 +++++++++-------------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 3c1e495..42b6ef5 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -43,6 +43,9 @@ describe("underpants library", () => { it('should return empty array if the array param is not an an array', () => { assert.deepEqual(_.first({a:"b"}, 2), [], "Should return empty array if the array param is not an array."); }); + it('should return the whole array if the number is greater than the length of the array', () => { + assert.deepEqual(_.first(["a", "b", "c"], 5), ["a", "b", "c"]); + }); }); describe("_.last()", () => { diff --git a/underpants.js b/underpants.js index 1e2daa5..bbd74f4 100644 --- a/underpants.js +++ b/underpants.js @@ -3,7 +3,7 @@ // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode 'use strict'; -var _ = {}; +const _ = {}; /** @@ -43,17 +43,7 @@ var _ = {}; * _.typeOf([1,2,3]) -> "array" */ -_.typeOf = (value) => { - if (typeof value !== 'object'){ - return typeof value; - } else if (Array.isArray(value)){ - return 'array'; - } else if (value === null){ - return 'null'; - } else { - return 'object'; - } -} + /** _.first * Arguments: @@ -65,15 +55,20 @@ _.typeOf = (value) => { * 3) Otherwise, return the first items of * Edge Cases: * 1) What if is negative? -* 2) What if is greater than .length? +* 2) What if is not provided? +* 3) What if is greater than the length of the array? +* 3) What if is not an array? * Examples: * _.first("ponies", 1) -> [] -* _.first(["a", "b", "c"], "ponies") -> "a" +* _.first(["a", "b", "c"], -1) -> [] +* _.first(["a", "b", "c"]) -> "a" * _.first(["a", "b", "c"], 1) -> "a" * _.first(["a", "b", "c"], 2) -> ["a", "b"] +* _.first("a", "b", "c", 5) -> ["a", "b", "c"] */ + /** _.last * Arguments: * 1) An array From 8ce2789f684889a9bdb9941e4f89663302cc6c94 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 15:35:09 -0500 Subject: [PATCH 05/31] updated _.first tests remove incorrrect exaple --- underpants.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/underpants.js b/underpants.js index bbd74f4..01c5559 100644 --- a/underpants.js +++ b/underpants.js @@ -62,7 +62,6 @@ const _ = {}; * _.first("ponies", 1) -> [] * _.first(["a", "b", "c"], -1) -> [] * _.first(["a", "b", "c"]) -> "a" -* _.first(["a", "b", "c"], 1) -> "a" * _.first(["a", "b", "c"], 2) -> ["a", "b"] * _.first("a", "b", "c", 5) -> ["a", "b", "c"] */ @@ -80,9 +79,12 @@ const _ = {}; * Edge Cases: * 1) What if is negative? * 2) What if is greater than .length? +* 3) What if is not provided? +* 4) What if is not an array? * Examples: * _.last("ponies", 2) -> [] -* _.last(["a", "b", "c"], "ponies") -> "c" +* _.last(["a", "b", "c"], -1) -> [] +* _.last(["a", "b", "c"], 5) -> ["a", "b", "c"] * _.last(["a", "b", "c"], 1) -> "c" * _.last(["a", "b", "c"], 2) -> ["b", "c"] */ From 24b0dc25b233bce7a53da397f5b1821f3f616e6f Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 15:37:59 -0500 Subject: [PATCH 06/31] updated _.last instructions to remove incorrect example --- underpants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/underpants.js b/underpants.js index 01c5559..267431c 100644 --- a/underpants.js +++ b/underpants.js @@ -84,8 +84,8 @@ const _ = {}; * Examples: * _.last("ponies", 2) -> [] * _.last(["a", "b", "c"], -1) -> [] +* _.last(["a", "b", "c"]) -> "c" * _.last(["a", "b", "c"], 5) -> ["a", "b", "c"] -* _.last(["a", "b", "c"], 1) -> "c" * _.last(["a", "b", "c"], 2) -> ["b", "c"] */ From 604c9082d8db43b0d15e2029d8436f4ae4a36360 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 15:47:34 -0500 Subject: [PATCH 07/31] updated spec/underpants.spec.js to include tests for contains, each, filter, unique --- spec/underpants.spec.js | 168 ++++++++++++++++++++++++++++++++++++++++ underpants.js | 3 +- 2 files changed, 170 insertions(+), 1 deletion(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 42b6ef5..ed69994 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -82,4 +82,172 @@ describe("underpants library", () => { }); }); + describe("_.contains()", () => { + const inputData = [1,"3",4,5,"a","4","b"]; + it('should return true if a list contains an element', () => { + assert.strictEqual(_.contains(inputData, "a") , true); + }); + it("should return false if the list doesn't contain an element", () => { + assert.strictEqual(_.contains(inputData, "c") , false); + }); + it('should not convert types when checking', () => { + assert.strictEqual(_.contains(inputData, 3) , false); + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, [1,"3",4,5,"a","4","b"]); + }); + }); + + describe("_.each()", () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + it('should handle arrays', () => { + const inputArray = [1,2,3,4,5]; + _.each(inputArray, function(e, i, a){ + inputArray[i] = e * a.length; + }); + assert.deepEqual(inputArray, [5, 10, 15, 20, 25]); + + }); + it('should handle objects', () => { + const inputObject = {a:"1",b:"2",c:"3",d:"4"}; + _.each(inputObject, function(v, k, o){ + inputObject[k] = inputObject[k] + inputObject[k]; + }); + assert.deepEqual(inputObject,{a: "11", b: "22", c: "33", d: "44"}); + }); + it('callback should take in current index as an argument if collection is an array', () => { + const inputArray = ['a', 'b', 'c']; + const logs = [0, 1, 2]; + const output = []; + _.each(inputArray, function(e, i, a){ + console.log(i); + output.push(e.toUpperCase()); + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + console.dir('hit this'); + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in array as an argument if collection is an array', () => { + const inputArray = ['a', 'b', 'c']; + const output = []; + _.each(inputArray, function(e, i, a){ + console.log(a); + output.push(e.toUpperCase()); + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b', 'c']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in current key as an argument if collection is an object', () => { + const inputObject = { a: "one", b: "two" }; + const logs = ["a", "b"]; + _.each(inputObject, (v, k, o) => { + console.log(k); + inputObject[k] = inputObject[k].toUpperCase(); + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in object as an argument if collection is an object', () => { + const inputObject = { a: "one", b: "two" }; + const output = []; + _.each(inputObject, (v, k, o) => { + console.log(o); + output.push(inputObject[k].toUpperCase()); + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], { a: 'one', b: 'two'}); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + }); + + describe("_.unique()", () => { + const inputData = ["a",1,1,"a","c",false,"b",5,"c",null,false,null]; + it('should return an array with no duplicates', () => { + assert.deepEqual(_.unique(inputData),["a",1,"c",false,"b",5,null]); + }); + it('should invoke _.indexOf() method', () => { + const func = _.unique.toString(); + assert.equal(func.includes("_.indexOf("), true); + }) + it('should not have side effects', () => { + assert.deepEqual(inputData, ["a",1,1,"a","c",false,"b",5,"c",null, false, null]); + }); + }); + + describe("_.filter()", () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + + const inputData = ["a",1,"b",2,"c",4]; + + it('should filter elements in an array', () => { + assert.deepEqual(_.filter(inputData, (e,i,a) => { + return typeof e === "string"; + }), ["a","b", "c"]); + }); + it('callback function should take in the current index as one of its arguments', () => { + const input = ['a', 'b', 'aa']; + const logs = [0, 1, 2] + _.filter(input, (e, i, a) => { + console.dir("current test: " + i); + console.log(i); + return e.length === 1; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback function should take in the array as one its arguments', () => { + const input = ['a', 'b', 'aa']; + _.filter(input, (e, i, a) => { + console.log(a); + return e.length === 1; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b', 'aa']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, ["a",1,"b",2,"c",4]); + }) + }); + }); \ No newline at end of file diff --git a/underpants.js b/underpants.js index 267431c..c264711 100644 --- a/underpants.js +++ b/underpants.js @@ -97,7 +97,7 @@ const _ = {}; * Objectives: * 1) Return the index of that is the first occurrance of * 2) Return -1 if is not in -* 3) Do not use [].indexOf()! +* 3) Do not use [].indexOf() * Edge Cases: * 1) What if has multiple occurances of val? * 2) What if isn't in ? @@ -107,6 +107,7 @@ const _ = {}; */ + /** _.contains * Arguments: * 1) An array From 68f715103c8f235f252fcc1148c48a45bba819c4 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 16:04:53 -0500 Subject: [PATCH 08/31] updated _.each instructions in underpants.js to show example for handling objects, updated tests --- spec/underpants.spec.js | 10 ++++++---- underpants.js | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index ed69994..f92474e 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -108,18 +108,20 @@ describe("underpants library", () => { }); it('should handle arrays', () => { const inputArray = [1,2,3,4,5]; + const output = []; _.each(inputArray, function(e, i, a){ - inputArray[i] = e * a.length; + output.push(e * 10); }); - assert.deepEqual(inputArray, [5, 10, 15, 20, 25]); + assert.deepEqual(output, [10, 20, 30, 40, 50]); }); it('should handle objects', () => { const inputObject = {a:"1",b:"2",c:"3",d:"4"}; + const output = []; _.each(inputObject, function(v, k, o){ - inputObject[k] = inputObject[k] + inputObject[k]; + output.push(v + v); }); - assert.deepEqual(inputObject,{a: "11", b: "22", c: "33", d: "44"}); + assert.deepEqual(output, ["11", "22", "33", "44"]); }); it('callback should take in current index as an argument if collection is an array', () => { const inputArray = ['a', 'b', 'c']; diff --git a/underpants.js b/underpants.js index c264711..17d967c 100644 --- a/underpants.js +++ b/underpants.js @@ -124,6 +124,7 @@ const _ = {}; */ + /** _.each * Arguments: * 1) A collection @@ -138,8 +139,23 @@ const _ = {}; * Examples: * _.each(["a","b","c"], function(e,i,a){ console.log(e)}); * -> should log "a" "b" "c" to the console +* +* _.each({ a: 'one', b: 'two'}, function(v, k, o){ console.log(v)}); +* -> should log "one" "two" to the console */ +_.each = (collection, func) => { + if (Array.isArray(collection)){ + for (let i = 0; i < collection.length; i++){ + func(collection[i], i, collection); + } + } else { + for (let key in collection){ + func(collection[key], key, collection); + } + } +} + /** _.unique * Arguments: From dfa5962a44bf70dd45c49aa8d5b78b1e6fff9f24 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 16:27:33 -0500 Subject: [PATCH 09/31] updated spec/underpants.spec.js to include tests for extend, reduce, some, every, pluck, map, partition, reject --- spec/underpants.spec.js | 474 ++++++++++++++++++++++++++++++++++++++++ underpants.js | 13 +- 2 files changed, 476 insertions(+), 11 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index f92474e..b195e2e 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -252,4 +252,478 @@ describe("underpants library", () => { }) }); + describe("_.reject()", () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + + const inputData = ["a",1,"b",2,"c",4]; + + it('should return an array of items rejected by the callback function', () => { + assert.deepEqual(_.reject(inputData, (e) => { + return typeof e === 'string'; + }), [1, 2,4]); + }); + it('callback function should take in the current index as an argument', () => { + const input = ['a', 'b', 'aa']; + const logs = [0, 1, 2]; + _.reject(input, (e, i, a) => { + console.log(i); + return e.length === 2; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback function should take in the array as an argument', () => { + const input = ['a', 'b', 'aa']; + _.reject(input, (e, i, a) => { + console.log(a); + return e.length === 2; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b', 'aa']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, ["a",1,"b",2,"c",4]); + }); + }); + + describe("_.partition()", () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + + const inputData = ["a",1,"b",2,"c",4]; + + it('should create a correctly partitioned array of subarrays', () => { + assert.deepEqual(_.partition(inputData, (e) => { + return typeof e === 'string'; + }), [ ['a', 'b', 'c'], [1, 2, 4]]) + }); + it('callback function should take in the current index as an argument', () => { + const input = ['a', 1]; + const logs = [0, 1]; + _.partition(input, (e, i, a) => { + console.log(i); + return typeof e === 'string'; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback function should take in the array as an argument', () => { + const input = ['a', 1]; + const logs = [['a', 1], ['a', 1]]; + _.partition(input, (e, i, a) => { + console.log(a); + return typeof e === 'string'; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + + it('should not have side effects', () => { + assert.deepEqual(inputData, ["a",1,"b",2,"c",4]); + }); + }); + + describe("_.map", () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + + const inputArray = ["a","b","c","d"]; + const inputObject = {"a":1, "b":2, "c":3, "d":4}; + + it('should correctly map an array', () => { + const result = _.map(inputArray, (e) => e.toUpperCase()); + assert.deepEqual(result, ['A', 'B', 'C', 'D']); + }); + it('should correctly map an object', () => { + const result = _.map(inputObject, (e) => e * 10); + assert.deepEqual(result, [10, 20, 30, 40]); + }); + it('callback should take in the current index as an argument if collection is an array', () => { + const logs = [0, 1, 2, 3]; + _.map(inputArray, (e, i, a) => { + console.log(i); + return e.toUpperCase(); + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in the array as argument if collection is an array', () => { + _.map(inputArray, (e, i, a) => { + console.log(a); + return e.toUpperCase(); + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ["a", "b", "c", "d"]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in the current key as an argument if collection is an argument', () => { + const logs = ["a", "b", "c", "d"]; + _.map(inputObject, (v, k, o) => { + console.log(k); + return v * 10; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in the object as an argument if collection is an argument', () => { + _.map(inputObject, (v, k, o) => { + console.log(o); + return v * 10; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], inputObject); + }) + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputArray, ["a","b","c","d"]); + assert.deepEqual(inputObject, {"a":1, "b":2, "c":3, "d":4}); + }); + }); + + describe("_.pluck()", () => { + const inputData = [ + { name: "Ralph", age: 22}, + { name: "Jimmy", age: 13}, + { name: "Carla", age: 20} + ]; + it('should pluck properties from a list of objects', () => { + const result = _.pluck(inputData, 'name'); + const correct = ['Ralph', 'Jimmy', 'Carla']; + assert.deepEqual(result, correct); + }); + it('should invoke the _.map() method', () => { + const func = _.pluck.toString(); + assert.equal(func.includes('.map('), true); + }) + it('should not have side effects', () => { + _.pluck(inputData, 'name'); + assert.deepEqual(inputData, [ + { name: "Ralph", age: 22}, + { name: "Jimmy", age: 13}, + { name: "Carla", age: 20} + ]); + }); + }); + + describe("_.every()", () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + + const inputData = [2,4,6,7,8]; + const inputObject = {a:"one",b:"two",c:"three"}; + + it('should return true when all iterations are true', () => { + const resultOne = _.every(inputData, (e) => e > 0); + const resultTwo = _.every(inputObject, (e) => typeof e === 'string'); + assert.equal(resultOne, true); + assert.equal(resultTwo, true); + }); + it('should return false when not all iterations are true for an array input', () => { + const resultOne = _.every(inputData, (e) => e % 2 === 0); + const resultTwo = _.every(inputObject, (e) => e.length === 3); + assert.equal(resultOne, false); + assert.equal(resultTwo, false); + }); + it('should return true for truthy results when no function is passed in', () => { + assert.equal(_.every(['a', 'b']), true); + assert.equal(_.every({ a: 1, b: 2 }), true); + }); + it('should return false for falsey results when no function is passed in', () => { + assert.equal(_.every(['a', 'b', null]), false); + assert.equal(_.every({ a: 1, b: 2, c: null}), false); + }); + it('callback should take in the current index as an argument if collection is an array', () => { + const input = ['a', 'b']; + const logs = [0, 1]; + _.every(input, (e, i, a) => { + console.log(i); + return typeof e === 'string'; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should take in the array as an argument if collection is an array', () => { + const input = ['a', 'b']; + _.every(input, (e, i, a) => { + console.log(a); + return typeof e === 'string'; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should take in the current value as an argument if collection is an object', () => { + const input = { a: 1, b: 2 }; + const logs = ['a', 'b']; + _.every(input, (v, k, o) => { + console.log(k); + return typeof v === 'number'; + }) + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }) + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should take in the object as an argument if collection is an object', () => { + const input = { a: 1, b: 2 }; + _.every(input, (v, k, o) => { + console.log(o); + return typeof v === 'number'; + }) + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], { a: 1, b: 2 }); + }) + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, [2,4,6,7,8]); + }); + }); + + describe("_.some()", () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + + const inputArray = [2,4,6,7,8]; + const inputObject = {a:"one",b:"two",c:"three"}; + + it('should handle objects', () => { + const result = _.every(inputObject, (e) => e.length > 3); + assert.equal(typeof result, 'boolean'); + }); + it('should return when at least one iteration is true', () => { + const resultOne = _.some(inputArray, (e) => e % 2 !== 0); + const resultTwo = _.some(inputObject, (e) => e.length > 3); + assert.equal(resultOne, true); + assert.equal(resultTwo, true); + }); + it('should return false when no iterations are true', () => { + const resultOne = _.some(inputArray, (e) => e > 10); + const resultTwo = _.some(inputObject, (e) => e.length > 5); + assert.equal(resultOne, false); + assert.equal(resultTwo, false); + }); + it('should return true for truthy results when no function is passed in', () => { + assert.equal(_.some(inputArray), true); + assert.equal(_.some(inputObject), true); + }); + it('should return false for falsey results when no function is passed in', () => { + assert.equal(_.some([undefined, null]), false); + assert.equal(_.some({a: undefined, b: null}), false); + }); + it('callback should take in current index as one of its arguments if collection is an array', () => { + const logs = [0, 1, 2]; + _.some([1, 2, 3], (e, i, a) => { + console.log(i); + return e > 0; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in array as one of its arguments if collection is an array', () => { + _.some([1, 2, 3], (e, i, a) => { + console.log(a); + return e > 0; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], [1, 2, 3]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in current key as one of its arguments if collection is an object', () => { + const logs = ['a', 'b']; + _.some({ a: 1, b: 2 }, (v, k, o) => { + console.log(k); + return v > 0; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in object as one of its arguments if collection is an object', () => { + _.some({ a: 1, b: 2 }, (v, k, o) => { + console.log(o); + return v > 0; + }); + if (console.log.args.length){ + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], { a: 1, b: 2 }); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputArray, [2,4,6,7,8]); + }); + }); + + describe("_.reduce()", () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + + const inputArray = [10,20,30,40]; + + it('should work with an array and a seed', () => { + const result = _.reduce(inputArray, (acc, current, i) => { + acc += current; + return acc; + }, 100); + assert.equal(result, 200); + }); + it('should work without a seed', () => { + const result = _.reduce(inputArray, (acc, current, i) => { + acc += current; + return acc; + }); + assert.equal(result, 100); + }); + it('should work when seed is falsey', () => { + const result = _.reduce(inputArray, (acc, current, i) => { + acc += current; + return acc; + }, 0); + assert.equal(result, 100); + }); + it('callback should take in current index as one of its arguments', () => { + const logs = [0, 1, 1]; + const resultOne = _.reduce([1, 2], (acc, current, i) => { + console.log(i); + acc += current; + return acc; + }, 0); + const resultTwo = _.reduce([3, 4], (acc, current, i) => { + console.log(i); + acc += current; + return acc; + }); + console.dir(console.log.args); + if (console.log.args.length > 0){ + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputArray, [10,20,30,40]); + }) + }); + + describe("_.extend()", () => { + it('should extend an object', () => { + const inputData = {a:"one", b:"two"}; + _.extend(inputData, {c: "three", d: "four"}); + assert.deepEqual(inputData, {a: "one",b:"two",c:"three",d:"four"}); + }); + it('should overwrite existing properties', () => { + const inputData = {a:"one", b:"two"}; + _.extend(inputData, {a: "three", d: "four"}); + assert.deepEqual(inputData, {a: "three", b:"two",d:"four"}); + }); + it('should handle any number of arguments', () => { + const inputData = {a:"one", b:"two"}; + _.extend(inputData, { c: 'three'}, { d: 'four' }, { e: 'five' }, { f: 'six' }); + assert.deepEqual(inputData, { a: 'one', b: 'two', c: 'three', d: 'four', e: 'five', f: 'six' }); + }); + + }); + }); \ No newline at end of file diff --git a/underpants.js b/underpants.js index 17d967c..b224e78 100644 --- a/underpants.js +++ b/underpants.js @@ -144,17 +144,6 @@ const _ = {}; * -> should log "one" "two" to the console */ -_.each = (collection, func) => { - if (Array.isArray(collection)){ - for (let i = 0; i < collection.length; i++){ - func(collection[i], i, collection); - } - } else { - for (let key in collection){ - func(collection[key], key, collection); - } - } -} /** _.unique @@ -168,6 +157,7 @@ _.each = (collection, func) => { */ + /** _.filter * Arguments: * 1) An array @@ -185,6 +175,7 @@ _.each = (collection, func) => { */ + /** _.reject * Arguments: * 1) An array From c10ad6d539525dc1c792c832132799fa27451c88 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 16:53:13 -0500 Subject: [PATCH 10/31] corrected tests for _.first, and _.last... tests were passing even though the function was not created --- spec/underpants.spec.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index b195e2e..d1114fc 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -35,7 +35,7 @@ describe("underpants library", () => { assert.deepEqual(_.first(["a","b","c"],2) ,["a","b"]); }); it('should return the first element if no numerical argument is given', () => { - assert.deepEqual(_.first(["a","b","c"]) ,"a"); + assert.equal(_.first(["a","b","c"]) ,"a"); }); it('should return empty array if numerical argument is not a positive number', () => { assert.deepEqual(_.first(["a","b","c"], -1) ,[], "Should return empty list if numerical argument is not a positive number."); @@ -53,7 +53,9 @@ describe("underpants library", () => { assert.deepEqual(_.last(["a","b","c"],2) ,["b","c"]); }); it('should return the last element if no numerical argument is given', () => { - assert.deepEqual(_.last(["a","b","c"]) ,"c"); + console.log('hit this test'); + console.log(_.last); + assert.equal(_.last(["a","b","c"]) ,"c"); }); it('should return empty array if numerical argument is not a positive number', () => { assert.deepEqual(_.last(["a","b","c"], -1) ,[]); From e6016cf7e9f2d51673a54af7db36c8212b4a61db Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Sun, 11 May 2025 17:11:25 -0500 Subject: [PATCH 11/31] updated test for _.every to remove mention of array input --- spec/underpants.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index d1114fc..48a6d8d 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -479,7 +479,7 @@ describe("underpants library", () => { assert.equal(resultOne, true); assert.equal(resultTwo, true); }); - it('should return false when not all iterations are true for an array input', () => { + it('should return false when not all iterations are true', () => { const resultOne = _.every(inputData, (e) => e % 2 === 0); const resultTwo = _.every(inputObject, (e) => e.length === 3); assert.equal(resultOne, false); From d272eef31a07b576cb318ce1ac9fcaf66591f141 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 11:14:03 -0500 Subject: [PATCH 12/31] corrected _.some() test in spec/underpants.spec.js to use _.some method instead of _.every... corrected test string to be more specific --- spec/underpants.spec.js | 441 +++++++++++++++++++------------- underpants.js | 538 ++++++++++++++++++++-------------------- 2 files changed, 539 insertions(+), 440 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 48a6d8d..be70997 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -1,139 +1,156 @@ -describe("underpants library", () => { - describe("_.identity()", () => { +describe('underpants library', () => { + describe('_.identity()', () => { it('should return input value unchanged', () => { - assert.strictEqual( _.identity(14), 14); - assert.deepEqual( _.identity({a: "one"}), {a: "one"}); - assert.strictEqual(_.identity("hello there"), "hello there"); - assert.deepEqual(_.identity([1,2,3]), [1,2,3]); + assert.strictEqual(_.identity(14), 14); + assert.deepEqual(_.identity({ a: 'one' }), { a: 'one' }); + assert.strictEqual(_.identity('hello there'), 'hello there'); + assert.deepEqual(_.identity([1, 2, 3]), [1, 2, 3]); }); }); - describe("_.typeof()", () => { + describe('_.typeof()', () => { it('should handle simple datatypes', () => { - assert.strictEqual(_.typeOf("a"), "string"); - assert.strictEqual(_.typeOf(10), "number"); - assert.strictEqual(_.typeOf(false), "boolean"); - assert.strictEqual(_.typeOf(undefined), "undefined"); - assert.strictEqual(_.typeOf(function(){}), "function"); + assert.strictEqual(_.typeOf('a'), 'string'); + assert.strictEqual(_.typeOf(10), 'number'); + assert.strictEqual(_.typeOf(false), 'boolean'); + assert.strictEqual(_.typeOf(undefined), 'undefined'); + assert.strictEqual( + _.typeOf(function () {}), + 'function' + ); }); it('should return `object` for objects intended as as collections', () => { - assert.strictEqual(_.typeOf({a: "one"}), "object", "Should handle objects."); + assert.strictEqual( + _.typeOf({ a: 'one' }), + 'object', + 'Should handle objects.' + ); }); it('should return `array` for array inputs', () => { - assert.strictEqual(_.typeOf([1,3]), "array"); + assert.strictEqual(_.typeOf([1, 3]), 'array'); }); it('should return `null` for null inputs', () => { - assert.strictEqual(_.typeOf(null), "null"); + assert.strictEqual(_.typeOf(null), 'null'); }); it('should return `function` for function inputs', () => { - assert.strictEqual(_.typeOf(function(){}), "function"); + assert.strictEqual( + _.typeOf(function () {}), + 'function' + ); }); }); - describe("_.first()", () => { + describe('_.first()', () => { it('should accept an argument representing the number of items to include in the output', () => { - assert.deepEqual(_.first(["a","b","c"],2) ,["a","b"]); + assert.deepEqual(_.first(['a', 'b', 'c'], 2), ['a', 'b']); }); it('should return the first element if no numerical argument is given', () => { - assert.equal(_.first(["a","b","c"]) ,"a"); + assert.equal(_.first(['a', 'b', 'c']), 'a'); }); it('should return empty array if numerical argument is not a positive number', () => { - assert.deepEqual(_.first(["a","b","c"], -1) ,[], "Should return empty list if numerical argument is not a positive number."); + assert.deepEqual( + _.first(['a', 'b', 'c'], -1), + [], + 'Should return empty list if numerical argument is not a positive number.' + ); }); it('should return empty array if the array param is not an an array', () => { - assert.deepEqual(_.first({a:"b"}, 2), [], "Should return empty array if the array param is not an array."); + assert.deepEqual( + _.first({ a: 'b' }, 2), + [], + 'Should return empty array if the array param is not an array.' + ); }); it('should return the whole array if the number is greater than the length of the array', () => { - assert.deepEqual(_.first(["a", "b", "c"], 5), ["a", "b", "c"]); + assert.deepEqual(_.first(['a', 'b', 'c'], 5), ['a', 'b', 'c']); }); }); - describe("_.last()", () => { + describe('_.last()', () => { it('should accept an argument representing the number of items to include in the output', () => { - assert.deepEqual(_.last(["a","b","c"],2) ,["b","c"]); + assert.deepEqual(_.last(['a', 'b', 'c'], 2), ['b', 'c']); }); it('should return the last element if no numerical argument is given', () => { console.log('hit this test'); console.log(_.last); - assert.equal(_.last(["a","b","c"]) ,"c"); + assert.equal(_.last(['a', 'b', 'c']), 'c'); }); it('should return empty array if numerical argument is not a positive number', () => { - assert.deepEqual(_.last(["a","b","c"], -1) ,[]); + assert.deepEqual(_.last(['a', 'b', 'c'], -1), []); }); it("shoud return the array if the numerical argument is greater than the array's length", () => { - assert.deepEqual(_.last(["a","b","c"], 5) ,["a","b","c"]); + assert.deepEqual(_.last(['a', 'b', 'c'], 5), ['a', 'b', 'c']); }); it('should return empty array if array param is not an array', () => { - assert.deepEqual(_.last({a:"b"}, 2), []); + assert.deepEqual(_.last({ a: 'b' }, 2), []); }); }); - describe("_.indexOf()", () => { - const inputData = ["a","b","c","d","b"]; + describe('_.indexOf()', () => { + const inputData = ['a', 'b', 'c', 'd', 'b']; it('should return the correct index when an element is found', () => { - assert.deepEqual(_.indexOf(inputData, "b") , 1); + assert.deepEqual(_.indexOf(inputData, 'b'), 1); }); it('should return the index of the first occurance of a found element if there are duplicates', () => { - assert.deepEqual(_.indexOf(inputData, "b"), 1); + assert.deepEqual(_.indexOf(inputData, 'b'), 1); }); it('should return -1 if the element is not found', () => { - assert.deepEqual(_.indexOf(inputData, "e") , -1); + assert.deepEqual(_.indexOf(inputData, 'e'), -1); }); it('should not have side effects', () => { - assert.deepEqual(inputData, ["a","b","c","d", "b"]); + assert.deepEqual(inputData, ['a', 'b', 'c', 'd', 'b']); }); }); - describe("_.contains()", () => { - const inputData = [1,"3",4,5,"a","4","b"]; + describe('_.contains()', () => { + const inputData = [1, '3', 4, 5, 'a', '4', 'b']; it('should return true if a list contains an element', () => { - assert.strictEqual(_.contains(inputData, "a") , true); + assert.strictEqual(_.contains(inputData, 'a'), true); }); it("should return false if the list doesn't contain an element", () => { - assert.strictEqual(_.contains(inputData, "c") , false); + assert.strictEqual(_.contains(inputData, 'c'), false); }); it('should not convert types when checking', () => { - assert.strictEqual(_.contains(inputData, 3) , false); + assert.strictEqual(_.contains(inputData, 3), false); }); it('should not have side effects', () => { - assert.deepEqual(inputData, [1,"3",4,5,"a","4","b"]); + assert.deepEqual(inputData, [1, '3', 4, 5, 'a', '4', 'b']); }); }); - describe("_.each()", () => { + describe('_.each()', () => { beforeEach(() => { sinon.spy(console, 'log'); }); - + afterEach(() => { console.log.restore(); }); it('should handle arrays', () => { - const inputArray = [1,2,3,4,5]; + const inputArray = [1, 2, 3, 4, 5]; const output = []; - _.each(inputArray, function(e, i, a){ + _.each(inputArray, function (e, i, a) { output.push(e * 10); }); assert.deepEqual(output, [10, 20, 30, 40, 50]); - }); it('should handle objects', () => { - const inputObject = {a:"1",b:"2",c:"3",d:"4"}; + const inputObject = { a: '1', b: '2', c: '3', d: '4' }; const output = []; - _.each(inputObject, function(v, k, o){ + _.each(inputObject, function (v, k, o) { output.push(v + v); }); - assert.deepEqual(output, ["11", "22", "33", "44"]); + assert.deepEqual(output, ['11', '22', '33', '44']); }); it('callback should take in current index as an argument if collection is an array', () => { const inputArray = ['a', 'b', 'c']; const logs = [0, 1, 2]; const output = []; - _.each(inputArray, function(e, i, a){ + _.each(inputArray, function (e, i, a) { console.log(i); output.push(e.toUpperCase()); }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { console.dir('hit this'); assert.equal(e[0], logs[i]); @@ -145,11 +162,11 @@ describe("underpants library", () => { it('callback should take in array as an argument if collection is an array', () => { const inputArray = ['a', 'b', 'c']; const output = []; - _.each(inputArray, function(e, i, a){ + _.each(inputArray, function (e, i, a) { console.log(a); output.push(e.toUpperCase()); }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], ['a', 'b', 'c']); }); @@ -158,13 +175,13 @@ describe("underpants library", () => { } }); it('callback should take in current key as an argument if collection is an object', () => { - const inputObject = { a: "one", b: "two" }; - const logs = ["a", "b"]; + const inputObject = { a: 'one', b: 'two' }; + const logs = ['a', 'b']; _.each(inputObject, (v, k, o) => { console.log(k); inputObject[k] = inputObject[k].toUpperCase(); }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], logs[i]); }); @@ -173,15 +190,15 @@ describe("underpants library", () => { } }); it('callback should take in object as an argument if collection is an object', () => { - const inputObject = { a: "one", b: "two" }; + const inputObject = { a: 'one', b: 'two' }; const output = []; _.each(inputObject, (v, k, o) => { console.log(o); output.push(inputObject[k].toUpperCase()); }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { - assert.deepEqual(e[0], { a: 'one', b: 'two'}); + assert.deepEqual(e[0], { a: 'one', b: 'two' }); }); } else { assert.equal(console.log.args.length > 0, true); @@ -189,45 +206,74 @@ describe("underpants library", () => { }); }); - describe("_.unique()", () => { - const inputData = ["a",1,1,"a","c",false,"b",5,"c",null,false,null]; + describe('_.unique()', () => { + const inputData = [ + 'a', + 1, + 1, + 'a', + 'c', + false, + 'b', + 5, + 'c', + null, + false, + null, + ]; it('should return an array with no duplicates', () => { - assert.deepEqual(_.unique(inputData),["a",1,"c",false,"b",5,null]); + assert.deepEqual(_.unique(inputData), ['a', 1, 'c', false, 'b', 5, null]); }); it('should invoke _.indexOf() method', () => { const func = _.unique.toString(); - assert.equal(func.includes("_.indexOf("), true); - }) + assert.equal(func.includes('_.indexOf('), true); + }); it('should not have side effects', () => { - assert.deepEqual(inputData, ["a",1,1,"a","c",false,"b",5,"c",null, false, null]); + assert.deepEqual(inputData, [ + 'a', + 1, + 1, + 'a', + 'c', + false, + 'b', + 5, + 'c', + null, + false, + null, + ]); }); }); - describe("_.filter()", () => { + describe('_.filter()', () => { beforeEach(() => { sinon.spy(console, 'log'); }); - + afterEach(() => { console.log.restore(); }); - const inputData = ["a",1,"b",2,"c",4]; + const inputData = ['a', 1, 'b', 2, 'c', 4]; it('should filter elements in an array', () => { - assert.deepEqual(_.filter(inputData, (e,i,a) => { - return typeof e === "string"; - }), ["a","b", "c"]); + assert.deepEqual( + _.filter(inputData, (e, i, a) => { + return typeof e === 'string'; + }), + ['a', 'b', 'c'] + ); }); it('callback function should take in the current index as one of its arguments', () => { const input = ['a', 'b', 'aa']; - const logs = [0, 1, 2] + const logs = [0, 1, 2]; _.filter(input, (e, i, a) => { - console.dir("current test: " + i); + console.dir('current test: ' + i); console.log(i); return e.length === 1; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); }); @@ -241,7 +287,7 @@ describe("underpants library", () => { console.log(a); return e.length === 1; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], ['a', 'b', 'aa']); }); @@ -250,25 +296,28 @@ describe("underpants library", () => { } }); it('should not have side effects', () => { - assert.deepEqual(inputData, ["a",1,"b",2,"c",4]); - }) + assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); + }); }); - describe("_.reject()", () => { + describe('_.reject()', () => { beforeEach(() => { sinon.spy(console, 'log'); }); - + afterEach(() => { console.log.restore(); }); - const inputData = ["a",1,"b",2,"c",4]; + const inputData = ['a', 1, 'b', 2, 'c', 4]; it('should return an array of items rejected by the callback function', () => { - assert.deepEqual(_.reject(inputData, (e) => { - return typeof e === 'string'; - }), [1, 2,4]); + assert.deepEqual( + _.reject(inputData, (e) => { + return typeof e === 'string'; + }), + [1, 2, 4] + ); }); it('callback function should take in the current index as an argument', () => { const input = ['a', 'b', 'aa']; @@ -277,7 +326,7 @@ describe("underpants library", () => { console.log(i); return e.length === 2; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); }); @@ -291,34 +340,40 @@ describe("underpants library", () => { console.log(a); return e.length === 2; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], ['a', 'b', 'aa']); }); } else { assert.equal(console.log.args.length > 0, true); } - }); + }); it('should not have side effects', () => { - assert.deepEqual(inputData, ["a",1,"b",2,"c",4]); + assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); }); }); - describe("_.partition()", () => { + describe('_.partition()', () => { beforeEach(() => { sinon.spy(console, 'log'); }); - + afterEach(() => { console.log.restore(); }); - const inputData = ["a",1,"b",2,"c",4]; + const inputData = ['a', 1, 'b', 2, 'c', 4]; it('should create a correctly partitioned array of subarrays', () => { - assert.deepEqual(_.partition(inputData, (e) => { - return typeof e === 'string'; - }), [ ['a', 'b', 'c'], [1, 2, 4]]) + assert.deepEqual( + _.partition(inputData, (e) => { + return typeof e === 'string'; + }), + [ + ['a', 'b', 'c'], + [1, 2, 4], + ] + ); }); it('callback function should take in the current index as an argument', () => { const input = ['a', 1]; @@ -327,7 +382,7 @@ describe("underpants library", () => { console.log(i); return typeof e === 'string'; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); }); @@ -337,12 +392,15 @@ describe("underpants library", () => { }); it('callback function should take in the array as an argument', () => { const input = ['a', 1]; - const logs = [['a', 1], ['a', 1]]; + const logs = [ + ['a', 1], + ['a', 1], + ]; _.partition(input, (e, i, a) => { console.log(a); return typeof e === 'string'; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], logs[i]); }); @@ -350,23 +408,23 @@ describe("underpants library", () => { assert.equal(console.log.args.length > 0, true); } }); - + it('should not have side effects', () => { - assert.deepEqual(inputData, ["a",1,"b",2,"c",4]); + assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); }); }); - describe("_.map", () => { + describe('_.map', () => { beforeEach(() => { sinon.spy(console, 'log'); }); - + afterEach(() => { console.log.restore(); }); - const inputArray = ["a","b","c","d"]; - const inputObject = {"a":1, "b":2, "c":3, "d":4}; + const inputArray = ['a', 'b', 'c', 'd']; + const inputObject = { a: 1, b: 2, c: 3, d: 4 }; it('should correctly map an array', () => { const result = _.map(inputArray, (e) => e.toUpperCase()); @@ -382,7 +440,7 @@ describe("underpants library", () => { console.log(i); return e.toUpperCase(); }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); }); @@ -395,21 +453,21 @@ describe("underpants library", () => { console.log(a); return e.toUpperCase(); }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { - assert.deepEqual(e[0], ["a", "b", "c", "d"]); + assert.deepEqual(e[0], ['a', 'b', 'c', 'd']); }); } else { assert.equal(console.log.args.length > 0, true); } }); it('callback should take in the current key as an argument if collection is an argument', () => { - const logs = ["a", "b", "c", "d"]; + const logs = ['a', 'b', 'c', 'd']; _.map(inputObject, (v, k, o) => { console.log(k); return v * 10; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); }); @@ -422,25 +480,25 @@ describe("underpants library", () => { console.log(o); return v * 10; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], inputObject); - }) - } else { + }); + } else { assert.equal(console.log.args.length > 0, true); } }); it('should not have side effects', () => { - assert.deepEqual(inputArray, ["a","b","c","d"]); - assert.deepEqual(inputObject, {"a":1, "b":2, "c":3, "d":4}); + assert.deepEqual(inputArray, ['a', 'b', 'c', 'd']); + assert.deepEqual(inputObject, { a: 1, b: 2, c: 3, d: 4 }); }); }); - describe("_.pluck()", () => { + describe('_.pluck()', () => { const inputData = [ - { name: "Ralph", age: 22}, - { name: "Jimmy", age: 13}, - { name: "Carla", age: 20} + { name: 'Ralph', age: 22 }, + { name: 'Jimmy', age: 13 }, + { name: 'Carla', age: 20 }, ]; it('should pluck properties from a list of objects', () => { const result = _.pluck(inputData, 'name'); @@ -450,28 +508,28 @@ describe("underpants library", () => { it('should invoke the _.map() method', () => { const func = _.pluck.toString(); assert.equal(func.includes('.map('), true); - }) + }); it('should not have side effects', () => { _.pluck(inputData, 'name'); assert.deepEqual(inputData, [ - { name: "Ralph", age: 22}, - { name: "Jimmy", age: 13}, - { name: "Carla", age: 20} + { name: 'Ralph', age: 22 }, + { name: 'Jimmy', age: 13 }, + { name: 'Carla', age: 20 }, ]); }); }); - describe("_.every()", () => { + describe('_.every()', () => { beforeEach(() => { sinon.spy(console, 'log'); }); - + afterEach(() => { console.log.restore(); }); - const inputData = [2,4,6,7,8]; - const inputObject = {a:"one",b:"two",c:"three"}; + const inputData = [2, 4, 6, 7, 8]; + const inputObject = { a: 'one', b: 'two', c: 'three' }; it('should return true when all iterations are true', () => { const resultOne = _.every(inputData, (e) => e > 0); @@ -491,7 +549,7 @@ describe("underpants library", () => { }); it('should return false for falsey results when no function is passed in', () => { assert.equal(_.every(['a', 'b', null]), false); - assert.equal(_.every({ a: 1, b: 2, c: null}), false); + assert.equal(_.every({ a: 1, b: 2, c: null }), false); }); it('callback should take in the current index as an argument if collection is an array', () => { const input = ['a', 'b']; @@ -500,7 +558,7 @@ describe("underpants library", () => { console.log(i); return typeof e === 'string'; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); }); @@ -514,7 +572,7 @@ describe("underpants library", () => { console.log(a); return typeof e === 'string'; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], ['a', 'b']); }); @@ -528,11 +586,11 @@ describe("underpants library", () => { _.every(input, (v, k, o) => { console.log(k); return typeof v === 'number'; - }) - if (console.log.args.length){ + }); + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); - }) + }); } else { assert.equal(console.log.args.length > 0, true); } @@ -542,37 +600,37 @@ describe("underpants library", () => { _.every(input, (v, k, o) => { console.log(o); return typeof v === 'number'; - }) - if (console.log.args.length){ + }); + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], { a: 1, b: 2 }); - }) + }); } else { assert.equal(console.log.args.length > 0, true); } }); it('should not have side effects', () => { - assert.deepEqual(inputData, [2,4,6,7,8]); + assert.deepEqual(inputData, [2, 4, 6, 7, 8]); }); }); - describe("_.some()", () => { + describe('_.some()', () => { beforeEach(() => { sinon.spy(console, 'log'); }); - + afterEach(() => { console.log.restore(); }); - const inputArray = [2,4,6,7,8]; - const inputObject = {a:"one",b:"two",c:"three"}; + const inputArray = [2, 4, 6, 7, 8]; + const inputObject = { a: 'one', b: 'two', c: 'three' }; it('should handle objects', () => { - const result = _.every(inputObject, (e) => e.length > 3); + const result = _.some(inputObject, (e) => e.length > 3); assert.equal(typeof result, 'boolean'); }); - it('should return when at least one iteration is true', () => { + it('should return true when at least one iteration is true', () => { const resultOne = _.some(inputArray, (e) => e % 2 !== 0); const resultTwo = _.some(inputObject, (e) => e.length > 3); assert.equal(resultOne, true); @@ -590,15 +648,15 @@ describe("underpants library", () => { }); it('should return false for falsey results when no function is passed in', () => { assert.equal(_.some([undefined, null]), false); - assert.equal(_.some({a: undefined, b: null}), false); - }); + assert.equal(_.some({ a: undefined, b: null }), false); + }); it('callback should take in current index as one of its arguments if collection is an array', () => { const logs = [0, 1, 2]; _.some([1, 2, 3], (e, i, a) => { console.log(i); return e > 0; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); }); @@ -611,7 +669,7 @@ describe("underpants library", () => { console.log(a); return e > 0; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], [1, 2, 3]); }); @@ -625,7 +683,7 @@ describe("underpants library", () => { console.log(k); return v > 0; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); }); @@ -638,7 +696,7 @@ describe("underpants library", () => { console.log(o); return v > 0; }); - if (console.log.args.length){ + if (console.log.args.length) { console.log.args.forEach((e, i) => { assert.deepEqual(e[0], { a: 1, b: 2 }); }); @@ -647,26 +705,30 @@ describe("underpants library", () => { } }); it('should not have side effects', () => { - assert.deepEqual(inputArray, [2,4,6,7,8]); + assert.deepEqual(inputArray, [2, 4, 6, 7, 8]); }); }); - describe("_.reduce()", () => { + describe('_.reduce()', () => { beforeEach(() => { sinon.spy(console, 'log'); }); - + afterEach(() => { console.log.restore(); }); - const inputArray = [10,20,30,40]; + const inputArray = [10, 20, 30, 40]; it('should work with an array and a seed', () => { - const result = _.reduce(inputArray, (acc, current, i) => { - acc += current; - return acc; - }, 100); + const result = _.reduce( + inputArray, + (acc, current, i) => { + acc += current; + return acc; + }, + 100 + ); assert.equal(result, 200); }); it('should work without a seed', () => { @@ -677,26 +739,34 @@ describe("underpants library", () => { assert.equal(result, 100); }); it('should work when seed is falsey', () => { - const result = _.reduce(inputArray, (acc, current, i) => { - acc += current; - return acc; - }, 0); + const result = _.reduce( + inputArray, + (acc, current, i) => { + acc += current; + return acc; + }, + 0 + ); assert.equal(result, 100); }); it('callback should take in current index as one of its arguments', () => { const logs = [0, 1, 1]; - const resultOne = _.reduce([1, 2], (acc, current, i) => { - console.log(i); - acc += current; - return acc; - }, 0); + const resultOne = _.reduce( + [1, 2], + (acc, current, i) => { + console.log(i); + acc += current; + return acc; + }, + 0 + ); const resultTwo = _.reduce([3, 4], (acc, current, i) => { console.log(i); acc += current; return acc; }); console.dir(console.log.args); - if (console.log.args.length > 0){ + if (console.log.args.length > 0) { console.log.args.forEach((e, i) => { assert.equal(e[0], logs[i]); }); @@ -705,27 +775,44 @@ describe("underpants library", () => { } }); it('should not have side effects', () => { - assert.deepEqual(inputArray, [10,20,30,40]); - }) + assert.deepEqual(inputArray, [10, 20, 30, 40]); + }); }); - describe("_.extend()", () => { + describe('_.extend()', () => { it('should extend an object', () => { - const inputData = {a:"one", b:"two"}; - _.extend(inputData, {c: "three", d: "four"}); - assert.deepEqual(inputData, {a: "one",b:"two",c:"three",d:"four"}); + const inputData = { a: 'one', b: 'two' }; + _.extend(inputData, { c: 'three', d: 'four' }); + assert.deepEqual(inputData, { + a: 'one', + b: 'two', + c: 'three', + d: 'four', + }); }); it('should overwrite existing properties', () => { - const inputData = {a:"one", b:"two"}; - _.extend(inputData, {a: "three", d: "four"}); - assert.deepEqual(inputData, {a: "three", b:"two",d:"four"}); + const inputData = { a: 'one', b: 'two' }; + _.extend(inputData, { a: 'three', d: 'four' }); + assert.deepEqual(inputData, { a: 'three', b: 'two', d: 'four' }); }); it('should handle any number of arguments', () => { - const inputData = {a:"one", b:"two"}; - _.extend(inputData, { c: 'three'}, { d: 'four' }, { e: 'five' }, { f: 'six' }); - assert.deepEqual(inputData, { a: 'one', b: 'two', c: 'three', d: 'four', e: 'five', f: 'six' }); + const inputData = { a: 'one', b: 'two' }; + _.extend( + inputData, + { c: 'three' }, + { d: 'four' }, + { e: 'five' }, + { f: 'six' } + ); + assert.deepEqual(inputData, { + a: 'one', + b: 'two', + c: 'three', + d: 'four', + e: 'five', + f: 'six', + }); }); - }); -}); \ No newline at end of file +}); diff --git a/underpants.js b/underpants.js index b224e78..f03f6f9 100644 --- a/underpants.js +++ b/underpants.js @@ -5,190 +5,171 @@ const _ = {}; - /** -* START OF OUR LIBRARY! -* Implement each function below its instructions -*/ + * START OF OUR LIBRARY! + * Implement each function below its instructions + */ /** _.identity -* Arguments: -* 1) Any value -* Objectives: -* 1) Returns unchanged -* Examples: -* _.identity(5) === 5 -* _.identity({a: "b"}) === {a: "b"} -*/ - - + * Arguments: + * 1) Any value + * Objectives: + * 1) Returns unchanged + * Examples: + * _.identity(5) === 5 + * _.identity({a: "b"}) === {a: "b"} + */ /** _.typeOf -* Arguments: -* 1) Any value -* Objectives: -* 1) Return the type of as a string -* Types are one of: -* - "string" -* - "array" -* - "object" -* - "undefined" -* - "number" -* - "boolean" -* - "null" -* - "function" -* Examples: -* _.typeOf(134) -> "number" -* _.typeOf("javascript") -> "string" -* _.typeOf([1,2,3]) -> "array" -*/ - - + * Arguments: + * 1) Any value + * Objectives: + * 1) Return the type of as a string + * Types are one of: + * - "string" + * - "array" + * - "object" + * - "undefined" + * - "number" + * - "boolean" + * - "null" + * - "function" + * Examples: + * _.typeOf(134) -> "number" + * _.typeOf("javascript") -> "string" + * _.typeOf([1,2,3]) -> "array" + */ /** _.first -* Arguments: -* 1) An array -* 2) A number -* Objectives: -* 1) If is not an array, return [] -* 2) If is not given or not a number, return just the first element in . -* 3) Otherwise, return the first items of -* Edge Cases: -* 1) What if is negative? -* 2) What if is not provided? -* 3) What if is greater than the length of the array? -* 3) What if is not an array? -* Examples: -* _.first("ponies", 1) -> [] -* _.first(["a", "b", "c"], -1) -> [] -* _.first(["a", "b", "c"]) -> "a" -* _.first(["a", "b", "c"], 2) -> ["a", "b"] -* _.first("a", "b", "c", 5) -> ["a", "b", "c"] -*/ - - + * Arguments: + * 1) An array + * 2) A number + * Objectives: + * 1) If is not an array, return [] + * 2) If is not given or not a number, return just the first element in . + * 3) Otherwise, return the first items of + * Edge Cases: + * 1) What if is negative? + * 2) What if is not provided? + * 3) What if is greater than the length of the array? + * 3) What if is not an array? + * Examples: + * _.first("ponies", 1) -> [] + * _.first(["a", "b", "c"], -1) -> [] + * _.first(["a", "b", "c"]) -> "a" + * _.first(["a", "b", "c"], 2) -> ["a", "b"] + * _.first("a", "b", "c", 5) -> ["a", "b", "c"] + */ /** _.last -* Arguments: -* 1) An array -* 2) A number -* Objectives: -* 1) If is not an array, return [] -* 2) If is not given or not a number, return just the last element in . -* 3) Otherwise, return the last items of -* Edge Cases: -* 1) What if is negative? -* 2) What if is greater than .length? -* 3) What if is not provided? -* 4) What if is not an array? -* Examples: -* _.last("ponies", 2) -> [] -* _.last(["a", "b", "c"], -1) -> [] -* _.last(["a", "b", "c"]) -> "c" -* _.last(["a", "b", "c"], 5) -> ["a", "b", "c"] -* _.last(["a", "b", "c"], 2) -> ["b", "c"] -*/ - + * Arguments: + * 1) An array + * 2) A number + * Objectives: + * 1) If is not an array, return [] + * 2) If is not given or not a number, return just the last element in . + * 3) Otherwise, return the last items of + * Edge Cases: + * 1) What if is negative? + * 2) What if is greater than .length? + * 3) What if is not provided? + * 4) What if is not an array? + * Examples: + * _.last("ponies", 2) -> [] + * _.last(["a", "b", "c"], -1) -> [] + * _.last(["a", "b", "c"]) -> "c" + * _.last(["a", "b", "c"], 5) -> ["a", "b", "c"] + * _.last(["a", "b", "c"], 2) -> ["b", "c"] + */ /** _.indexOf -* Arguments: -* 1) An array -* 2) A value -* Objectives: -* 1) Return the index of that is the first occurrance of -* 2) Return -1 if is not in -* 3) Do not use [].indexOf() -* Edge Cases: -* 1) What if has multiple occurances of val? -* 2) What if isn't in ? -* Examples: -* _.indexOf(["a","b","c"], "c") -> 2 -* _.indexOf(["a","b","c"], "d") -> -1 -*/ - - + * Arguments: + * 1) An array + * 2) A value + * Objectives: + * 1) Return the index of that is the first occurrance of + * 2) Return -1 if is not in + * 3) Do not use [].indexOf() + * Edge Cases: + * 1) What if has multiple occurances of val? + * 2) What if isn't in ? + * Examples: + * _.indexOf(["a","b","c"], "c") -> 2 + * _.indexOf(["a","b","c"], "d") -> -1 + */ /** _.contains -* Arguments: -* 1) An array -* 2) A value -* Objectives: -* 1) Return true if contains -* 2) Return false otherwise -* 3) You must use the ternary operator in your implementation. -* Edge Cases: -* 1) did you use === ? -* 2) what if no is given? -* Examples: -* _.contains([1,"two", 3.14], "two") -> true -*/ - - + * Arguments: + * 1) An array + * 2) A value + * Objectives: + * 1) Return true if contains + * 2) Return false otherwise + * 3) You must use the ternary operator in your implementation. + * Edge Cases: + * 1) did you use === ? + * 2) what if no is given? + * Examples: + * _.contains([1,"two", 3.14], "two") -> true + */ /** _.each -* Arguments: -* 1) A collection -* 2) A function -* Objectives: -* 1) if is an array, call once for each element -* with the arguments: -* the element, it's index, -* 2) if is an object, call once for each property -* with the arguments: -* the property's value, it's key, -* Examples: -* _.each(["a","b","c"], function(e,i,a){ console.log(e)}); -* -> should log "a" "b" "c" to the console -* -* _.each({ a: 'one', b: 'two'}, function(v, k, o){ console.log(v)}); -* -> should log "one" "two" to the console -*/ - - + * Arguments: + * 1) A collection + * 2) A function + * Objectives: + * 1) if is an array, call once for each element + * with the arguments: + * the element, it's index, + * 2) if is an object, call once for each property + * with the arguments: + * the property's value, it's key, + * Examples: + * _.each(["a","b","c"], function(e,i,a){ console.log(e)}); + * -> should log "a" "b" "c" to the console + * + * _.each({ a: 'one', b: 'two'}, function(v, k, o){ console.log(v)}); + * -> should log "one" "two" to the console + */ /** _.unique -* Arguments: -* 1) An array -* Objectives: -* 1) Return a new array of all elements from with duplicates removed -* 2) Use _.indexOf() from above -* Examples: -* _.unique([1,2,2,4,5,6,5,2]) -> [1,2,4,5,6] -*/ - - + * Arguments: + * 1) An array + * Objectives: + * 1) Return a new array of all elements from with duplicates removed + * 2) Use _.indexOf() from above + * Examples: + * _.unique([1,2,2,4,5,6,5,2]) -> [1,2,4,5,6] + */ /** _.filter -* Arguments: -* 1) An array -* 2) A function -* Objectives: -* 1) call for each element in passing the arguments: -* the element, it's index, -* 2) return a new array of elements for which calling returned true -* Edge Cases: -* 1) What if returns something other than true or false? -* Examples: -* _.filter([1,2,3,4,5], function(x){return x%2 === 0}) -> [2,4] -* Extra Credit: -* use _.each in your implementation -*/ - - + * Arguments: + * 1) An array + * 2) A function + * Objectives: + * 1) call for each element in passing the arguments: + * the element, it's index, + * 2) return a new array of elements for which calling returned true + * Edge Cases: + * 1) What if returns something other than true or false? + * Examples: + * _.filter([1,2,3,4,5], function(x){return x%2 === 0}) -> [2,4] + * Extra Credit: + * use _.each in your implementation + */ /** _.reject -* Arguments: -* 1) An array -* 2) A function -* Objectives: -* 1) call for each element in passing the arguments: -* the element, it's index, -* 2) return a new array of elements for which calling returned false -* 3) This is the logical inverse if _.filter() -* Examples: -* _.reject([1,2,3,4,5], function(e){return e%2 === 0}) -> [1,3,5] -*/ - + * Arguments: + * 1) An array + * 2) A function + * Objectives: + * 1) call for each element in passing the arguments: + * the element, it's index, + * 2) return a new array of elements for which calling returned false + * 3) This is the logical inverse if _.filter() + * Examples: + * _.reject([1,2,3,4,5], function(e){return e%2 === 0}) -> [1,3,5] + */ /** _.partition * Arguments: @@ -209,121 +190,152 @@ const _ = {}; } */ - /** _.map -* Arguments: -* 1) A collection -* 2) a function -* Objectives: -* 1) call for each element in passing the arguments: -* if is an array: -* the element, it's index, -* if is an object: -* the value, it's key, -* 2) save the return value of each call in a new array -* 3) return the new array -* Examples: -* _.map([1,2,3,4], function(e){return e * 2}) -> [2,4,6,8] -*/ - + * Arguments: + * 1) A collection + * 2) a function + * Objectives: + * 1) call for each element in passing the arguments: + * if is an array: + * the element, it's index, + * if is an object: + * the value, it's key, + * 2) save the return value of each call in a new array + * 3) return the new array + * Examples: + * _.map([1,2,3,4], function(e){return e * 2}) -> [2,4,6,8] + */ /** _.pluck -* Arguments: -* 1) An array of objects -* 2) A property -* Objectives: -* 1) Return an array containing the value of for every element in -* 2) You must use _.map() in your implementation. -* Examples: -* _.pluck([{a: "one"}, {a: "two"}], "a") -> ["one", "two"] -*/ - + * Arguments: + * 1) An array of objects + * 2) A property + * Objectives: + * 1) Return an array containing the value of for every element in + * 2) You must use _.map() in your implementation. + * Examples: + * _.pluck([{a: "one"}, {a: "two"}], "a") -> ["one", "two"] + */ /** _.every -* Arguments: -* 1) A collection -* 2) A function -* Objectives: -* 1) Call for every element of with the paramaters: -* if is an array: -* current element, it's index, -* if is an object: -* current value, current key, -* 2) If the return value of calling for every element is true, return true -* 3) If even one of them returns false, return false -* 4) If is not provided, return true if every element is truthy, otherwise return false -* Edge Cases: -* 1) what if doesn't return a boolean -* 2) What if is not given? -* Examples: -* _.every([2,4,6], function(e){return e % 2 === 0}) -> true -* _.every([1,2,3], function(e){return e % 2 === 0}) -> false -*/ + * Arguments: + * 1) A collection + * 2) A function + * Objectives: + * 1) Call for every element of with the paramaters: + * if is an array: + * current element, it's index, + * if is an object: + * current value, current key, + * 2) If the return value of calling for every element is true, return true + * 3) If even one of them returns false, return false + * 4) If is not provided, return true if every element is truthy, otherwise return false + * Edge Cases: + * 1) what if doesn't return a boolean + * 2) What if is not given? + * Examples: + * _.every([2,4,6], function(e){return e % 2 === 0}) -> true + * _.every([1,2,3], function(e){return e % 2 === 0}) -> false + */ -/** _.some -* Arguments: -* 1) A collection -* 2) A function -* Objectives: -* 1) Call for every element of with the paramaters: -* if is an array: -* current element, it's index, -* if is an object: -* current value, current key, -* 2) If the return value of calling is true for at least one element, return true -* 3) If it is false for all elements, return false -* 4) If is not provided return true if at least one element is truthy, otherwise return false -* Edge Cases: -* 1) what if doesn't return a boolean -* 2) What if is not given? -* Examples: -* _.some([1,3,5], function(e){return e % 2 === 0}) -> false -* _.some([1,2,3], function(e){return e % 2 === 0}) -> true -*/ +/** _.some + * Arguments: + * 1) A collection + * 2) A function + * Objectives: + * 1) Call for every element of with the paramaters: + * if is an array: + * current element, it's index, + * if is an object: + * current value, current key, + * 2) If the return value of calling is true for at least one element, return true + * 3) If it is false for all elements, return false + * 4) If is not provided return true if at least one element is truthy, otherwise return false + * Edge Cases: + * 1) what if doesn't return a boolean + * 2) What if is not given? + * Examples: + * _.some([1,3,5], function(e){return e % 2 === 0}) -> false + * _.some([1,2,3], function(e){return e % 2 === 0}) -> true + */ + +_.some = (coll, func) => { + if (Array.isArray(coll)){ + if (func){ + for (let i = 0; i < coll.length; i++){ + if (func(coll[i], i, coll)){ + return true; + } + } + } else { + for (let i = 0; i < coll.length; i++){ + if (coll[i]){ + return true; + } + } + } + } else { + if (func){ + for (let key in coll){ + if (func(coll[key], key, coll)){ + return true; + } + } + } else { + for (let key in coll){ + if (coll[key]){ + return true; + } + } + } + } + return false; +} /** _.reduce -* Arguments: -* 1) An array -* 2) A function -* 3) A seed -* Objectives: -* 1) Call for every element in passing the arguments: -* previous result, element, index -* 2) Use the return value of as the "previous result" -* for the next iteration -* 3) On the very first iteration, use as the "previous result" -* 4) If no was given, use the first element/value of as and continue to the next element -* 5) After the last iteration, return the return value of the final call -* Edge Cases: -* 1) What if is not given? -* Examples: -* _.reduce([1,2,3], function(previousSum, currentValue, currentIndex){ return previousSum + currentValue }, 0) -> 6 -*/ - + * Arguments: + * 1) An array + * 2) A function + * 3) A seed + * Objectives: + * 1) Call for every element in passing the arguments: + * previous result, element, index + * 2) Use the return value of as the "previous result" + * for the next iteration + * 3) On the very first iteration, use as the "previous result" + * 4) If no was given, use the first element/value of as and continue to the next element + * 5) After the last iteration, return the return value of the final call + * Edge Cases: + * 1) What if is not given? + * Examples: + * _.reduce([1,2,3], function(previousSum, currentValue, currentIndex){ return previousSum + currentValue }, 0) -> 6 + */ /** _.extend -* Arguments: -* 1) An Object -* 2) An Object -* ...Possibly more objects -* Objectives: -* 1) Copy properties from to -* 2) If more objects are passed in, copy their properties to as well, in the order they are passed in. -* 3) Return the update -* Examples: -* var data = {a:"one"}; -* _.extend(data, {b:"two"}); -> data now equals {a:"one",b:"two"} -* _.extend(data, {a:"two"}); -> data now equals {a:"two"} -*/ + * Arguments: + * 1) An Object + * 2) An Object + * ...Possibly more objects + * Objectives: + * 1) Copy properties from to + * 2) If more objects are passed in, copy their properties to as well, in the order they are passed in. + * 3) Return the update + * Examples: + * var data = {a:"one"}; + * _.extend(data, {b:"two"}); -> data now equals {a:"one",b:"two"} + * _.extend(data, {a:"two"}); -> data now equals {a:"two"} + */ //////////////////////////// // DON'T REMOVE THIS CODE // //////////////////////////// -if((typeof process !== 'undefined') && - (typeof process.versions.node !== 'undefined')) { - // here, export any references you need for tests // - module.exports = _; +if ( + typeof process !== 'undefined' && + typeof process.versions.node !== 'undefined' +) { + // here, export any references you need for tests // + module.exports = _; } From 554e6efe6468044f210b4239dc9d6913994c48db Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 11:18:53 -0500 Subject: [PATCH 13/31] removed solution code --- underpants.js | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/underpants.js b/underpants.js index f03f6f9..186ab07 100644 --- a/underpants.js +++ b/underpants.js @@ -261,38 +261,7 @@ const _ = {}; * _.some([1,2,3], function(e){return e % 2 === 0}) -> true */ -_.some = (coll, func) => { - if (Array.isArray(coll)){ - if (func){ - for (let i = 0; i < coll.length; i++){ - if (func(coll[i], i, coll)){ - return true; - } - } - } else { - for (let i = 0; i < coll.length; i++){ - if (coll[i]){ - return true; - } - } - } - } else { - if (func){ - for (let key in coll){ - if (func(coll[key], key, coll)){ - return true; - } - } - } else { - for (let key in coll){ - if (coll[key]){ - return true; - } - } - } - } - return false; -} + /** _.reduce * Arguments: @@ -313,6 +282,8 @@ _.some = (coll, func) => { * _.reduce([1,2,3], function(previousSum, currentValue, currentIndex){ return previousSum + currentValue }, 0) -> 6 */ + + /** _.extend * Arguments: * 1) An Object @@ -328,6 +299,8 @@ _.some = (coll, func) => { * _.extend(data, {a:"two"}); -> data now equals {a:"two"} */ + + //////////////////////////// // DON'T REMOVE THIS CODE // //////////////////////////// From d722fa3d9432bd6eb2e6cb1dcc875d57d1f89614 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 11:23:05 -0500 Subject: [PATCH 14/31] updated test/underpants.spec.js test code for identity and typeof --- package-lock.json | 896 ++++++++++++++++++++++++++++++++++++++++ package.json | 3 +- test/underpants.spec.js | 71 ++-- underpants.js | 2 + 4 files changed, 934 insertions(+), 38 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ae7000c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,896 @@ +{ + "name": "underpants", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "underpants", + "version": "1.0.0", + "license": "CC", + "devDependencies": { + "chai": "^3.5.0", + "istanbul": "^0.4.5", + "lodash": "^4.17.4", + "mocha": "^3.4.1", + "sinon": "^2.2.0" + } + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "dev": true, + "license": "BSD-3-Clause OR MIT", + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha512-7Rfk377tpSM9TWBEeHs0FlDZGoAIei2V/4MdZJoFMBFAK6BqLpxAIUepGRHGdPFgGsLb02PXovC4qddyHvQqTg==", + "dev": true + }, + "node_modules/chai": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", + "integrity": "sha512-eRYY0vPS2a9zt5w5Z0aCeWbrXTEyvk7u/Xf71EzNObrjSCPgMm1Nku/D/u2tiqHBX5j40wWhj54YJLtgn8g55A==", + "dev": true, + "dependencies": { + "assertion-error": "^1.0.1", + "deep-eql": "^0.1.3", + "type-detect": "^1.0.0" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", + "dev": true, + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha512-E22fsyWPt/lr4/UgQLt/pXqerGMDsanhbnmqIS3VAXuDi1v3IpiwXe2oncEIondHSBuPDWRoK/pMjlvi8FuOXQ==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha512-6sEotTRGBFiNcqVoeHwnfopbSpi5NbH1VWJmYCVkmxMmaVTT0bUTrNaGyBwhgP4MZL012W/mkzIn3Da+iDYweg==", + "dev": true, + "dependencies": { + "type-detect": "0.1.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/deep-eql/node_modules/type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha512-5rqszGVwYgBoDkIm2oUtvkfZMQ0vk29iDMU0W2qCa3rG0vPDNczCMT4hV/bLBgLg8k8ri6+u3Zbt+S/14eMzlA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha512-597ykPFhtJYaXqPq6fF7Vl1fXTKgPdLOntyxpmdzUOKiYGqK7zcnbplj5088+8qJnWdzXhyeau5iVr8HVo9dgg==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", + "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" + } + }, + "node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/estraverse": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", + "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/formatio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", + "integrity": "sha512-YAF05v8+XCxAyHOdiiAmHdgCVPrWO8X744fYIPtBciIorh5LndWfi1gjeJ16sTbJhzek9kd+j3YByhohtz5Wmg==", + "deprecated": "This package is unmaintained. Use @sinonjs/formatio instead", + "dev": true, + "dependencies": { + "samsam": "1.x" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", + "dev": true + }, + "node_modules/growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha512-RTBwDHhNuOx4F0hqzItc/siXCasGfC4DeWcBamclWd+6jWtBaeB/SGbMkGf0eiQoW7ib8JpvOgnUsmgMHI3Mfw==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", + "integrity": "sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==", + "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha512-I5YLeauH3rIaE99EE++UeH2M2gSYo8/2TqDac7oZEH6D/DSQ4Woa628Qrfj1X9/OY5Mk5VvIDQaKCDchXaKrmA==", + "deprecated": "Please use the native JSON object instead of JSON 3", + "dev": true + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha512-t3N26QR2IdSN+gqSy9Ds9pBu/J1EAFEshKlUHpJG3rvyJOYgcELIxcIeKKfZk7sjOz11cFfzJRsyFry/JyabJQ==", + "dev": true, + "dependencies": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "node_modules/lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ==", + "dev": true + }, + "node_modules/lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha512-EDem6C9iQpn7fxnGdmhXmqYGjCkStmDXT4AeyB2Ph8WKbglg4aJZczNkQglj+zWXcOEEkViK8THuV2JvugW47g==", + "dev": true + }, + "node_modules/lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==", + "dev": true + }, + "node_modules/lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==", + "dev": true + }, + "node_modules/lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha512-IUfOYwDEbI8JbhW6psW+Ig01BOVK67dTSCUAbS58M0HBkPcAv/jHuxD+oJVP2tUCo3H9L6f/8GM6rxwY+oc7/w==", + "dev": true, + "dependencies": { + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "dev": true + }, + "node_modules/lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==", + "dev": true + }, + "node_modules/lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", + "dev": true, + "dependencies": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "node_modules/lolex": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", + "integrity": "sha512-/bpxDL56TG5LS5zoXxKqA6Ro5tkOS5M8cm/7yQcwLIKIcM2HR5fjjNCaIhJNv96SEk4hNGSafYMZK42Xv5fihQ==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "dev": true, + "dependencies": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 0.10.x", + "npm": ">= 1.4.x" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-mRyN/EsN2SyNhKWykF3eEGhDpeNplMWaW18Bmh76tnOqk5TbELAVwFAYOCmKVssOYFrYvvLMguiA+NXO3ZTuVA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==", + "dev": true + }, + "node_modules/mocha/node_modules/mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha512-F8dvPrZJtNzvDRX26eNXT4a7AecAvTGljmmnI39xEgSpbHKhQ7N0dO/NTxUExd0wuLHp4zbwYY7lvHq0aKpwrA==", + "dev": true, + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/native-promise-only": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", + "integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==", + "dev": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", + "dev": true, + "license": "MIT" + }, + "node_modules/samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "deprecated": "This package has been deprecated in favour of @sinonjs/samsam", + "dev": true + }, + "node_modules/sinon": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.4.1.tgz", + "integrity": "sha512-vFTrO9Wt0ECffDYIPSP/E5bBugt0UjcBQOfQUMh66xzkyPEnhl/vM2LRZi2ajuTdkH07sA6DzrM6KvdvGIH8xw==", + "deprecated": "16.1.1", + "dev": true, + "dependencies": { + "diff": "^3.1.0", + "formatio": "1.2.0", + "lolex": "^1.6.0", + "native-promise-only": "^0.8.1", + "path-to-regexp": "^1.7.0", + "samsam": "^1.1.3", + "text-encoding": "0.6.4", + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.1.103" + } + }, + "node_modules/sinon/node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/source-map": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", + "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", + "dev": true, + "optional": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha512-hJnc6Qg3dWoOMkqP53F0dzRIgtmsAge09kxUIqGrEUS4qr5rWLckGYaQAVr+opBrIMRErGgy6f5aPnyPpyGRfg==", + "deprecated": "no longer maintained", + "dev": true + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", + "integrity": "sha512-f9Uv6ezcpvCQjJU0Zqbg+65qdcszv3qUQsZfjdRbWiZ7AMenrX1u0lNk9EoWWX6e1F+NULyg27mtdeZ5WhpljA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/package.json b/package.json index 721ceba..906f920 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,7 @@ }, "scripts": { "pretest": "npm install", - "test": "mocha ./test/underpants.spec.js || :", - "posttest": "rm -rf ./test ./node_modules" + "test": "mocha ./test/underpants.spec.js || :" }, "repository": { "type": "git", diff --git a/test/underpants.spec.js b/test/underpants.spec.js index d57c829..7076659 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -7,45 +7,44 @@ const describe('Underpants', function() { - describe('identity', function() { - it('Should handle numbers.', function() { - expect(_.identity(14)).to.equal(14); - }); - it('Should handle objects.', function() { - expect(_.identity({a: 'one'})).to.eql({a: 'one'}); - }); - it('Should handle strings.', function() { - expect(_.identity('Hello there!')).to.eql('Hello there!'); - }); - it('Should handle arrays.', function() { - expect(_.identity([1,2,3])).to.eql([1,2,3]); + describe('_.identity()', () => { + it('should return input value unchanged', () => { + assert.strictEqual(_.identity(14), 14); + assert.deepEqual(_.identity({ a: 'one' }), { a: 'one' }); + assert.strictEqual(_.identity('hello there'), 'hello there'); + assert.deepEqual(_.identity([1, 2, 3]), [1, 2, 3]); }); }); - describe('typeOf', function() { - it("Should handle strings", function() { - expect(_.typeOf("a")).to.equal("string"); - }); - it("Should handle numbers", function() { - expect(_.typeOf(10)).to.equal("number"); - }); - it("Should handle arrays", function() { - expect(_.typeOf([1,3])).to.equal("array"); - }); - it("Should handle objects", function() { - expect(_.typeOf({a: "one"})).to.equal("object"); - }); - it("Should handle booleans", function() { - expect(_.typeOf(false)).to.equal("boolean"); - }); - it("Should handle undefined", function() { - expect(_.typeOf(undefined)).to.equal("undefined"); - }); - it("Should handle null", function() { - expect(_.typeOf(null)).to.equal("null"); - }); - it("Should handle functions", function() { - expect(_.typeOf(function(){})).to.equal("function"); + describe('_.typeof()', () => { + it('should handle simple datatypes', () => { + assert.strictEqual(_.typeOf('a'), 'string'); + assert.strictEqual(_.typeOf(10), 'number'); + assert.strictEqual(_.typeOf(false), 'boolean'); + assert.strictEqual(_.typeOf(undefined), 'undefined'); + assert.strictEqual( + _.typeOf(function () {}), + 'function' + ); + }); + it('should return `object` for objects intended as as collections', () => { + assert.strictEqual( + _.typeOf({ a: 'one' }), + 'object', + 'Should handle objects.' + ); + }); + it('should return `array` for array inputs', () => { + assert.strictEqual(_.typeOf([1, 3]), 'array'); + }); + it('should return `null` for null inputs', () => { + assert.strictEqual(_.typeOf(null), 'null'); + }); + it('should return `function` for function inputs', () => { + assert.strictEqual( + _.typeOf(function () {}), + 'function' + ); }); }); diff --git a/underpants.js b/underpants.js index 186ab07..42a930c 100644 --- a/underpants.js +++ b/underpants.js @@ -20,6 +20,8 @@ const _ = {}; * _.identity({a: "b"}) === {a: "b"} */ + + /** _.typeOf * Arguments: * 1) Any value From 67551050daf296cc48413df3f5c772002c236be5 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 11:27:58 -0500 Subject: [PATCH 15/31] updated spec/underpants.spec.js and test/underpants.spec.js to remove additional string from _.first test --- spec/underpants.spec.js | 4 +- test/underpants.spec.js | 467 ++++++++++++++++++++++++---------------- 2 files changed, 278 insertions(+), 193 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index be70997..48d211a 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -57,8 +57,7 @@ describe('underpants library', () => { it('should return empty array if the array param is not an an array', () => { assert.deepEqual( _.first({ a: 'b' }, 2), - [], - 'Should return empty array if the array param is not an array.' + [] ); }); it('should return the whole array if the number is greater than the length of the array', () => { @@ -71,7 +70,6 @@ describe('underpants library', () => { assert.deepEqual(_.last(['a', 'b', 'c'], 2), ['b', 'c']); }); it('should return the last element if no numerical argument is given', () => { - console.log('hit this test'); console.log(_.last); assert.equal(_.last(['a', 'b', 'c']), 'c'); }); diff --git a/test/underpants.spec.js b/test/underpants.spec.js index 7076659..43438e9 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -1,12 +1,10 @@ -const - path = '../underpants', - _ = require(path), - expect = require('chai').expect, - assert = require('chai').assert, - sinon = require('sinon'); - -describe('Underpants', function() { +const path = '../underpants', + _ = require(path), + expect = require('chai').expect, + assert = require('chai').assert, + sinon = require('sinon'); +describe('Underpants', () => { describe('_.identity()', () => { it('should return input value unchanged', () => { assert.strictEqual(_.identity(14), 14); @@ -48,122 +46,159 @@ describe('Underpants', function() { }); }); - describe('first', function() { - it("Should return the first element if no numerical argument is given.", function() { - expect(_.first(["a","b","c"])).to.eql("a"); + describe('_.first()', () => { + it('should accept an argument representing the number of items to include in the output', () => { + assert.deepEqual(_.first(['a', 'b', 'c'], 2), ['a', 'b']); }); - it("Should accept an argument representing the number of items to include in the output.", function() { - expect(_.first(["a","b","c"],2)).to.eql(["a","b"]); + it('should return the first element if no numerical argument is given', () => { + assert.equal(_.first(['a', 'b', 'c']), 'a'); }); - it("Should return empty list if numerical argument is not a positive number.", function() { - expect(_.first(["a","b","c"], -1)).to.eql([]); + it('should return empty array if numerical argument is not a positive number', () => { + assert.deepEqual( + _.first(['a', 'b', 'c'], -1), + [], + ); }); - it("Should return the whole array if numerical argument is greater than the array's length.", function() { - expect(_.first(["a","b","c"], 5)).to.eql(["a","b","c"]); + it('should return empty array if the array param is not an an array', () => { + assert.deepEqual( + _.first({ a: 'b' }, 2), + [], + 'Should return empty array if the array param is not an array.' + ); }); - it("Should return empty array if the array param is not an array.", function() { - expect(_.first({a:"b"}, 2)).to.eql([]); + it('should return the whole array if the number is greater than the length of the array', () => { + assert.deepEqual(_.first(['a', 'b', 'c'], 5), ['a', 'b', 'c']); }); }); - describe('last', function() { - it("Should return the last element if no numerical argument is given.", function() { - expect(_.last(["a","b","c"])).to.eql("c"); + describe('_.last()', () => { + it('should accept an argument representing the number of items to include in the output', () => { + assert.deepEqual(_.last(['a', 'b', 'c'], 2), ['b', 'c']); }); - it("Should accept an argument representing the number of items to include in the output.", function() { - expect(_.last(["a","b","c"], 2)).to.eql(["b","c"]); + it('should return the last element if no numerical argument is given', () => { + console.log('hit this test'); + console.log(_.last); + assert.equal(_.last(['a', 'b', 'c']), 'c'); }); - it("Should return empty list if numerical argument is not a positive number.", function() { - expect(_.last(["a","b","c"], -1)).to.eql([]); + it('should return empty array if numerical argument is not a positive number', () => { + assert.deepEqual(_.last(['a', 'b', 'c'], -1), []); }); - it("Should return the whole array if numerical argument is greater than the array's length.", function() { - expect(_.last(["a","b","c"], 5)).to.eql(["a","b","c"]); + it("shoud return the array if the numerical argument is greater than the array's length", () => { + assert.deepEqual(_.last(['a', 'b', 'c'], 5), ['a', 'b', 'c']); }); - it("Should return empty array if the array param is not an array.", function() { - expect(_.last({a:"b"}, 2)).to.eql([]); + it('should return empty array if array param is not an array', () => { + assert.deepEqual(_.last({ a: 'b' }, 2), []); }); }); - - describe('indexOf', function() { - var inputData = ["a", "b", "c", "d"]; - it("Should return the correct index when an element is found.", function() { - expect(_.indexOf(inputData, "b")).to.equal(1); + + describe('_.indexOf()', () => { + const inputData = ['a', 'b', 'c', 'd', 'b']; + it('should return the correct index when an element is found', () => { + assert.deepEqual(_.indexOf(inputData, 'b'), 1); }); - it("Should return the index of the first occurance of a found element.", function() { - expect(_.indexOf(inputData.concat("b"), "b")).to.equal(1); + it('should return the index of the first occurance of a found element if there are duplicates', () => { + assert.deepEqual(_.indexOf(inputData, 'b'), 1); }); - it("Should return -1 if the element is not found.", function() { - expect(_.indexOf(inputData, "e")).to.equal(-1); + it('should return -1 if the element is not found', () => { + assert.deepEqual(_.indexOf(inputData, 'e'), -1); }); - it("Should not have side effects.", function() { - expect(inputData).to.eql(["a", "b", "c", "d"]); + it('should not have side effects', () => { + assert.deepEqual(inputData, ['a', 'b', 'c', 'd', 'b']); }); }); - - describe('contains', function() { - var inputData = [1, "3", 4, 5, "a", "4", "b"]; - it("Should return true if a list contains an element.", function() { - expect(_.contains(inputData, "a")).to.eql(true); + + describe('contains', function () { + var inputData = [1, '3', 4, 5, 'a', '4', 'b']; + it('Should return true if a list contains an element.', function () { + expect(_.contains(inputData, 'a')).to.eql(true); }); - it("Should return false if a list doesn't contain an element.", function() { - expect(_.contains(inputData, "c")).to.eql(false); + it("Should return false if a list doesn't contain an element.", function () { + expect(_.contains(inputData, 'c')).to.eql(false); }); - it("Should not convert types when checking.", function() { + it('Should not convert types when checking.', function () { expect(_.contains(inputData, 3)).to.eql(false); }); - it("Should not have side effects.", function() { - expect(inputData).to.eql([1, "3", 4, 5, "a", "4", "b"]); + it('Should not have side effects.', function () { + expect(inputData).to.eql([1, '3', 4, 5, 'a', '4', 'b']); }); }); - describe('each', function() { - it("Should handle arrays.", function() { + describe('each', function () { + it('Should handle arrays.', function () { var inputArray = [1, 2, 3, 4, 5]; - _.each(inputArray, function(e, i, a) { + _.each(inputArray, function (e, i, a) { inputArray[i] = e * a.length; }); expect(inputArray).to.eql([5, 10, 15, 20, 25]); }); - it("Should handle Objects.", function() { - var inputObject = { a: "1", b: "2", c: "3", d: "4" }; - _.each(inputObject, function(v, k, o) { + it('Should handle Objects.', function () { + var inputObject = { a: '1', b: '2', c: '3', d: '4' }; + _.each(inputObject, function (v, k, o) { inputObject[v] = k + Object.keys(o).length; delete inputObject[k]; }); - expect(inputObject).to.eql({ 1: "a4", 2: "b4", 3: "c4", 4: "d4" }); + expect(inputObject).to.eql({ 1: 'a4', 2: 'b4', 3: 'c4', 4: 'd4' }); }); }); - - describe('unique', function() { - var inputData = ["a", 1, 1, "a", "c", false, "b", 5, "c", null, false, null]; - it("Should return an array with no duplicates.", function() { - expect(_.unique(inputData)).to.eql(["a", 1, "c", false, "b", 5, null]); - }); - it("Should not have side effects.", function() { - expect(inputData).to.eql(["a", 1, 1, "a", "c", false, "b", 5, "c", null, false, null]); + + describe('unique', function () { + var inputData = [ + 'a', + 1, + 1, + 'a', + 'c', + false, + 'b', + 5, + 'c', + null, + false, + null, + ]; + it('Should return an array with no duplicates.', function () { + expect(_.unique(inputData)).to.eql(['a', 1, 'c', false, 'b', 5, null]); + }); + it('Should not have side effects.', function () { + expect(inputData).to.eql([ + 'a', + 1, + 1, + 'a', + 'c', + false, + 'b', + 5, + 'c', + null, + false, + null, + ]); }); }); - describe('filter', function() { - beforeEach(function() { + describe('filter', function () { + beforeEach(function () { sinon.spy(_, 'each'); // const each = sinon.spy(_.each); sinon.spy(_, 'filter'); }); - afterEach(function() { + afterEach(function () { _.each.restore(); _.filter.restore(); }); - var inputData = ["a", 1, "b", 2, "c", 4]; - it("Should filter elements in an array.", function() { - expect(_.filter(inputData, function(e, i, a) { - return typeof e === "string" && i < a.length / 2; - })).to.eql(["a", "b"]); + var inputData = ['a', 1, 'b', 2, 'c', 4]; + it('Should filter elements in an array.', function () { + expect( + _.filter(inputData, function (e, i, a) { + return typeof e === 'string' && i < a.length / 2; + }) + ).to.eql(['a', 'b']); }); - it("Should not have side effects.", function() { - expect(inputData).to.eql(["a", 1, "b", 2, "c", 4]); + it('Should not have side effects.', function () { + expect(inputData).to.eql(['a', 1, 'b', 2, 'c', 4]); }); // TODO: Incorporate test to see if each is used // xit('should use the _.each function', function() { @@ -177,27 +212,33 @@ describe('Underpants', function() { // }); }); - describe('reject', function() { - var inputData = ["a", 1, "b", 2, "c", 4]; - it("Should reject elements in an array.", function() { - expect(_.reject(inputData, function(e, i, a) { - return typeof e === "string" || i < a.length / 2; - })).to.eql([2, 4]); - }); - it("Should not have side effects.", function() { - expect(inputData).to.eql(["a", 1, "b", 2, "c", 4]); + describe('reject', function () { + var inputData = ['a', 1, 'b', 2, 'c', 4]; + it('Should reject elements in an array.', function () { + expect( + _.reject(inputData, function (e, i, a) { + return typeof e === 'string' || i < a.length / 2; + }) + ).to.eql([2, 4]); + }); + it('Should not have side effects.', function () { + expect(inputData).to.eql(['a', 1, 'b', 2, 'c', 4]); }); // TODO: Incorporate test to see if filter is used }); - describe('partition', function() { - var inputData = ["a", 1, "b", 2, "c", 4]; - it("Should reject elements in an array.", function() { - expect(_.partition(inputData, (e, i, a) => typeof e === "string")) - .to.eql([["a", "b", "c"], [1, 2, 4]]); + describe('partition', function () { + var inputData = ['a', 1, 'b', 2, 'c', 4]; + it('Should reject elements in an array.', function () { + expect(_.partition(inputData, (e, i, a) => typeof e === 'string')).to.eql( + [ + ['a', 'b', 'c'], + [1, 2, 4], + ] + ); }); - it("Should not have side effects.", function() { - expect(inputData).to.eql(["a", 1, "b", 2, "c", 4]); + it('Should not have side effects.', function () { + expect(inputData).to.eql(['a', 1, 'b', 2, 'c', 4]); }); // TODO: Add tests to check if filter and reject are used // xit('should use the _.filter function', function() { @@ -209,21 +250,28 @@ describe('Underpants', function() { // }); }); - describe('map', function() { - var inputArray = ["a", "b", "c", "d"]; + describe('map', function () { + var inputArray = ['a', 'b', 'c', 'd']; var inputObject = { a: 1, b: 2, c: 3, d: 4 }; - it("Should map through arrays.", function() { - expect(_.map(inputArray, function(e, i, a) { - return e + i * a.length; - })).to.eql(["a0", "b4", "c8", "d12"]); - }); - it("Should map through Objects.", function() { - expect(_.map(inputObject, function(v, k, o) { - return k + v * Object.keys(o).length; - })).to.eql(["a4", "b8", "c12", "d16"]); - }); - it("Should not have side effects.", function() { - expect([inputArray, inputObject]).to.eql([["a", "b", "c", "d"], { a: 1, b: 2, c: 3, d: 4 }]); + it('Should map through arrays.', function () { + expect( + _.map(inputArray, function (e, i, a) { + return e + i * a.length; + }) + ).to.eql(['a0', 'b4', 'c8', 'd12']); + }); + it('Should map through Objects.', function () { + expect( + _.map(inputObject, function (v, k, o) { + return k + v * Object.keys(o).length; + }) + ).to.eql(['a4', 'b8', 'c12', 'd16']); + }); + it('Should not have side effects.', function () { + expect([inputArray, inputObject]).to.eql([ + ['a', 'b', 'c', 'd'], + { a: 1, b: 2, c: 3, d: 4 }, + ]); }); // TODO: add test to see if each is used // xit('should use the _.each function', function() { @@ -232,117 +280,156 @@ describe('Underpants', function() { // }); }); - describe('pluck', function() { - var inputData = [{ name: "Ralph", age: 22 }, { name: "Jimmy", age: 13 }, { name: "Carla", age: 20 }]; - it("Should pluck properties out of a list of objects.", function() { - expect(_.pluck(inputData, "name")).to.eql(["Ralph", "Jimmy", "Carla"]); + describe('pluck', function () { + var inputData = [ + { name: 'Ralph', age: 22 }, + { name: 'Jimmy', age: 13 }, + { name: 'Carla', age: 20 }, + ]; + it('Should pluck properties out of a list of objects.', function () { + expect(_.pluck(inputData, 'name')).to.eql(['Ralph', 'Jimmy', 'Carla']); }); - it("Should not have side effects.", function() { - expect(inputData).to.eql([{ name: "Ralph", age: 22 }, { name: "Jimmy", age: 13 }, { name: "Carla", age: 20 }]); + it('Should not have side effects.', function () { + expect(inputData).to.eql([ + { name: 'Ralph', age: 22 }, + { name: 'Jimmy', age: 13 }, + { name: 'Carla', age: 20 }, + ]); }); - }); - describe('every', function() { + describe('every', function () { var inputData = [2, 4, 6, 7, 8]; - var inputDataTruthy = [1, [], true, "a"]; - var inputDataFalsy = ["", 0, false, null]; - var inputObject = { a: "one", b: "two", c: "three" }; - it("Should return true when all iterations are true", function() { - expect(_.every(inputData, function(v) { - return v % 2 === 0 || v === 7; - })).to.equal(true); - }); - it("Should return false when not all iterations are true", function() { - expect(_.every(inputData, function(v) { - return v % 2 === 0; - })).to.equal(false); - }); - it("Should handle objects", function() { - expect(_.every(inputObject, function(v, k, o) { - return ["aone3", "btwo3", "cthree3"].indexOf(k + v + Object.keys(o).length) !== -1; - })).to.equal(true); - }); - it("Should return true for truthy results when no function is passed in.", function() { + var inputDataTruthy = [1, [], true, 'a']; + var inputDataFalsy = ['', 0, false, null]; + var inputObject = { a: 'one', b: 'two', c: 'three' }; + it('Should return true when all iterations are true', function () { + expect( + _.every(inputData, function (v) { + return v % 2 === 0 || v === 7; + }) + ).to.equal(true); + }); + it('Should return false when not all iterations are true', function () { + expect( + _.every(inputData, function (v) { + return v % 2 === 0; + }) + ).to.equal(false); + }); + it('Should handle objects', function () { + expect( + _.every(inputObject, function (v, k, o) { + return ( + ['aone3', 'btwo3', 'cthree3'].indexOf( + k + v + Object.keys(o).length + ) !== -1 + ); + }) + ).to.equal(true); + }); + it('Should return true for truthy results when no function is passed in.', function () { expect(_.every(inputDataTruthy)).to.equal(true); }); - it("Should return false for falsy results when no function is passed in.", function() { + it('Should return false for falsy results when no function is passed in.', function () { expect(_.every(inputDataFalsy)).to.equal(false); }); - it("Should not have side effects.", function() { + it('Should not have side effects.', function () { expect(inputData).to.eql([2, 4, 6, 7, 8]); }); }); - describe('some', function() { + describe('some', function () { var inputData = [2, 4, 6, 7, 8]; - var inputDataTruthy = [1, [], true, "a"]; - var inputDataFalsy = ["", 0, false, null]; - var inputObject = { a: "one", b: "two", c: "three" }; - it("Should return true when at least one iteration is true", function() { - expect(_.some(inputData, function(v) { - return v === 7; - })).to.equal(true); - }); - it("Should return false when no iterations are true", function() { - expect(_.some(inputData, function(v) { - return v > 10; - })).to.equal(false); - }); - it("Should handle objects", function() { - expect(_.some(inputObject, function(v, k, o) { - return ["aone3", "btwo3"].indexOf(k + v + Object.keys(o).length) !== -1; - })).to.equal(true); - }); - it("Should return true for truthy results when no function is passed in.", function() { + var inputDataTruthy = [1, [], true, 'a']; + var inputDataFalsy = ['', 0, false, null]; + var inputObject = { a: 'one', b: 'two', c: 'three' }; + it('Should return true when at least one iteration is true', function () { + expect( + _.some(inputData, function (v) { + return v === 7; + }) + ).to.equal(true); + }); + it('Should return false when no iterations are true', function () { + expect( + _.some(inputData, function (v) { + return v > 10; + }) + ).to.equal(false); + }); + it('Should handle objects', function () { + expect( + _.some(inputObject, function (v, k, o) { + return ( + ['aone3', 'btwo3'].indexOf(k + v + Object.keys(o).length) !== -1 + ); + }) + ).to.equal(true); + }); + it('Should return true for truthy results when no function is passed in.', function () { expect(_.some(inputDataTruthy)).to.equal(true); }); - it("Should return false for falsy results when no function is passed in.", function() { + it('Should return false for falsy results when no function is passed in.', function () { expect(_.some(inputDataFalsy)).to.equal(false); }); - it("Should not have side effects.", function() { + it('Should not have side effects.', function () { expect(inputData).to.eql([2, 4, 6, 7, 8]); }); }); - describe('reduce', function() { - var inputArray = [10,20,30,40]; - it("Should work with an array and a seed", function() { - expect(_.reduce(inputArray, function(memo, element, i){ - return memo + element + i; - }, 10)).to.equal(116); - }); - it("Should work without a seed", function() { - expect(_.reduce(inputArray, function(memo, element, i){ - return memo * element * (i+1); - })).to.equal(5760000); - }); - it("Should work when seed is falsy", function() { - expect(_.reduce(inputArray, function(memo, element, i){ - return memo * element * (i+1); - }, 0)).to.equal(0); - }); - it("Should not have side effects", function() { + describe('reduce', function () { + var inputArray = [10, 20, 30, 40]; + it('Should work with an array and a seed', function () { + expect( + _.reduce( + inputArray, + function (memo, element, i) { + return memo + element + i; + }, + 10 + ) + ).to.equal(116); + }); + it('Should work without a seed', function () { + expect( + _.reduce(inputArray, function (memo, element, i) { + return memo * element * (i + 1); + }) + ).to.equal(5760000); + }); + it('Should work when seed is falsy', function () { + expect( + _.reduce( + inputArray, + function (memo, element, i) { + return memo * element * (i + 1); + }, + 0 + ) + ).to.equal(0); + }); + it('Should not have side effects', function () { expect(inputArray).to.eql([10, 20, 30, 40]); }); }); - describe('extend', function() { - it("Should extend an object.", function() { - var inputData = { a: "one", b: "two" }; - _.extend(inputData, { c: "three", d: "four" }); - expect(inputData).to.eql({ a: "one", b: "two", c: "three", d: "four" }); - }); - it("Should overwrite existing properties", function() { - var inputData = { a: "one", b: "two" }; - _.extend(inputData, { a: "three", d: "four" }); - expect(inputData).to.eql({ a: "three", b: "two", d: "four" }); - }); - it("Should handle any number of arguments.", function() { - var inputData = { a: "one", b: "two" }; - _.extend(inputData, { a: "three", c: "four" }, { d: "five", c: "six" }); - expect(inputData).to.eql({ a: "three", b: "two", c: "six", d: "five" }); + describe('extend', function () { + it('Should extend an object.', function () { + var inputData = { a: 'one', b: 'two' }; + _.extend(inputData, { c: 'three', d: 'four' }); + expect(inputData).to.eql({ a: 'one', b: 'two', c: 'three', d: 'four' }); + }); + it('Should overwrite existing properties', function () { + var inputData = { a: 'one', b: 'two' }; + _.extend(inputData, { a: 'three', d: 'four' }); + expect(inputData).to.eql({ a: 'three', b: 'two', d: 'four' }); + }); + it('Should handle any number of arguments.', function () { + var inputData = { a: 'one', b: 'two' }; + _.extend(inputData, { a: 'three', c: 'four' }, { d: 'five', c: 'six' }); + expect(inputData).to.eql({ a: 'three', b: 'two', c: 'six', d: 'five' }); }); }); }); From 5a9ae657e1c5fe6b5026ef09f50fc65ae4e94c61 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 11:28:55 -0500 Subject: [PATCH 16/31] removed additional string from test/underpants.spec.js _.first test --- test/underpants.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/underpants.spec.js b/test/underpants.spec.js index 43438e9..365a7b5 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -62,8 +62,7 @@ describe('Underpants', () => { it('should return empty array if the array param is not an an array', () => { assert.deepEqual( _.first({ a: 'b' }, 2), - [], - 'Should return empty array if the array param is not an array.' + [] ); }); it('should return the whole array if the number is greater than the length of the array', () => { From ed4130f1579dae16f50ed70985656f507b0e118c Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 11:36:43 -0500 Subject: [PATCH 17/31] corrected camel casing of .typeOf in test code --- spec/underpants.spec.js | 2 +- test/underpants.spec.js | 130 +++++++++++++++++++++++++++++++--------- 2 files changed, 102 insertions(+), 30 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 48d211a..adf326d 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -8,7 +8,7 @@ describe('underpants library', () => { }); }); - describe('_.typeof()', () => { + describe('_.typeOff()', () => { it('should handle simple datatypes', () => { assert.strictEqual(_.typeOf('a'), 'string'); assert.strictEqual(_.typeOf(10), 'number'); diff --git a/test/underpants.spec.js b/test/underpants.spec.js index 365a7b5..641b727 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -14,7 +14,7 @@ describe('Underpants', () => { }); }); - describe('_.typeof()', () => { + describe('_.typeOf()', () => { it('should handle simple datatypes', () => { assert.strictEqual(_.typeOf('a'), 'string'); assert.strictEqual(_.typeOf(10), 'number'); @@ -75,8 +75,6 @@ describe('Underpants', () => { assert.deepEqual(_.last(['a', 'b', 'c'], 2), ['b', 'c']); }); it('should return the last element if no numerical argument is given', () => { - console.log('hit this test'); - console.log(_.last); assert.equal(_.last(['a', 'b', 'c']), 'c'); }); it('should return empty array if numerical argument is not a positive number', () => { @@ -106,42 +104,112 @@ describe('Underpants', () => { }); }); - describe('contains', function () { - var inputData = [1, '3', 4, 5, 'a', '4', 'b']; - it('Should return true if a list contains an element.', function () { - expect(_.contains(inputData, 'a')).to.eql(true); + describe('_.contains()', () => { + const inputData = [1, '3', 4, 5, 'a', '4', 'b']; + it('should return true if a list contains an element', () => { + assert.strictEqual(_.contains(inputData, 'a'), true); }); - it("Should return false if a list doesn't contain an element.", function () { - expect(_.contains(inputData, 'c')).to.eql(false); + it("should return false if the list doesn't contain an element", () => { + assert.strictEqual(_.contains(inputData, 'c'), false); }); - it('Should not convert types when checking.', function () { - expect(_.contains(inputData, 3)).to.eql(false); + it('should not convert types when checking', () => { + assert.strictEqual(_.contains(inputData, 3), false); }); - it('Should not have side effects.', function () { - expect(inputData).to.eql([1, '3', 4, 5, 'a', '4', 'b']); + it('should not have side effects', () => { + assert.deepEqual(inputData, [1, '3', 4, 5, 'a', '4', 'b']); }); }); - describe('each', function () { - it('Should handle arrays.', function () { - var inputArray = [1, 2, 3, 4, 5]; + describe('_.each()', () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + it('should handle arrays', () => { + const inputArray = [1, 2, 3, 4, 5]; + const output = []; _.each(inputArray, function (e, i, a) { - inputArray[i] = e * a.length; + output.push(e * 10); }); - expect(inputArray).to.eql([5, 10, 15, 20, 25]); + assert.deepEqual(output, [10, 20, 30, 40, 50]); }); - it('Should handle Objects.', function () { - var inputObject = { a: '1', b: '2', c: '3', d: '4' }; + it('should handle objects', () => { + const inputObject = { a: '1', b: '2', c: '3', d: '4' }; + const output = []; _.each(inputObject, function (v, k, o) { - inputObject[v] = k + Object.keys(o).length; - delete inputObject[k]; + output.push(v + v); }); - expect(inputObject).to.eql({ 1: 'a4', 2: 'b4', 3: 'c4', 4: 'd4' }); + assert.deepEqual(output, ['11', '22', '33', '44']); + }); + it('callback should take in current index as an argument if collection is an array', () => { + const inputArray = ['a', 'b', 'c']; + const logs = [0, 1, 2]; + const output = []; + _.each(inputArray, function (e, i, a) { + console.log(i); + output.push(e.toUpperCase()); + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + console.dir('hit this'); + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in array as an argument if collection is an array', () => { + const inputArray = ['a', 'b', 'c']; + const output = []; + _.each(inputArray, function (e, i, a) { + console.log(a); + output.push(e.toUpperCase()); + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b', 'c']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in current key as an argument if collection is an object', () => { + const inputObject = { a: 'one', b: 'two' }; + const logs = ['a', 'b']; + _.each(inputObject, (v, k, o) => { + console.log(k); + inputObject[k] = inputObject[k].toUpperCase(); + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in object as an argument if collection is an object', () => { + const inputObject = { a: 'one', b: 'two' }; + const output = []; + _.each(inputObject, (v, k, o) => { + console.log(o); + output.push(inputObject[k].toUpperCase()); + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], { a: 'one', b: 'two' }); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } }); }); - describe('unique', function () { - var inputData = [ + describe('_.unique()', () => { + const inputData = [ 'a', 1, 1, @@ -155,11 +223,15 @@ describe('Underpants', () => { false, null, ]; - it('Should return an array with no duplicates.', function () { - expect(_.unique(inputData)).to.eql(['a', 1, 'c', false, 'b', 5, null]); + it('should return an array with no duplicates', () => { + assert.deepEqual(_.unique(inputData), ['a', 1, 'c', false, 'b', 5, null]); }); - it('Should not have side effects.', function () { - expect(inputData).to.eql([ + it('should invoke _.indexOf() method', () => { + const func = _.unique.toString(); + assert.equal(func.includes('_.indexOf('), true); + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, [ 'a', 1, 1, From 9d6672244874112c1c17a650df7a37270037025c Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 12:04:38 -0500 Subject: [PATCH 18/31] updated filter tests in test and spec directories to include optional test to use _.each and removed unnecessary console.log statements --- spec/underpants.spec.js | 99 ++++++++++++++++++++++------------------- test/underpants.spec.js | 73 +++++++++++++++++++----------- 2 files changed, 100 insertions(+), 72 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index adf326d..686e94c 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -245,58 +245,63 @@ describe('underpants library', () => { }); describe('_.filter()', () => { - beforeEach(() => { - sinon.spy(console, 'log'); - }); - - afterEach(() => { - console.log.restore(); - }); - - const inputData = ['a', 1, 'b', 2, 'c', 4]; - - it('should filter elements in an array', () => { - assert.deepEqual( - _.filter(inputData, (e, i, a) => { - return typeof e === 'string'; - }), - ['a', 'b', 'c'] - ); - }); - it('callback function should take in the current index as one of its arguments', () => { - const input = ['a', 'b', 'aa']; - const logs = [0, 1, 2]; - _.filter(input, (e, i, a) => { - console.dir('current test: ' + i); - console.log(i); - return e.length === 1; + beforeEach(() => { + sinon.spy(console, 'log'); + sinon.spy(_, "each"); }); - if (console.log.args.length) { - console.log.args.forEach((e, i) => { - assert.equal(e[0], logs[i]); + + afterEach(() => { + console.log.restore(); + _.each.restore(); + }); + + const inputData = ['a', 1, 'b', 2, 'c', 4]; + + it('should filter elements in an array', () => { + assert.deepEqual( + _.filter(inputData, (e, i, a) => { + return typeof e === 'string'; + }), + ['a', 'b', 'c'] + ); + }); + it('callback function should take in the current index as one of its arguments', () => { + const input = ['a', 'b', 'aa']; + const logs = [0, 1, 2]; + _.filter(input, (e, i, a) => { + console.log(i); + return e.length === 1; }); - } else { - assert.equal(console.log.args.length > 0, true); - } - }); - it('callback function should take in the array as one its arguments', () => { - const input = ['a', 'b', 'aa']; - _.filter(input, (e, i, a) => { - console.log(a); - return e.length === 1; + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } }); - if (console.log.args.length) { - console.log.args.forEach((e, i) => { - assert.deepEqual(e[0], ['a', 'b', 'aa']); + it('callback function should take in the array as one its arguments', () => { + const input = ['a', 'b', 'aa']; + _.filter(input, (e, i, a) => { + console.log(a); + return e.length === 1; }); - } else { - assert.equal(console.log.args.length > 0, true); - } - }); - it('should not have side effects', () => { - assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b', 'aa']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); + }); + // it('optional - use _.each', () => { + // _.filter([1, 2, 3, 4], (e) => e % 2 === 0); + // expect(_.each.calledOnce).to.be.true; + // }); }); - }); describe('_.reject()', () => { beforeEach(() => { diff --git a/test/underpants.spec.js b/test/underpants.spec.js index 641b727..9c904ff 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -154,7 +154,6 @@ describe('Underpants', () => { }); if (console.log.args.length) { console.log.args.forEach((e, i) => { - console.dir('hit this'); assert.equal(e[0], logs[i]); }); } else { @@ -248,37 +247,61 @@ describe('Underpants', () => { }); }); - describe('filter', function () { - beforeEach(function () { - sinon.spy(_, 'each'); - // const each = sinon.spy(_.each); - sinon.spy(_, 'filter'); + describe('_.filter()', () => { + beforeEach(() => { + sinon.spy(console, 'log'); + sinon.spy(_, "each"); }); - afterEach(function () { + afterEach(() => { + console.log.restore(); _.each.restore(); - _.filter.restore(); }); - var inputData = ['a', 1, 'b', 2, 'c', 4]; - it('Should filter elements in an array.', function () { - expect( - _.filter(inputData, function (e, i, a) { - return typeof e === 'string' && i < a.length / 2; - }) - ).to.eql(['a', 'b']); + const inputData = ['a', 1, 'b', 2, 'c', 4]; + + it('should filter elements in an array', () => { + assert.deepEqual( + _.filter(inputData, (e, i, a) => { + return typeof e === 'string'; + }), + ['a', 'b', 'c'] + ); }); - it('Should not have side effects.', function () { - expect(inputData).to.eql(['a', 1, 'b', 2, 'c', 4]); + it('callback function should take in the current index as one of its arguments', () => { + const input = ['a', 'b', 'aa']; + const logs = [0, 1, 2]; + _.filter(input, (e, i, a) => { + console.log(i); + return e.length === 1; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } }); - // TODO: Incorporate test to see if each is used - // xit('should use the _.each function', function() { - // var isEven = function(num) { return num % 2 === 0; }; - // expect(_.each.calledOnce).to.be.false; - // - // _.filter([1, 2, 3, 4, 5, 6], isEven); - // - // console.log('each', _.each); + it('callback function should take in the array as one its arguments', () => { + const input = ['a', 'b', 'aa']; + _.filter(input, (e, i, a) => { + console.log(a); + return e.length === 1; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b', 'aa']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); + }); + // it('optional - use _.each', () => { + // _.filter([1, 2, 3, 4], (e) => e % 2 === 0); // expect(_.each.calledOnce).to.be.true; // }); }); From a02d8c9b4079b6f2f5af0fb43387f89ee2c72d41 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 12:16:18 -0500 Subject: [PATCH 19/31] updated reject, partition, and map test code --- test/underpants.spec.js | 238 ++++++++++++++++++++++++++++++---------- 1 file changed, 179 insertions(+), 59 deletions(-) diff --git a/test/underpants.spec.js b/test/underpants.spec.js index 9c904ff..5d80195 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -54,16 +54,10 @@ describe('Underpants', () => { assert.equal(_.first(['a', 'b', 'c']), 'a'); }); it('should return empty array if numerical argument is not a positive number', () => { - assert.deepEqual( - _.first(['a', 'b', 'c'], -1), - [], - ); + assert.deepEqual(_.first(['a', 'b', 'c'], -1), []); }); it('should return empty array if the array param is not an an array', () => { - assert.deepEqual( - _.first({ a: 'b' }, 2), - [] - ); + assert.deepEqual(_.first({ a: 'b' }, 2), []); }); it('should return the whole array if the number is greater than the length of the array', () => { assert.deepEqual(_.first(['a', 'b', 'c'], 5), ['a', 'b', 'c']); @@ -250,7 +244,7 @@ describe('Underpants', () => { describe('_.filter()', () => { beforeEach(() => { sinon.spy(console, 'log'); - sinon.spy(_, "each"); + sinon.spy(_, 'each'); }); afterEach(() => { @@ -306,72 +300,198 @@ describe('Underpants', () => { // }); }); - describe('reject', function () { - var inputData = ['a', 1, 'b', 2, 'c', 4]; - it('Should reject elements in an array.', function () { - expect( - _.reject(inputData, function (e, i, a) { - return typeof e === 'string' || i < a.length / 2; - }) - ).to.eql([2, 4]); + describe('_.reject()', () => { + beforeEach(() => { + sinon.spy(console, 'log'); }); - it('Should not have side effects.', function () { - expect(inputData).to.eql(['a', 1, 'b', 2, 'c', 4]); + + afterEach(() => { + console.log.restore(); + }); + + const inputData = ['a', 1, 'b', 2, 'c', 4]; + + it('should return an array of items rejected by the callback function', () => { + assert.deepEqual( + _.reject(inputData, (e) => { + return typeof e === 'string'; + }), + [1, 2, 4] + ); + }); + it('callback function should take in the current index as an argument', () => { + const input = ['a', 'b', 'aa']; + const logs = [0, 1, 2]; + _.reject(input, (e, i, a) => { + console.log(i); + return e.length === 2; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback function should take in the array as an argument', () => { + const input = ['a', 'b', 'aa']; + _.reject(input, (e, i, a) => { + console.log(a); + return e.length === 2; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b', 'aa']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); }); - // TODO: Incorporate test to see if filter is used }); - describe('partition', function () { - var inputData = ['a', 1, 'b', 2, 'c', 4]; - it('Should reject elements in an array.', function () { - expect(_.partition(inputData, (e, i, a) => typeof e === 'string')).to.eql( + describe('_.partition()', () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + + const inputData = ['a', 1, 'b', 2, 'c', 4]; + + it('should create a correctly partitioned array of subarrays', () => { + assert.deepEqual( + _.partition(inputData, (e) => { + return typeof e === 'string'; + }), [ ['a', 'b', 'c'], [1, 2, 4], ] ); }); - it('Should not have side effects.', function () { - expect(inputData).to.eql(['a', 1, 'b', 2, 'c', 4]); + it('callback function should take in the current index as an argument', () => { + const input = ['a', 1]; + const logs = [0, 1]; + _.partition(input, (e, i, a) => { + console.log(i); + return typeof e === 'string'; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback function should take in the array as an argument', () => { + const input = ['a', 1]; + const logs = [ + ['a', 1], + ['a', 1], + ]; + _.partition(input, (e, i, a) => { + console.log(a); + return typeof e === 'string'; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + + it('should not have side effects', () => { + assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); }); - // TODO: Add tests to check if filter and reject are used - // xit('should use the _.filter function', function() { - // expect(_.filter.called).to.be.true; - // }); - // - // xit('should use the _.reject function', function() { - // expect(_.reject.called).to.be.true; - // }); }); - describe('map', function () { - var inputArray = ['a', 'b', 'c', 'd']; - var inputObject = { a: 1, b: 2, c: 3, d: 4 }; - it('Should map through arrays.', function () { - expect( - _.map(inputArray, function (e, i, a) { - return e + i * a.length; - }) - ).to.eql(['a0', 'b4', 'c8', 'd12']); + describe('_.map', () => { + beforeEach(() => { + sinon.spy(console, 'log'); }); - it('Should map through Objects.', function () { - expect( - _.map(inputObject, function (v, k, o) { - return k + v * Object.keys(o).length; - }) - ).to.eql(['a4', 'b8', 'c12', 'd16']); + + afterEach(() => { + console.log.restore(); }); - it('Should not have side effects.', function () { - expect([inputArray, inputObject]).to.eql([ - ['a', 'b', 'c', 'd'], - { a: 1, b: 2, c: 3, d: 4 }, - ]); + + const inputArray = ['a', 'b', 'c', 'd']; + const inputObject = { a: 1, b: 2, c: 3, d: 4 }; + + it('should correctly map an array', () => { + const result = _.map(inputArray, (e) => e.toUpperCase()); + assert.deepEqual(result, ['A', 'B', 'C', 'D']); + }); + it('should correctly map an object', () => { + const result = _.map(inputObject, (e) => e * 10); + assert.deepEqual(result, [10, 20, 30, 40]); + }); + it('callback should take in the current index as an argument if collection is an array', () => { + const logs = [0, 1, 2, 3]; + _.map(inputArray, (e, i, a) => { + console.log(i); + return e.toUpperCase(); + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in the array as argument if collection is an array', () => { + _.map(inputArray, (e, i, a) => { + console.log(a); + return e.toUpperCase(); + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b', 'c', 'd']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in the current key as an argument if collection is an argument', () => { + const logs = ['a', 'b', 'c', 'd']; + _.map(inputObject, (v, k, o) => { + console.log(k); + return v * 10; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in the object as an argument if collection is an argument', () => { + _.map(inputObject, (v, k, o) => { + console.log(o); + return v * 10; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], inputObject); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputArray, ['a', 'b', 'c', 'd']); + assert.deepEqual(inputObject, { a: 1, b: 2, c: 3, d: 4 }); }); - // TODO: add test to see if each is used - // xit('should use the _.each function', function() { - // console.log(_.map.toString()); - // expect(_.map.toString()).to.contain('_.each'); - // }); }); describe('pluck', function () { From 1f8cf3716664a51ac4061c19334e832e5767f80c Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 12:28:35 -0500 Subject: [PATCH 20/31] updated pluck, every, some tests in tests/underpants.spec.js and added map test to pluck tests for spec and test directories --- spec/underpants.spec.js | 120 +++++++++--------- test/underpants.spec.js | 264 +++++++++++++++++++++++++++++----------- 2 files changed, 254 insertions(+), 130 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 686e94c..5387232 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -55,10 +55,7 @@ describe('underpants library', () => { ); }); it('should return empty array if the array param is not an an array', () => { - assert.deepEqual( - _.first({ a: 'b' }, 2), - [] - ); + assert.deepEqual(_.first({ a: 'b' }, 2), []); }); it('should return the whole array if the number is greater than the length of the array', () => { assert.deepEqual(_.first(['a', 'b', 'c'], 5), ['a', 'b', 'c']); @@ -245,63 +242,63 @@ describe('underpants library', () => { }); describe('_.filter()', () => { - beforeEach(() => { - sinon.spy(console, 'log'); - sinon.spy(_, "each"); - }); - - afterEach(() => { - console.log.restore(); - _.each.restore(); - }); - - const inputData = ['a', 1, 'b', 2, 'c', 4]; - - it('should filter elements in an array', () => { - assert.deepEqual( - _.filter(inputData, (e, i, a) => { - return typeof e === 'string'; - }), - ['a', 'b', 'c'] - ); + beforeEach(() => { + sinon.spy(console, 'log'); + sinon.spy(_, 'each'); + }); + + afterEach(() => { + console.log.restore(); + _.each.restore(); + }); + + const inputData = ['a', 1, 'b', 2, 'c', 4]; + + it('should filter elements in an array', () => { + assert.deepEqual( + _.filter(inputData, (e, i, a) => { + return typeof e === 'string'; + }), + ['a', 'b', 'c'] + ); + }); + it('callback function should take in the current index as one of its arguments', () => { + const input = ['a', 'b', 'aa']; + const logs = [0, 1, 2]; + _.filter(input, (e, i, a) => { + console.log(i); + return e.length === 1; }); - it('callback function should take in the current index as one of its arguments', () => { - const input = ['a', 'b', 'aa']; - const logs = [0, 1, 2]; - _.filter(input, (e, i, a) => { - console.log(i); - return e.length === 1; + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); }); - if (console.log.args.length) { - console.log.args.forEach((e, i) => { - assert.equal(e[0], logs[i]); - }); - } else { - assert.equal(console.log.args.length > 0, true); - } + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback function should take in the array as one its arguments', () => { + const input = ['a', 'b', 'aa']; + _.filter(input, (e, i, a) => { + console.log(a); + return e.length === 1; }); - it('callback function should take in the array as one its arguments', () => { - const input = ['a', 'b', 'aa']; - _.filter(input, (e, i, a) => { - console.log(a); - return e.length === 1; + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b', 'aa']); }); - if (console.log.args.length) { - console.log.args.forEach((e, i) => { - assert.deepEqual(e[0], ['a', 'b', 'aa']); - }); - } else { - assert.equal(console.log.args.length > 0, true); - } - }); - it('should not have side effects', () => { - assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); - }); - // it('optional - use _.each', () => { - // _.filter([1, 2, 3, 4], (e) => e % 2 === 0); - // expect(_.each.calledOnce).to.be.true; - // }); + } else { + assert.equal(console.log.args.length > 0, true); + } }); + it('should not have side effects', () => { + assert.deepEqual(inputData, ['a', 1, 'b', 2, 'c', 4]); + }); + // it('optional - use _.each', () => { + // _.filter([1, 2, 3, 4], (e) => e % 2 === 0); + // expect(_.each.calledOnce).to.be.true; + // }); + }); describe('_.reject()', () => { beforeEach(() => { @@ -498,6 +495,12 @@ describe('underpants library', () => { }); describe('_.pluck()', () => { + beforeEach(() => { + sinon.spy(_, "map"); + }) + afterEach(() => { + _.map.restore(); + }) const inputData = [ { name: 'Ralph', age: 22 }, { name: 'Jimmy', age: 13 }, @@ -509,8 +512,8 @@ describe('underpants library', () => { assert.deepEqual(result, correct); }); it('should invoke the _.map() method', () => { - const func = _.pluck.toString(); - assert.equal(func.includes('.map('), true); + _.pluck(inputData, 'age'); + expect(_.map.calledOnce).to.be.true; }); it('should not have side effects', () => { _.pluck(inputData, 'name'); @@ -817,5 +820,4 @@ describe('underpants library', () => { }); }); }); - }); diff --git a/test/underpants.spec.js b/test/underpants.spec.js index 5d80195..51d7e8b 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -494,18 +494,30 @@ describe('Underpants', () => { }); }); - describe('pluck', function () { - var inputData = [ + describe('_.pluck()', () => { + beforeEach(() => { + sinon.spy(_, "map"); + }) + afterEach(() => { + _.map.restore(); + }) + const inputData = [ { name: 'Ralph', age: 22 }, { name: 'Jimmy', age: 13 }, { name: 'Carla', age: 20 }, ]; - it('Should pluck properties out of a list of objects.', function () { - expect(_.pluck(inputData, 'name')).to.eql(['Ralph', 'Jimmy', 'Carla']); + it('should pluck properties from a list of objects', () => { + const result = _.pluck(inputData, 'name'); + const correct = ['Ralph', 'Jimmy', 'Carla']; + assert.deepEqual(result, correct); }); - - it('Should not have side effects.', function () { - expect(inputData).to.eql([ + it('should invoke the _.map() method', () => { + _.pluck(inputData, 'age'); + expect(_.map.calledOnce).to.be.true; + }); + it('should not have side effects', () => { + _.pluck(inputData, 'name'); + assert.deepEqual(inputData, [ { name: 'Ralph', age: 22 }, { name: 'Jimmy', age: 13 }, { name: 'Carla', age: 20 }, @@ -513,83 +525,193 @@ describe('Underpants', () => { }); }); - describe('every', function () { - var inputData = [2, 4, 6, 7, 8]; - var inputDataTruthy = [1, [], true, 'a']; - var inputDataFalsy = ['', 0, false, null]; - var inputObject = { a: 'one', b: 'two', c: 'three' }; - it('Should return true when all iterations are true', function () { - expect( - _.every(inputData, function (v) { - return v % 2 === 0 || v === 7; - }) - ).to.equal(true); + describe('_.every()', () => { + beforeEach(() => { + sinon.spy(console, 'log'); }); - it('Should return false when not all iterations are true', function () { - expect( - _.every(inputData, function (v) { - return v % 2 === 0; - }) - ).to.equal(false); + + afterEach(() => { + console.log.restore(); }); - it('Should handle objects', function () { - expect( - _.every(inputObject, function (v, k, o) { - return ( - ['aone3', 'btwo3', 'cthree3'].indexOf( - k + v + Object.keys(o).length - ) !== -1 - ); - }) - ).to.equal(true); + + const inputData = [2, 4, 6, 7, 8]; + const inputObject = { a: 'one', b: 'two', c: 'three' }; + + it('should return true when all iterations are true', () => { + const resultOne = _.every(inputData, (e) => e > 0); + const resultTwo = _.every(inputObject, (e) => typeof e === 'string'); + assert.equal(resultOne, true); + assert.equal(resultTwo, true); }); - it('Should return true for truthy results when no function is passed in.', function () { - expect(_.every(inputDataTruthy)).to.equal(true); + it('should return false when not all iterations are true', () => { + const resultOne = _.every(inputData, (e) => e % 2 === 0); + const resultTwo = _.every(inputObject, (e) => e.length === 3); + assert.equal(resultOne, false); + assert.equal(resultTwo, false); }); - it('Should return false for falsy results when no function is passed in.', function () { - expect(_.every(inputDataFalsy)).to.equal(false); + it('should return true for truthy results when no function is passed in', () => { + assert.equal(_.every(['a', 'b']), true); + assert.equal(_.every({ a: 1, b: 2 }), true); }); - it('Should not have side effects.', function () { - expect(inputData).to.eql([2, 4, 6, 7, 8]); + it('should return false for falsey results when no function is passed in', () => { + assert.equal(_.every(['a', 'b', null]), false); + assert.equal(_.every({ a: 1, b: 2, c: null }), false); + }); + it('callback should take in the current index as an argument if collection is an array', () => { + const input = ['a', 'b']; + const logs = [0, 1]; + _.every(input, (e, i, a) => { + console.log(i); + return typeof e === 'string'; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should take in the array as an argument if collection is an array', () => { + const input = ['a', 'b']; + _.every(input, (e, i, a) => { + console.log(a); + return typeof e === 'string'; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], ['a', 'b']); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should take in the current value as an argument if collection is an object', () => { + const input = { a: 1, b: 2 }; + const logs = ['a', 'b']; + _.every(input, (v, k, o) => { + console.log(k); + return typeof v === 'number'; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should take in the object as an argument if collection is an object', () => { + const input = { a: 1, b: 2 }; + _.every(input, (v, k, o) => { + console.log(o); + return typeof v === 'number'; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], { a: 1, b: 2 }); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputData, [2, 4, 6, 7, 8]); }); }); - describe('some', function () { - var inputData = [2, 4, 6, 7, 8]; - var inputDataTruthy = [1, [], true, 'a']; - var inputDataFalsy = ['', 0, false, null]; - var inputObject = { a: 'one', b: 'two', c: 'three' }; - it('Should return true when at least one iteration is true', function () { - expect( - _.some(inputData, function (v) { - return v === 7; - }) - ).to.equal(true); + describe('_.some()', () => { + beforeEach(() => { + sinon.spy(console, 'log'); }); - it('Should return false when no iterations are true', function () { - expect( - _.some(inputData, function (v) { - return v > 10; - }) - ).to.equal(false); + + afterEach(() => { + console.log.restore(); }); - it('Should handle objects', function () { - expect( - _.some(inputObject, function (v, k, o) { - return ( - ['aone3', 'btwo3'].indexOf(k + v + Object.keys(o).length) !== -1 - ); - }) - ).to.equal(true); + + const inputArray = [2, 4, 6, 7, 8]; + const inputObject = { a: 'one', b: 'two', c: 'three' }; + + it('should handle objects', () => { + const result = _.some(inputObject, (e) => e.length > 3); + assert.equal(typeof result, 'boolean'); + }); + it('should return true when at least one iteration is true', () => { + const resultOne = _.some(inputArray, (e) => e % 2 !== 0); + const resultTwo = _.some(inputObject, (e) => e.length > 3); + assert.equal(resultOne, true); + assert.equal(resultTwo, true); + }); + it('should return false when no iterations are true', () => { + const resultOne = _.some(inputArray, (e) => e > 10); + const resultTwo = _.some(inputObject, (e) => e.length > 5); + assert.equal(resultOne, false); + assert.equal(resultTwo, false); + }); + it('should return true for truthy results when no function is passed in', () => { + assert.equal(_.some(inputArray), true); + assert.equal(_.some(inputObject), true); + }); + it('should return false for falsey results when no function is passed in', () => { + assert.equal(_.some([undefined, null]), false); + assert.equal(_.some({ a: undefined, b: null }), false); + }); + it('callback should take in current index as one of its arguments if collection is an array', () => { + const logs = [0, 1, 2]; + _.some([1, 2, 3], (e, i, a) => { + console.log(i); + return e > 0; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } }); - it('Should return true for truthy results when no function is passed in.', function () { - expect(_.some(inputDataTruthy)).to.equal(true); + it('callback should take in array as one of its arguments if collection is an array', () => { + _.some([1, 2, 3], (e, i, a) => { + console.log(a); + return e > 0; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], [1, 2, 3]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } }); - it('Should return false for falsy results when no function is passed in.', function () { - expect(_.some(inputDataFalsy)).to.equal(false); + it('callback should take in current key as one of its arguments if collection is an object', () => { + const logs = ['a', 'b']; + _.some({ a: 1, b: 2 }, (v, k, o) => { + console.log(k); + return v > 0; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('callback should take in object as one of its arguments if collection is an object', () => { + _.some({ a: 1, b: 2 }, (v, k, o) => { + console.log(o); + return v > 0; + }); + if (console.log.args.length) { + console.log.args.forEach((e, i) => { + assert.deepEqual(e[0], { a: 1, b: 2 }); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } }); - it('Should not have side effects.', function () { - expect(inputData).to.eql([2, 4, 6, 7, 8]); + it('should not have side effects', () => { + assert.deepEqual(inputArray, [2, 4, 6, 7, 8]); }); }); From 774629cd5181aabad10e273ea7fba7d014868a21 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 12:37:04 -0500 Subject: [PATCH 21/31] updated test/underpants.spec.js tests for reduce, extend and removed unnecessary console.log statements --- test/underpants.spec.js | 147 +++++++++++++++++++++++++++------------- underpants.js | 17 +++-- 2 files changed, 111 insertions(+), 53 deletions(-) diff --git a/test/underpants.spec.js b/test/underpants.spec.js index 51d7e8b..277dab6 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -496,11 +496,11 @@ describe('Underpants', () => { describe('_.pluck()', () => { beforeEach(() => { - sinon.spy(_, "map"); - }) + sinon.spy(_, 'map'); + }); afterEach(() => { _.map.restore(); - }) + }); const inputData = [ { name: 'Ralph', age: 22 }, { name: 'Jimmy', age: 13 }, @@ -715,57 +715,108 @@ describe('Underpants', () => { }); }); - describe('reduce', function () { - var inputArray = [10, 20, 30, 40]; - it('Should work with an array and a seed', function () { - expect( - _.reduce( - inputArray, - function (memo, element, i) { - return memo + element + i; - }, - 10 - ) - ).to.equal(116); - }); - it('Should work without a seed', function () { - expect( - _.reduce(inputArray, function (memo, element, i) { - return memo * element * (i + 1); - }) - ).to.equal(5760000); - }); - it('Should work when seed is falsy', function () { - expect( - _.reduce( - inputArray, - function (memo, element, i) { - return memo * element * (i + 1); - }, - 0 - ) - ).to.equal(0); - }); - it('Should not have side effects', function () { - expect(inputArray).to.eql([10, 20, 30, 40]); + describe('_.reduce()', () => { + beforeEach(() => { + sinon.spy(console, 'log'); + }); + + afterEach(() => { + console.log.restore(); + }); + + const inputArray = [10, 20, 30, 40]; + + it('should work with an array and a seed', () => { + const result = _.reduce( + inputArray, + (acc, current, i) => { + acc += current; + return acc; + }, + 100 + ); + assert.equal(result, 200); + }); + it('should work without a seed', () => { + const result = _.reduce(inputArray, (acc, current, i) => { + acc += current; + return acc; + }); + assert.equal(result, 100); + }); + it('should work when seed is falsey', () => { + const result = _.reduce( + inputArray, + (acc, current, i) => { + acc += current; + return acc; + }, + 0 + ); + assert.equal(result, 100); + }); + it('callback should take in current index as one of its arguments', () => { + const logs = [0, 1, 1]; + const resultOne = _.reduce( + [1, 2], + (acc, current, i) => { + console.log(i); + acc += current; + return acc; + }, + 0 + ); + const resultTwo = _.reduce([3, 4], (acc, current, i) => { + console.log(i); + acc += current; + return acc; + }); + if (console.log.args.length > 0) { + console.log.args.forEach((e, i) => { + assert.equal(e[0], logs[i]); + }); + } else { + assert.equal(console.log.args.length > 0, true); + } + }); + it('should not have side effects', () => { + assert.deepEqual(inputArray, [10, 20, 30, 40]); }); }); - describe('extend', function () { - it('Should extend an object.', function () { - var inputData = { a: 'one', b: 'two' }; + describe('_.extend()', () => { + it('should extend an object', () => { + const inputData = { a: 'one', b: 'two' }; _.extend(inputData, { c: 'three', d: 'four' }); - expect(inputData).to.eql({ a: 'one', b: 'two', c: 'three', d: 'four' }); + assert.deepEqual(inputData, { + a: 'one', + b: 'two', + c: 'three', + d: 'four', + }); }); - it('Should overwrite existing properties', function () { - var inputData = { a: 'one', b: 'two' }; + it('should overwrite existing properties', () => { + const inputData = { a: 'one', b: 'two' }; _.extend(inputData, { a: 'three', d: 'four' }); - expect(inputData).to.eql({ a: 'three', b: 'two', d: 'four' }); - }); - it('Should handle any number of arguments.', function () { - var inputData = { a: 'one', b: 'two' }; - _.extend(inputData, { a: 'three', c: 'four' }, { d: 'five', c: 'six' }); - expect(inputData).to.eql({ a: 'three', b: 'two', c: 'six', d: 'five' }); + assert.deepEqual(inputData, { a: 'three', b: 'two', d: 'four' }); + }); + it('should handle any number of arguments', () => { + const inputData = { a: 'one', b: 'two' }; + _.extend( + inputData, + { c: 'three' }, + { d: 'four' }, + { e: 'five' }, + { f: 'six' } + ); + assert.deepEqual(inputData, { + a: 'one', + b: 'two', + c: 'three', + d: 'four', + e: 'five', + f: 'six', + }); }); }); }); diff --git a/underpants.js b/underpants.js index 42a930c..668b149 100644 --- a/underpants.js +++ b/underpants.js @@ -21,7 +21,6 @@ const _ = {}; */ - /** _.typeOf * Arguments: * 1) Any value @@ -42,6 +41,7 @@ const _ = {}; * _.typeOf([1,2,3]) -> "array" */ + /** _.first * Arguments: * 1) An array @@ -63,6 +63,7 @@ const _ = {}; * _.first("a", "b", "c", 5) -> ["a", "b", "c"] */ + /** _.last * Arguments: * 1) An array @@ -84,6 +85,7 @@ const _ = {}; * _.last(["a", "b", "c"], 2) -> ["b", "c"] */ + /** _.indexOf * Arguments: * 1) An array @@ -100,6 +102,7 @@ const _ = {}; * _.indexOf(["a","b","c"], "d") -> -1 */ + /** _.contains * Arguments: * 1) An array @@ -115,6 +118,7 @@ const _ = {}; * _.contains([1,"two", 3.14], "two") -> true */ + /** _.each * Arguments: * 1) A collection @@ -134,6 +138,7 @@ const _ = {}; * -> should log "one" "two" to the console */ + /** _.unique * Arguments: * 1) An array @@ -144,6 +149,7 @@ const _ = {}; * _.unique([1,2,2,4,5,6,5,2]) -> [1,2,4,5,6] */ + /** _.filter * Arguments: * 1) An array @@ -160,6 +166,7 @@ const _ = {}; * use _.each in your implementation */ + /** _.reject * Arguments: * 1) An array @@ -173,6 +180,7 @@ const _ = {}; * _.reject([1,2,3,4,5], function(e){return e%2 === 0}) -> [1,3,5] */ + /** _.partition * Arguments: * 1) An array @@ -192,6 +200,7 @@ const _ = {}; } */ + /** _.map * Arguments: * 1) A collection @@ -208,6 +217,7 @@ const _ = {}; * _.map([1,2,3,4], function(e){return e * 2}) -> [2,4,6,8] */ + /** _.pluck * Arguments: * 1) An array of objects @@ -219,6 +229,7 @@ const _ = {}; * _.pluck([{a: "one"}, {a: "two"}], "a") -> ["one", "two"] */ + /** _.every * Arguments: * 1) A collection @@ -241,7 +252,6 @@ const _ = {}; */ - /** _.some * Arguments: * 1) A collection @@ -264,7 +274,6 @@ const _ = {}; */ - /** _.reduce * Arguments: * 1) An array @@ -285,7 +294,6 @@ const _ = {}; */ - /** _.extend * Arguments: * 1) An Object @@ -302,7 +310,6 @@ const _ = {}; */ - //////////////////////////// // DON'T REMOVE THIS CODE // //////////////////////////// From 1b307aebcf568d6175f0d8732c1687ccf39e37a2 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 17:47:08 +0000 Subject: [PATCH 22/31] added post-test script back to package.json --- package-lock.json | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index ae7000c..ff7a577 100644 --- a/package-lock.json +++ b/package-lock.json @@ -722,20 +722,6 @@ "node": ">= 0.8.0" } }, - "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, "node_modules/resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", From e6bc2eb5f9ff89dfa517ec877125ef140cabef91 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 12 May 2025 12:53:18 -0500 Subject: [PATCH 23/31] added post-test script back to package.json --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 906f920..721ceba 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ }, "scripts": { "pretest": "npm install", - "test": "mocha ./test/underpants.spec.js || :" + "test": "mocha ./test/underpants.spec.js || :", + "posttest": "rm -rf ./test ./node_modules" }, "repository": { "type": "git", From a4af5dfd79baa9ca889f0cf49f872d9b923cc697 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Fri, 16 May 2025 11:38:45 -0500 Subject: [PATCH 24/31] added .vscode/settings.json --- .vscode/settings.json | 9 +++++++++ spec/underpants.spec.js | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..671a71b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit" + }, + "files.insertFinalNewline": true, +} \ No newline at end of file diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 5387232..8bc3b4b 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -8,7 +8,7 @@ describe('underpants library', () => { }); }); - describe('_.typeOff()', () => { + describe('_.typeOf()', () => { it('should handle simple datatypes', () => { assert.strictEqual(_.typeOf('a'), 'string'); assert.strictEqual(_.typeOf(10), 'number'); @@ -496,11 +496,11 @@ describe('underpants library', () => { describe('_.pluck()', () => { beforeEach(() => { - sinon.spy(_, "map"); - }) + sinon.spy(_, 'map'); + }); afterEach(() => { _.map.restore(); - }) + }); const inputData = [ { name: 'Ralph', age: 22 }, { name: 'Jimmy', age: 13 }, From b046c5a7ead6669d4709523f7846241673649a9c Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Fri, 16 May 2025 11:39:24 -0500 Subject: [PATCH 25/31] added prettier script to package.json --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 721ceba..c154771 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "scripts": { "pretest": "npm install", "test": "mocha ./test/underpants.spec.js || :", - "posttest": "rm -rf ./test ./node_modules" + "posttest": "rm -rf ./test ./node_modules", + "prettier": "prettier . --write" }, "repository": { "type": "git", From 89e80b5b5fc9052fc14f4fd4d5909d8e630aa1bd Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Fri, 16 May 2025 11:41:00 -0500 Subject: [PATCH 26/31] updated mocha, chai, sinon, installed prettier, uninstalled istanbul --- package-lock.json | 1450 +++++++++++++++++++++++++++------------------ package.json | 8 +- 2 files changed, 888 insertions(+), 570 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff7a577..8a31b18 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,39 +9,185 @@ "version": "1.0.0", "license": "CC", "devDependencies": { - "chai": "^3.5.0", - "istanbul": "^0.4.5", + "chai": "^4.5.0", "lodash": "^4.17.4", - "mocha": "^3.4.1", - "sinon": "^2.2.0" + "mocha": "^11.3.0", + "prettier": "^3.5.3", + "sinon": "^19.0.5" } }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "license": "ISC" + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, - "license": "BSD-3-Clause OR MIT", "optional": true, "engines": { - "node": ">=0.4.2" + "node": ">=14" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/commons/node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", "dev": true, - "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", + "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "lodash.get": "^4.4.2", + "type-detect": "^4.1.0" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "dev": true + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/assertion-error": { @@ -53,13 +199,6 @@ "node": "*" } }, - "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true, - "license": "MIT" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -67,295 +206,335 @@ "dev": true, "license": "MIT" }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha512-7Rfk377tpSM9TWBEeHs0FlDZGoAIei2V/4MdZJoFMBFAK6BqLpxAIUepGRHGdPFgGsLb02PXovC4qddyHvQqTg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "node_modules/chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha512-eRYY0vPS2a9zt5w5Z0aCeWbrXTEyvk7u/Xf71EzNObrjSCPgMm1Nku/D/u2tiqHBX5j40wWhj54YJLtgn8g55A==", + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, - "dependencies": { - "assertion-error": "^1.0.1", - "deep-eql": "^0.1.3", - "type-detect": "^1.0.0" - }, "engines": { - "node": ">= 0.4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, "dependencies": { - "graceful-readlink": ">= 1.0.0" + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" }, "engines": { - "node": ">= 0.6.x" + "node": ">=4" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha512-E22fsyWPt/lr4/UgQLt/pXqerGMDsanhbnmqIS3VAXuDi1v3IpiwXe2oncEIondHSBuPDWRoK/pMjlvi8FuOXQ==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "ms": "2.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha512-6sEotTRGBFiNcqVoeHwnfopbSpi5NbH1VWJmYCVkmxMmaVTT0bUTrNaGyBwhgP4MZL012W/mkzIn3Da+iDYweg==", + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, "dependencies": { - "type-detect": "0.1.1" + "get-func-name": "^2.0.2" }, "engines": { "node": "*" } }, - "node_modules/deep-eql/node_modules/type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha512-5rqszGVwYgBoDkIm2oUtvkfZMQ0vk29iDMU0W2qCa3rG0vPDNczCMT4hV/bLBgLg8k8ri6+u3Zbt+S/14eMzlA==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, + "dependencies": { + "readdirp": "^4.0.1" + }, "engines": { - "node": "*" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, - "license": "MIT" + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } }, - "node_modules/diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha512-597ykPFhtJYaXqPq6fF7Vl1fXTKgPdLOntyxpmdzUOKiYGqK7zcnbplj5088+8qJnWdzXhyeau5iVr8HVo9dgg==", + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.3.1" + "node": ">=7.0.0" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, "engines": { - "node": ">=0.8.0" + "node": ">= 8" } }, - "node_modules/escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1" + "isexe": "^2.0.0" }, "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "node-which": "bin/node-which" }, "engines": { - "node": ">=0.12.0" - }, - "optionalDependencies": { - "source-map": "~0.2.0" + "node": ">= 8" } }, - "node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "dependencies": { + "ms": "^2.1.3" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, - "license": "BSD-2-Clause", + "dependencies": { + "type-detect": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=0.3.1" + } }, - "node_modules/formatio": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", - "integrity": "sha512-YAF05v8+XCxAyHOdiiAmHdgCVPrWO8X744fYIPtBciIorh5LndWfi1gjeJ16sTbJhzek9kd+j3YByhohtz5Wmg==", - "deprecated": "This package is unmaintained. Use @sinonjs/formatio instead", + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, - "dependencies": { - "samsam": "1.x" + "engines": { + "node": ">=6" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, - "license": "ISC", "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", - "dev": true - }, - "node_modules/growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha512-RTBwDHhNuOx4F0hqzItc/siXCasGfC4DeWcBamclWd+6jWtBaeB/SGbMkGf0eiQoW7ib8JpvOgnUsmgMHI3Mfw==", - "dev": true + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, - "license": "MIT", "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">=0.4.7" + "node": ">=14" }, - "optionalDependencies": { - "uglify-js": "^3.1.4" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, - "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "engines": { + "node": "*" } }, "node_modules/has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "bin": { "he": "bin/he" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "engines": { + "node": ">=8" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, - "license": "ISC" + "engines": { + "node": ">=8" + } }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "dev": true + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/isexe": { "version": "2.0.0", @@ -364,80 +543,40 @@ "dev": true, "license": "ISC" }, - "node_modules/istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==", - "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "istanbul": "lib/cli.js" - } - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, - "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@isaacs/cliui": "^8.0.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/js-yaml/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "funding": { + "url": "https://github.com/sponsors/isaacs" }, - "engines": { - "node": ">=4" + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha512-I5YLeauH3rIaE99EE++UeH2M2gSYo8/2TqDac7oZEH6D/DSQ4Woa628Qrfj1X9/OY5Mk5VvIDQaKCDchXaKrmA==", - "deprecated": "Please use the native JSON object instead of JSON 3", + "node_modules/just-extend": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", "dev": true }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, - "license": "MIT", "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "p-locate": "^5.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -447,436 +586,615 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha512-t3N26QR2IdSN+gqSy9Ds9pBu/J1EAFEshKlUHpJG3rvyJOYgcELIxcIeKKfZk7sjOz11cFfzJRsyFry/JyabJQ==", + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "dependencies": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ==", - "dev": true - }, - "node_modules/lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha512-EDem6C9iQpn7fxnGdmhXmqYGjCkStmDXT4AeyB2Ph8WKbglg4aJZczNkQglj+zWXcOEEkViK8THuV2JvugW47g==", - "dev": true + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.1" + } }, - "node_modules/lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==", + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true }, - "node_modules/lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==", - "dev": true + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } }, - "node_modules/lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha512-IUfOYwDEbI8JbhW6psW+Ig01BOVK67dTSCUAbS58M0HBkPcAv/jHuxD+oJVP2tUCo3H9L6f/8GM6rxwY+oc7/w==", + "node_modules/mocha": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.3.0.tgz", + "integrity": "sha512-J0RLIM89xi8y6l77bgbX+03PeBRDQCOVQpnwOcCN7b8hCmbh6JvGI2ZDJ5WMoHz+IaPU+S4lvTd0j51GmBAdgQ==", "dev": true, "dependencies": { - "lodash._baseassign": "^3.0.0", - "lodash._basecreate": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", - "dev": true - }, - "node_modules/lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==", + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "balanced-match": "^1.0.0" } }, - "node_modules/lolex": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", - "integrity": "sha512-/bpxDL56TG5LS5zoXxKqA6Ro5tkOS5M8cm/7yQcwLIKIcM2HR5fjjNCaIhJNv96SEk4hNGSafYMZK42Xv5fihQ==", - "dev": true + "node_modules/mocha/node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/mocha/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "*" + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { - "minimist": "^1.2.6" + "argparse": "^2.0.1" }, "bin": { - "mkdirp": "bin/cmd.js" + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, - "dependencies": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 0.10.x", - "npm": ">= 1.4.x" + "node": ">=10" } }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-mRyN/EsN2SyNhKWykF3eEGhDpeNplMWaW18Bmh76tnOqk5TbELAVwFAYOCmKVssOYFrYvvLMguiA+NXO3ZTuVA==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/mocha/node_modules/minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/mocha/node_modules/mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==", - "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "node_modules/nise": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", + "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.1", + "@sinonjs/text-encoding": "^0.7.3", + "just-extend": "^6.2.0", + "path-to-regexp": "^8.1.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "dependencies": { - "minimist": "0.0.8" + "yocto-queue": "^0.1.0" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha512-F8dvPrZJtNzvDRX26eNXT4a7AecAvTGljmmnI39xEgSpbHKhQ7N0dO/NTxUExd0wuLHp4zbwYY7lvHq0aKpwrA==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "has-flag": "^1.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, - "node_modules/native-promise-only": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==", - "dev": true + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=8" + } }, - "node_modules/nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, - "license": "ISC", "dependencies": { - "abbrev": "1" + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/prettier": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "dev": true, "bin": { - "nopt": "bin/nopt.js" + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, - "license": "ISC", "dependencies": { - "wrappy": "1" + "safe-buffer": "^5.1.0" } }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, "engines": { - "node": ">= 0.8.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "dependencies": { - "isarray": "0.0.1" + "randombytes": "^2.1.0" } }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "MIT" + "engines": { + "node": ">=8" + } }, - "node_modules/samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "deprecated": "This package has been deprecated in favour of @sinonjs/samsam", - "dev": true + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/sinon": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.4.1.tgz", - "integrity": "sha512-vFTrO9Wt0ECffDYIPSP/E5bBugt0UjcBQOfQUMh66xzkyPEnhl/vM2LRZi2ajuTdkH07sA6DzrM6KvdvGIH8xw==", - "deprecated": "16.1.1", - "dev": true, - "dependencies": { - "diff": "^3.1.0", - "formatio": "1.2.0", - "lolex": "^1.6.0", - "native-promise-only": "^0.8.1", - "path-to-regexp": "^1.7.0", - "samsam": "^1.1.3", - "text-encoding": "0.6.4", - "type-detect": "^4.0.0" + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.5.tgz", + "integrity": "sha512-r15s9/s+ub/d4bxNXqIUmwp6imVSdTorIRaxoecYjqTVLZ8RuoXr/4EDGwIBo6Waxn7f2gnURX9zuhAfCwaF6Q==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.1", + "@sinonjs/fake-timers": "^13.0.5", + "@sinonjs/samsam": "^8.0.1", + "diff": "^7.0.0", + "nise": "^6.1.1", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">=0.1.103" + "node": ">=8" } }, - "node_modules/sinon/node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "optional": true, "dependencies": { - "amdefine": ">=0.0.4" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">=0.8.0" + "node": ">=8" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, - "license": "BSD-3-Clause" + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { - "has-flag": "^1.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.8.0" + "node": ">=8" } }, - "node_modules/text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha512-hJnc6Qg3dWoOMkqP53F0dzRIgtmsAge09kxUIqGrEUS4qr5rWLckGYaQAVr+opBrIMRErGgy6f5aPnyPpyGRfg==", - "deprecated": "no longer maintained", + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", "dev": true }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, - "license": "MIT", "dependencies": { - "prelude-ls": "~1.1.2" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha512-f9Uv6ezcpvCQjJU0Zqbg+65qdcszv3qUQsZfjdRbWiZ7AMenrX1u0lNk9EoWWX6e1F+NULyg27mtdeZ5WhpljA==", + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, "engines": { - "node": ">=0.8.0" + "node": ">=10" } }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, - "license": "ISC", "dependencies": { - "isexe": "^2.0.0" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=12" } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, - "license": "MIT" + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "license": "ISC" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index c154771..f32a8f3 100644 --- a/package.json +++ b/package.json @@ -24,10 +24,10 @@ }, "homepage": "https://github.com/OperationSpark/underpants", "devDependencies": { - "chai": "^3.5.0", - "istanbul": "^0.4.5", + "chai": "^4.5.0", "lodash": "^4.17.4", - "mocha": "^3.4.1", - "sinon": "^2.2.0" + "mocha": "^11.3.0", + "prettier": "^3.5.3", + "sinon": "^19.0.5" } } From 4120ebfc454eeda0f2ec9e8d07949a48f2ff442a Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 26 May 2025 12:23:48 -0500 Subject: [PATCH 27/31] removed unnecessary string _.first unit test --- spec/underpants.spec.js | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 8bc3b4b..6a77dc3 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -51,7 +51,6 @@ describe('underpants library', () => { assert.deepEqual( _.first(['a', 'b', 'c'], -1), [], - 'Should return empty list if numerical argument is not a positive number.' ); }); it('should return empty array if the array param is not an an array', () => { From 3f385eba82aac95e01d1b17db814beed778e9e53 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 26 May 2025 12:35:45 -0500 Subject: [PATCH 28/31] corrected take in current value to current key in _.every tests in spec directory --- spec/underpants.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 6a77dc3..626a8eb 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -585,7 +585,7 @@ describe('underpants library', () => { assert.equal(console.log.args.length > 0, true); } }); - it('should take in the current value as an argument if collection is an object', () => { + it('should take in the current key as an argument if collection is an object', () => { const input = { a: 1, b: 2 }; const logs = ['a', 'b']; _.every(input, (v, k, o) => { From c05932a6ad2c7625cc3c79ed183fe695938136c7 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Mon, 26 May 2025 12:55:32 -0500 Subject: [PATCH 29/31] updated _.unique tests in spec directory to check for invoking _.indexOf() --- spec/underpants.spec.js | 10 ++++++++-- underpants.js | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 626a8eb..6a3bf30 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -201,6 +201,12 @@ describe('underpants library', () => { }); describe('_.unique()', () => { + beforeEach(() => { + sinon.spy(_, "indexOf"); + }); + afterEach(() => { + _.indexOf.restore(); + }); const inputData = [ 'a', 1, @@ -219,8 +225,8 @@ describe('underpants library', () => { assert.deepEqual(_.unique(inputData), ['a', 1, 'c', false, 'b', 5, null]); }); it('should invoke _.indexOf() method', () => { - const func = _.unique.toString(); - assert.equal(func.includes('_.indexOf('), true); + _.unique(["a", "a", 1, 1, "b", "b", "b"]); + _.indexOf.called.should.be.true; }); it('should not have side effects', () => { assert.deepEqual(inputData, [ diff --git a/underpants.js b/underpants.js index 668b149..786cbb7 100644 --- a/underpants.js +++ b/underpants.js @@ -103,6 +103,7 @@ const _ = {}; */ + /** _.contains * Arguments: * 1) An array @@ -150,6 +151,7 @@ const _ = {}; */ + /** _.filter * Arguments: * 1) An array From 37f285ca0a876822beefb72de60f49fb5d31a2e5 Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Wed, 28 May 2025 13:11:24 -0500 Subject: [PATCH 30/31] added .prettierrc --- .prettierrc | 9 +++++++++ .vscode/settings.json | 4 ++-- README.md | 35 +++++++++++++++++++++-------------- index.html | 23 +++++++++++------------ spec/underpants.spec.js | 29 +++++++++++++---------------- test/underpants.spec.js | 20 ++++++++++---------- underpants.js | 19 ------------------- 7 files changed, 66 insertions(+), 73 deletions(-) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..980ebdf --- /dev/null +++ b/.prettierrc @@ -0,0 +1,9 @@ +{ + "arrowParens": "always", + "bracketSpacing": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "all", + "jsxSingleQuote": true, + "useTabs": false +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 671a71b..f1e3e32 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,5 @@ "editor.codeActionsOnSave": { "source.organizeImports": "explicit" }, - "files.insertFinalNewline": true, -} \ No newline at end of file + "files.insertFinalNewline": true +} diff --git a/README.md b/README.md index 201f083..f97bcb5 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,20 @@ # Underpants + This activity is essentially a re-write of [underscore.js](http://underscorejs.org/). ## Why? + In the past exercises we've been writing a lot of loops over objects and arrays ourselves. Instead of doing that, we are going to write several fuctions to handle the looping for us. These functions are used every day by professional developers and we're well on our way to becoming professional developers!! This means that if we're confused about how a function should work, we can check the underscore.js documentation linked above for help. ## Instructions - - Open up index.html in a web browser. - - Notice that all the tests are failing. :) - - Open up underpants.js in a text editor and follow the instructions. - - Make all the test pass!! - - Open underpants.html in a text editor to view the code that runs the tests. + +- Open up index.html in a web browser. +- Notice that all the tests are failing. :) +- Open up underpants.js in a text editor and follow the instructions. +- Make all the test pass!! +- Open underpants.html in a text editor to view the code that runs the tests. ## Links and Resources @@ -20,31 +23,35 @@ Some quick notes that may come in handy: - [underscore documentation](http://underscorejs.org/). - Many of the functions operate on "collections." They can take both arrays or objects as their arguments and you need to be able to handle both cases. - - You can use `Array.isArray(obj)` to find out whether an object is an array. - - You can use `obj.length` to test if something is either a string or an - array. + - You can use `Array.isArray(obj)` to find out whether an object is an array. + - You can use `obj.length` to test if something is either a string or an + array. - Javascript has a built-in `Math` object that provides some very useful functions. [Math Documentation](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Math). - Within a function, you can use the `arguments` variable to access all the parameters that were passed in even if they aren't named in the function definition. This is useful if you don't know how many arguments are going to be passed in in advance. - - You can count the arguments by using `arguments.length` and access each - argument using `arguments[i]`. - - The `arguments` object is very similar to an array, but note that it does - not support most array functions (such as `slice` or `push`). You can read - more about this [here](http://www.sitepoint.com/arguments-a-javascript-oddity/). + - You can count the arguments by using `arguments.length` and access each + argument using `arguments[i]`. + - The `arguments` object is very similar to an array, but note that it does + not support most array functions (such as `slice` or `push`). You can read + more about this [here](http://www.sitepoint.com/arguments-a-javascript-oddity/). ### Extra Credit: + See Instructor for instructions. + - defaults -- *once* +- _once_ - memoize - delay - shuffle ### Double Extra Credit: + See Instructor for instructions. + - once - invoke - sortBy diff --git a/index.html b/index.html index 7a764fe..2dd85c2 100644 --- a/index.html +++ b/index.html @@ -22,18 +22,17 @@
- + - - - - - + + + + diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 6a3bf30..6f59d54 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -16,14 +16,14 @@ describe('underpants library', () => { assert.strictEqual(_.typeOf(undefined), 'undefined'); assert.strictEqual( _.typeOf(function () {}), - 'function' + 'function', ); }); it('should return `object` for objects intended as as collections', () => { assert.strictEqual( _.typeOf({ a: 'one' }), 'object', - 'Should handle objects.' + 'Should handle objects.', ); }); it('should return `array` for array inputs', () => { @@ -35,7 +35,7 @@ describe('underpants library', () => { it('should return `function` for function inputs', () => { assert.strictEqual( _.typeOf(function () {}), - 'function' + 'function', ); }); }); @@ -48,10 +48,7 @@ describe('underpants library', () => { assert.equal(_.first(['a', 'b', 'c']), 'a'); }); it('should return empty array if numerical argument is not a positive number', () => { - assert.deepEqual( - _.first(['a', 'b', 'c'], -1), - [], - ); + assert.deepEqual(_.first(['a', 'b', 'c'], -1), []); }); it('should return empty array if the array param is not an an array', () => { assert.deepEqual(_.first({ a: 'b' }, 2), []); @@ -202,7 +199,7 @@ describe('underpants library', () => { describe('_.unique()', () => { beforeEach(() => { - sinon.spy(_, "indexOf"); + sinon.spy(_, 'indexOf'); }); afterEach(() => { _.indexOf.restore(); @@ -225,7 +222,7 @@ describe('underpants library', () => { assert.deepEqual(_.unique(inputData), ['a', 1, 'c', false, 'b', 5, null]); }); it('should invoke _.indexOf() method', () => { - _.unique(["a", "a", 1, 1, "b", "b", "b"]); + _.unique(['a', 'a', 1, 1, 'b', 'b', 'b']); _.indexOf.called.should.be.true; }); it('should not have side effects', () => { @@ -264,7 +261,7 @@ describe('underpants library', () => { _.filter(inputData, (e, i, a) => { return typeof e === 'string'; }), - ['a', 'b', 'c'] + ['a', 'b', 'c'], ); }); it('callback function should take in the current index as one of its arguments', () => { @@ -321,7 +318,7 @@ describe('underpants library', () => { _.reject(inputData, (e) => { return typeof e === 'string'; }), - [1, 2, 4] + [1, 2, 4], ); }); it('callback function should take in the current index as an argument', () => { @@ -377,7 +374,7 @@ describe('underpants library', () => { [ ['a', 'b', 'c'], [1, 2, 4], - ] + ], ); }); it('callback function should take in the current index as an argument', () => { @@ -738,7 +735,7 @@ describe('underpants library', () => { acc += current; return acc; }, - 100 + 100, ); assert.equal(result, 200); }); @@ -756,7 +753,7 @@ describe('underpants library', () => { acc += current; return acc; }, - 0 + 0, ); assert.equal(result, 100); }); @@ -769,7 +766,7 @@ describe('underpants library', () => { acc += current; return acc; }, - 0 + 0, ); const resultTwo = _.reduce([3, 4], (acc, current, i) => { console.log(i); @@ -813,7 +810,7 @@ describe('underpants library', () => { { c: 'three' }, { d: 'four' }, { e: 'five' }, - { f: 'six' } + { f: 'six' }, ); assert.deepEqual(inputData, { a: 'one', diff --git a/test/underpants.spec.js b/test/underpants.spec.js index 277dab6..e135a8a 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -22,14 +22,14 @@ describe('Underpants', () => { assert.strictEqual(_.typeOf(undefined), 'undefined'); assert.strictEqual( _.typeOf(function () {}), - 'function' + 'function', ); }); it('should return `object` for objects intended as as collections', () => { assert.strictEqual( _.typeOf({ a: 'one' }), 'object', - 'Should handle objects.' + 'Should handle objects.', ); }); it('should return `array` for array inputs', () => { @@ -41,7 +41,7 @@ describe('Underpants', () => { it('should return `function` for function inputs', () => { assert.strictEqual( _.typeOf(function () {}), - 'function' + 'function', ); }); }); @@ -259,7 +259,7 @@ describe('Underpants', () => { _.filter(inputData, (e, i, a) => { return typeof e === 'string'; }), - ['a', 'b', 'c'] + ['a', 'b', 'c'], ); }); it('callback function should take in the current index as one of its arguments', () => { @@ -316,7 +316,7 @@ describe('Underpants', () => { _.reject(inputData, (e) => { return typeof e === 'string'; }), - [1, 2, 4] + [1, 2, 4], ); }); it('callback function should take in the current index as an argument', () => { @@ -372,7 +372,7 @@ describe('Underpants', () => { [ ['a', 'b', 'c'], [1, 2, 4], - ] + ], ); }); it('callback function should take in the current index as an argument', () => { @@ -733,7 +733,7 @@ describe('Underpants', () => { acc += current; return acc; }, - 100 + 100, ); assert.equal(result, 200); }); @@ -751,7 +751,7 @@ describe('Underpants', () => { acc += current; return acc; }, - 0 + 0, ); assert.equal(result, 100); }); @@ -764,7 +764,7 @@ describe('Underpants', () => { acc += current; return acc; }, - 0 + 0, ); const resultTwo = _.reduce([3, 4], (acc, current, i) => { console.log(i); @@ -807,7 +807,7 @@ describe('Underpants', () => { { c: 'three' }, { d: 'four' }, { e: 'five' }, - { f: 'six' } + { f: 'six' }, ); assert.deepEqual(inputData, { a: 'one', diff --git a/underpants.js b/underpants.js index 786cbb7..5bbe7ed 100644 --- a/underpants.js +++ b/underpants.js @@ -20,7 +20,6 @@ const _ = {}; * _.identity({a: "b"}) === {a: "b"} */ - /** _.typeOf * Arguments: * 1) Any value @@ -41,7 +40,6 @@ const _ = {}; * _.typeOf([1,2,3]) -> "array" */ - /** _.first * Arguments: * 1) An array @@ -63,7 +61,6 @@ const _ = {}; * _.first("a", "b", "c", 5) -> ["a", "b", "c"] */ - /** _.last * Arguments: * 1) An array @@ -85,7 +82,6 @@ const _ = {}; * _.last(["a", "b", "c"], 2) -> ["b", "c"] */ - /** _.indexOf * Arguments: * 1) An array @@ -102,8 +98,6 @@ const _ = {}; * _.indexOf(["a","b","c"], "d") -> -1 */ - - /** _.contains * Arguments: * 1) An array @@ -119,7 +113,6 @@ const _ = {}; * _.contains([1,"two", 3.14], "two") -> true */ - /** _.each * Arguments: * 1) A collection @@ -139,7 +132,6 @@ const _ = {}; * -> should log "one" "two" to the console */ - /** _.unique * Arguments: * 1) An array @@ -150,8 +142,6 @@ const _ = {}; * _.unique([1,2,2,4,5,6,5,2]) -> [1,2,4,5,6] */ - - /** _.filter * Arguments: * 1) An array @@ -168,7 +158,6 @@ const _ = {}; * use _.each in your implementation */ - /** _.reject * Arguments: * 1) An array @@ -182,7 +171,6 @@ const _ = {}; * _.reject([1,2,3,4,5], function(e){return e%2 === 0}) -> [1,3,5] */ - /** _.partition * Arguments: * 1) An array @@ -202,7 +190,6 @@ const _ = {}; } */ - /** _.map * Arguments: * 1) A collection @@ -219,7 +206,6 @@ const _ = {}; * _.map([1,2,3,4], function(e){return e * 2}) -> [2,4,6,8] */ - /** _.pluck * Arguments: * 1) An array of objects @@ -231,7 +217,6 @@ const _ = {}; * _.pluck([{a: "one"}, {a: "two"}], "a") -> ["one", "two"] */ - /** _.every * Arguments: * 1) A collection @@ -253,7 +238,6 @@ const _ = {}; * _.every([1,2,3], function(e){return e % 2 === 0}) -> false */ - /** _.some * Arguments: * 1) A collection @@ -275,7 +259,6 @@ const _ = {}; * _.some([1,2,3], function(e){return e % 2 === 0}) -> true */ - /** _.reduce * Arguments: * 1) An array @@ -295,7 +278,6 @@ const _ = {}; * _.reduce([1,2,3], function(previousSum, currentValue, currentIndex){ return previousSum + currentValue }, 0) -> 6 */ - /** _.extend * Arguments: * 1) An Object @@ -311,7 +293,6 @@ const _ = {}; * _.extend(data, {a:"two"}); -> data now equals {a:"two"} */ - //////////////////////////// // DON'T REMOVE THIS CODE // //////////////////////////// From 70f02b2b3b2d3df55d53bd616cf9dd80f262aeac Mon Sep 17 00:00:00 2001 From: Alex Aaron Date: Wed, 28 May 2025 14:48:06 -0500 Subject: [PATCH 31/31] updated tests --- spec/underpants.spec.js | 46 +++++++++++++++-------------------------- test/underpants.spec.js | 46 +++++++++++++++-------------------------- underpants.js | 12 +++++++++++ 3 files changed, 46 insertions(+), 58 deletions(-) diff --git a/spec/underpants.spec.js b/spec/underpants.spec.js index 6f59d54..618d43f 100644 --- a/spec/underpants.spec.js +++ b/spec/underpants.spec.js @@ -9,35 +9,23 @@ describe('underpants library', () => { }); describe('_.typeOf()', () => { - it('should handle simple datatypes', () => { - assert.strictEqual(_.typeOf('a'), 'string'); - assert.strictEqual(_.typeOf(10), 'number'); - assert.strictEqual(_.typeOf(false), 'boolean'); - assert.strictEqual(_.typeOf(undefined), 'undefined'); - assert.strictEqual( - _.typeOf(function () {}), - 'function', - ); - }); - it('should return `object` for objects intended as as collections', () => { - assert.strictEqual( - _.typeOf({ a: 'one' }), - 'object', - 'Should handle objects.', - ); - }); - it('should return `array` for array inputs', () => { - assert.strictEqual(_.typeOf([1, 3]), 'array'); - }); - it('should return `null` for null inputs', () => { - assert.strictEqual(_.typeOf(null), 'null'); - }); - it('should return `function` for function inputs', () => { - assert.strictEqual( - _.typeOf(function () {}), - 'function', - ); - }); + const tests = [ + {input: 'hello world', expected: 'string'}, + {input: 100, expected: 'number'}, + {input: false, expected: 'boolean'}, + {input: undefined, expected: 'undefined'}, + {input: function(x,y){return x + y}, expected: 'function'}, + {input: null, expected: 'null'}, + {input: [1, 2, 3], expected: 'array'}, + {input: { a: 1, b: 2 }, expected: 'object'} + ]; + + tests.forEach((e, i) => { + const { input, expected } = e; + it(`should return "${expected}" for ${expected} input`, () => { + assert.equal(_.typeOf(input), expected); + }); + }) }); describe('_.first()', () => { diff --git a/test/underpants.spec.js b/test/underpants.spec.js index e135a8a..e22ade7 100644 --- a/test/underpants.spec.js +++ b/test/underpants.spec.js @@ -15,35 +15,23 @@ describe('Underpants', () => { }); describe('_.typeOf()', () => { - it('should handle simple datatypes', () => { - assert.strictEqual(_.typeOf('a'), 'string'); - assert.strictEqual(_.typeOf(10), 'number'); - assert.strictEqual(_.typeOf(false), 'boolean'); - assert.strictEqual(_.typeOf(undefined), 'undefined'); - assert.strictEqual( - _.typeOf(function () {}), - 'function', - ); - }); - it('should return `object` for objects intended as as collections', () => { - assert.strictEqual( - _.typeOf({ a: 'one' }), - 'object', - 'Should handle objects.', - ); - }); - it('should return `array` for array inputs', () => { - assert.strictEqual(_.typeOf([1, 3]), 'array'); - }); - it('should return `null` for null inputs', () => { - assert.strictEqual(_.typeOf(null), 'null'); - }); - it('should return `function` for function inputs', () => { - assert.strictEqual( - _.typeOf(function () {}), - 'function', - ); - }); + const tests = [ + {input: 'hello world', expected: 'string'}, + {input: 100, expected: 'number'}, + {input: false, expected: 'boolean'}, + {input: undefined, expected: 'undefined'}, + {input: function(x,y){return x + y}, expected: 'function'}, + {input: null, expected: 'null'}, + {input: [1, 2, 3], expected: 'array'}, + {input: { a: 1, b: 2 }, expected: 'object'} + ]; + + tests.forEach((e, i) => { + const { input, expected } = e; + it(`should return "${expected}" for ${expected} input`, () => { + assert.equal(_.typeOf(input), expected); + }); + }) }); describe('_.first()', () => { diff --git a/underpants.js b/underpants.js index 5bbe7ed..a632bbb 100644 --- a/underpants.js +++ b/underpants.js @@ -40,6 +40,18 @@ const _ = {}; * _.typeOf([1,2,3]) -> "array" */ +_.typeOf = function(value){ + if (typeof value !== 'object'){ + return typeof value; + } else if (Array.isArray(value)){ + return 'array'; + } else if (value === null){ + return 'null' + } else { + return 'object'; + } +} + /** _.first * Arguments: * 1) An array