diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc5760ff8..a44c16ba7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,14 +38,17 @@ Here's what you can do to help: - You can start creating a new snippet, by using the [snippet template](snippet-template.md) to format your snippets. ### Writing tests -- Before writing any tests run `npm run tdd` script. It will update test directory to include new snippets as well as update old ones if needed. +- Before writing any tests run `npm run tester` script. It will update test directory to include new snippets as well as update old ones if needed. - **DO NOT MODIFY THE snippetName.js files** under test directory. - We are using [tape](https://github.com/substack/tape) for testing. - Write tests under `snippetName.test.js` file. If you have trouble doing so, check out tests of other snippets. - Be sure to run `npm run test`. It is going to run all tests for all snippets. - Make a new pull request **only if all the tests are passing**. - +#### Browser specific tests +- If your snippet belongs to `browser` category, then you will need to modify the tests to make them work. +- By default, `Node.js` isn't browser environment. That said we have to use an external package to help us simulate the browser for our tests. +- We use [jsdom](https://www.npmjs.com/package/jsdom) for our browser specific tests. You can find their [documentation](https://github.com/jsdom/jsdom) on GitHub as well. ### Additional guidelines and conventions regarding snippets diff --git a/README.md b/README.md index 92f8a301f..923e59745 100644 --- a/README.md +++ b/README.md @@ -82,8 +82,11 @@ average(1, 2, 3); * [`collectInto`](#collectinto) * [`flip`](#flip) * [`over`](#over) +* [`overArgs`](#overargs) +* [`pipeAsyncFunctions`](#pipeasyncfunctions) * [`pipeFunctions`](#pipefunctions) * [`promisify`](#promisify) +* [`rearg`](#rearg) * [`spreadOver`](#spreadover) * [`unary`](#unary) @@ -219,12 +222,14 @@ average(1, 2, 3);
View contents +* [`attempt`](#attempt) * [`bind`](#bind) * [`bindKey`](#bindkey) * [`chainAsync`](#chainasync) * [`compose`](#compose) * [`composeRight`](#composeright) * [`curry`](#curry) +* [`debounce`](#debounce) * [`defer`](#defer) * [`delay`](#delay) * [`functionName`](#functionname) @@ -235,6 +240,7 @@ average(1, 2, 3); * [`partialRight`](#partialright) * [`runPromisesInSeries`](#runpromisesinseries) * [`sleep`](#sleep) +* [`throttle`](#throttle) * [`times`](#times) * [`unfold`](#unfold) @@ -495,7 +501,7 @@ const Pall = collectInto(Promise.all.bind(Promise)); let p1 = Promise.resolve(1); let p2 = Promise.resolve(2); let p3 = new Promise(resolve => setTimeout(resolve, 2000, 3)); -Pall(p1, p2, p3).then(console.log); +Pall(p1, p2, p3).then(console.log); // [1, 2, 3] (after about 2 seconds) ```
@@ -554,6 +560,66 @@ minMax(1, 2, 3, 4, 5); // [1,5]
[⬆ Back to top](#table-of-contents) +### overArgs + +Creates a function that invokes the provided function with its arguments transformed. + +Use `Array.map()` to apply `transforms` to `args` in combination with the spread operator (`...`) to pass the transformed arguments to `fn`. + +```js +const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val))); +``` + +
+Examples + +```js +var func = overArgs( + function(x, y) { + return [x, y]; + }, + [square, doubled] +); +func(9, 3); // [81, 6] +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + +### pipeAsyncFunctions + +Performs left-to-right function composition for asynchronous functions. + +Use `Array.reduce()` with the spread operator (`...`) to perform left-to-right function composition using `Promise.then()`. +The functions can return a combination of: simple values, `Promise`'s, or they can be defined as `async` ones returning through `await`. +All functions must be unary. + +```js +const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg)); +``` + +
+Examples + +```js +const sum = pipeAsyncFunctions( + x => x + 1, + x => new Promise(resolve => setTimeout(() => resolve(x + 2), 1000)), + x => x + 3, + async x => (await x) + 4 +); +(async () => { + console.log(await sum(5)); // 15 (after one second) +})(); +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### pipeFunctions Performs left-to-right function composition. @@ -609,6 +675,40 @@ delay(2000).then(() => console.log('Hi!')); // // Promise resolves after 2s
[⬆ Back to top](#table-of-contents) +### rearg + +Creates a function that invokes the provided function with its arguments arranged according to the specified indexes. + +Use `Array.reduce()` and `Array.indexOf()` to reorder arguments based on `indexes` in combination with the spread operator (`...`) to pass the transformed arguments to `fn`. + +```js +const rearg = (fn, indexes) => (...args) => + fn( + ...args.reduce( + (acc, val, i) => ((acc[indexes.indexOf(i)] = val), acc), + Array.from({ length: indexes.length }) + ) + ); +``` + +
+Examples + +```js +var rearged = rearg( + function(a, b, c) { + return [a, b, c]; + }, + [2, 0, 1] +); +rearged('b', 'c', 'a'); // ['a', 'b', 'c'] +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### spreadOver Takes a variadic function and returns a closure that accepts an array of arguments to map to the inputs of the function. @@ -3432,6 +3532,37 @@ tomorrow(); // 2017-12-27 (if current date is 2017-12-26) --- ## 🎛️ Function +### attempt + +Attempts to invoke a function with the provided arguments, returning either the result or the caught error object. + +Use a `try... catch` block to return either the result of the function or an appropriate error. + +```js +const attempt = (fn, ...args) => { + try { + return fn(args); + } catch (e) { + return e instanceof Error ? e : new Error(e); + } +}; +``` + +
+Examples + +```js +var elements = attempt(function(selector) { + return document.querySelectorAll(selector); +}, '>_>'); +if (elements instanceof Error) elements = []; // elements = [] +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### bind Creates a function that invokes `fn` with a given context, optionally adding any additional supplied parameters to the beginning of the arguments. @@ -3609,6 +3740,44 @@ curry(Math.min, 3)(10)(50)(2); // 2
[⬆ Back to top](#table-of-contents) +### debounce + +Creates a debounced function that delays invoking the provided function until after `wait` milliseconds have elapsed since the last time the debounced function was invoked. + +Use `setTimeout()` and `clearTimeout()` to debounce the given method, `fn`. +Use `Function.apply()` to apply the `this` context to the function and provide the necessary `arguments`. +Omit the second argument, `wait`, to set the timeout at a default of 0 ms. + +```js +const debounce = (fn, wait = 0) => { + let inDebounce; + return function() { + const context = this, + args = arguments; + clearTimeout(inDebounce); + inDebounce = setTimeout(() => fn.apply(context, args), wait); + }; +}; +``` + +
+Examples + +```js +window.addEventListener( + 'resize', + debounce(function(evt) { + console.log(window.innerWidth); + console.log(window.innerHeight); + }, 250) +); // Will log the window dimensions at most every 250ms +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### defer Defers invoking a function until the current call stack has cleared. @@ -3879,6 +4048,56 @@ async function sleepyWork() {
[⬆ Back to top](#table-of-contents) +### throttle + +Creates a throttled function that only invokes the provided function at most once per every `wait` milliseconds + +Use `setTimeout()` and `clearTimeout()` to throttle the given method, `fn`. +Use `Function.apply()` to apply the `this` context to the function and provide the necessary `arguments`. +Use `Date.now()` to keep track of the last time the throttled function was invoked. +Omit the second argument, `wait`, to set the timeout at a default of 0 ms. + +```js +const throttle = (fn, wait) => { + let inThrottle, lastFn, lastTime; + return function() { + const context = this, + args = arguments; + if (!inThrottle) { + fn.apply(context, args); + lastTime = Date.now(); + inThrottle = true; + } else { + clearTimeout(lastFn); + lastFn = setTimeout(function() { + if (Date.now() - lastTime >= wait) { + fn.apply(context, args); + lastTime = Date.now(); + } + }, wait - (Date.now() - lastTime)); + } + }; +}; +``` + +
+Examples + +```js +window.addEventListener( + 'resize', + throttle(function(evt) { + console.log(window.innerWidth); + console.log(window.innerHeight); + }, 250) +); // Will log the window dimensions at most every 250ms +``` + +
+ +
[⬆ Back to top](#table-of-contents) + + ### times Iterates over a callback `n` times @@ -5095,17 +5314,17 @@ UUIDGeneratorNode(); // '79c7c136-60ee-40a2-beb2-856f1feabefc' ### bindAll -Explain briefly what the snippet does. - Use `Array.forEach()` to return a `function` that uses `Function.apply()` to apply the given context (`obj`) to `fn` for each function specified. ```js const bindAll = (obj, ...fns) => fns.forEach( - fn => + fn => ( + (f = obj[fn]), (obj[fn] = function() { - return fn.apply(obj); + return f.apply(obj); }) + ) ); ``` diff --git a/docs/index.html b/docs/index.html index 6df6bfcae..366cc80a2 100644 --- a/docs/index.html +++ b/docs/index.html @@ -50,7 +50,7 @@ scrollToTop(); } }, false); - }

logo 30 seconds of code Curated collection of useful JavaScript snippets that you can understand in 30 seconds or less.

 

Adapter

ary

Creates a function that accepts up to n arguments, ignoring any additional arguments.

Call the provided function, fn, with up to n arguments, using Array.slice(0,n) and the spread operator (...).

const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
+      }

logo 30 seconds of code Curated collection of useful JavaScript snippets that you can understand in 30 seconds or less.

 

Adapter

ary

Creates a function that accepts up to n arguments, ignoring any additional arguments.

Call the provided function, fn, with up to n arguments, using Array.slice(0,n) and the spread operator (...).

const ary = (fn, n) => (...args) => fn(...args.slice(0, n));
 
const firstTwoMax = ary(Math.max, 2);
 [[2, 6, 'a'], [8, 4, 6], [10]].map(x => firstTwoMax(...x)); // [6, 8, 10]
 

call

Given a key and a set of arguments, call them when given a context. Primarily useful in composition.

Use a closure to call a stored key with stored arguments.

const call = (key, ...args) => context => context[key](...args);
@@ -66,7 +66,7 @@ Promise.reso
 let p1 = Promise.resolve(1);
 let p2 = Promise.resolve(2);
 let p3 = new Promise(resolve => setTimeout(resolve, 2000, 3));
-Pall(p1, p2, p3).then(console.log);
+Pall(p1, p2, p3).then(console.log); // [1, 2, 3] (after about 2 seconds)
 

flip

Flip takes a function as an argument, then makes the first argument the last.

Return a closure that takes variadic inputs, and splices the last argument to make it the first argument before applying the rest.

const flip = fn => (first, ...rest) => fn(...rest, first);
 
let a = { name: 'John Smith' };
 let b = {};
@@ -78,6 +78,24 @@ Object.assig
 

over

Creates a function that invokes each provided function with the arguments it receives and returns the results.

Use Array.map() and Function.apply() to apply each function to the given arguments.

const over = (...fns) => (...args) => fns.map(fn => fn.apply(null, args));
 
const minMax = over(Math.min, Math.max);
 minMax(1, 2, 3, 4, 5); // [1,5]
+

overArgs

Creates a function that invokes the provided function with its arguments transformed.

Use Array.map() to apply transforms to args in combination with the spread operator (...) to pass the transformed arguments to fn.

const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
+
var func = overArgs(
+  function(x, y) {
+    return [x, y];
+  },
+  [square, doubled]
+);
+func(9, 3); // [81, 6]
+

pipeAsyncFunctions

Performs left-to-right function composition for asynchronous functions.

Use Array.reduce() with the spread operator (...) to perform left-to-right function composition using Promise.then(). The functions can return a combination of: simple values, Promise's, or they can be defined as async ones returning through await. All functions must be unary.

const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
+
const sum = pipeAsyncFunctions(
+  x => x + 1,
+  x => new Promise(resolve => setTimeout(() => resolve(x + 2), 1000)),
+  x => x + 3,
+  async x => (await x) + 4
+);
+(async () => {
+  console.log(await sum(5)); // 15 (after one second)
+})();
 

pipeFunctions

Performs left-to-right function composition.

Use Array.reduce() with the spread operator (...) to perform left-to-right function composition. The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.

const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
 
const add5 = x => x + 5;
 const multiply = (x, y) => x * y;
@@ -89,6 +107,20 @@ Object.assig
   );
 
const delay = promisify((d, cb) => setTimeout(cb, d));
 delay(2000).then(() => console.log('Hi!')); // // Promise resolves after 2s
+

rearg

Creates a function that invokes the provided function with its arguments arranged according to the specified indexes.

Use Array.reduce() and Array.indexOf() to reorder arguments based on indexes in combination with the spread operator (...) to pass the transformed arguments to fn.

const rearg = (fn, indexes) => (...args) =>
+  fn(
+    ...args.reduce(
+      (acc, val, i) => ((acc[indexes.indexOf(i)] = val), acc),
+      Array.from({ length: indexes.length })
+    )
+  );
+
var rearged = rearg(
+  function(a, b, c) {
+    return [a, b, c];
+  },
+  [2, 0, 1]
+);
+rearged('b', 'c', 'a'); // ['a', 'b', 'c']
 

spreadOver

Takes a variadic function and returns a closure that accepts an array of arguments to map to the inputs of the function.

Use closures and the spread operator (...) to map the array of arguments to the inputs of the function.

const spreadOver = fn => argsArr => fn(...argsArr);
 
const arrayMax = spreadOver(Math.max);
 arrayMax([1, 2, 3]); // 3
@@ -752,7 +784,18 @@ document.bodypadStart(2, '0')}`;
 };
 
tomorrow(); // 2017-12-27 (if current date is 2017-12-26)
-

Function

bind

Creates a function that invokes fn with a given context, optionally adding any additional supplied parameters to the beginning of the arguments.

Return a function that uses Function.apply() to apply the given context to fn. Use Array.concat() to prepend any additional supplied parameters to the arguments.

const bind = (fn, context, ...args) =>
+

Function

attempt

Attempts to invoke a function with the provided arguments, returning either the result or the caught error object.

Use a try... catch block to return either the result of the function or an appropriate error.

const attempt = (fn, ...args) => {
+  try {
+    return fn(args);
+  } catch (e) {
+    return e instanceof Error ? e : new Error(e);
+  }
+};
+
var elements = attempt(function(selector) {
+  return document.querySelectorAll(selector);
+}, '>_>');
+if (elements instanceof Error) elements = []; // elements = []
+

bind

Creates a function that invokes fn with a given context, optionally adding any additional supplied parameters to the beginning of the arguments.

Return a function that uses Function.apply() to apply the given context to fn. Use Array.concat() to prepend any additional supplied parameters to the arguments.

const bind = (fn, context, ...args) =>
   function() {
     return fn.apply(context, args.concat(...arguments));
   };
@@ -802,6 +845,22 @@ console.log<
   arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
 
curry(Math.pow)(2)(10); // 1024
 curry(Math.min, 3)(10)(50)(2); // 2
+

debounce

Creates a debounced function that delays invoking the provided function until after wait milliseconds have elapsed since the last time the debounced function was invoked.

Use setTimeout() and clearTimeout() to debounce the given method, fn. Use Function.apply() to apply the this context to the function and provide the necessary arguments. Omit the second argument, wait, to set the timeout at a default of 0 ms.

const debounce = (fn, wait = 0) => {
+  let inDebounce;
+  return function() {
+    const context = this,
+      args = arguments;
+    clearTimeout(inDebounce);
+    inDebounce = setTimeout(() => fn.apply(context, args), wait);
+  };
+};
+
window.addEventListener(
+  'resize',
+  debounce(function(evt) {
+    console.log(window.innerWidth);
+    console.log(window.innerHeight);
+  }, 250)
+); // Will log the window dimensions at most every 250ms
 

defer

Defers invoking a function until the current call stack has cleared.

Use setTimeout() with a timeout of 1ms to add a new event to the browser event queue and allow the rendering engine to complete its work. Use the spread (...) operator to supply the function with an arbitrary number of arguments.

const defer = (fn, ...args) => setTimeout(fn, 1, ...args);
 
// Example A:
 defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a'
@@ -868,6 +927,33 @@ document.bodyawait sleep(1000);
   console.log('I woke up after 1 second.');
 }
+

throttle

Creates a throttled function that only invokes the provided function at most once per every wait milliseconds

Use setTimeout() and clearTimeout() to throttle the given method, fn. Use Function.apply() to apply the this context to the function and provide the necessary arguments. Use Date.now() to keep track of the last time the throttled function was invoked. Omit the second argument, wait, to set the timeout at a default of 0 ms.

const throttle = (fn, wait) => {
+  let inThrottle, lastFn, lastTime;
+  return function() {
+    const context = this,
+      args = arguments;
+    if (!inThrottle) {
+      fn.apply(context, args);
+      lastTime = Date.now();
+      inThrottle = true;
+    } else {
+      clearTimeout(lastFn);
+      lastFn = setTimeout(function() {
+        if (Date.now() - lastTime >= wait) {
+          fn.apply(context, args);
+          lastTime = Date.now();
+        }
+      }, wait - (Date.now() - lastTime));
+    }
+  };
+};
+
window.addEventListener(
+  'resize',
+  throttle(function(evt) {
+    console.log(window.innerWidth);
+    console.log(window.innerHeight);
+  }, 250)
+); // Will log the window dimensions at most every 250ms
 

times

Iterates over a callback n times

Use Function.call() to call fn n times or until it returns false. Omit the last argument, context, to use an undefined object (or the global object in non-strict mode).

const times = (n, fn, context = undefined) => {
   let i = 0;
   while (fn.call(context, i) !== false && ++i < n) {}
@@ -1137,12 +1223,14 @@ console.log<
     (c ^ (crypto.randomBytes(1)[0] & (15 >> (c / 4)))).toString(16)
   );
 
UUIDGeneratorNode(); // '79c7c136-60ee-40a2-beb2-856f1feabefc'
-

Object

bindAll

Explain briefly what the snippet does.

Use Array.forEach() to return a function that uses Function.apply() to apply the given context (obj) to fn for each function specified.

const bindAll = (obj, ...fns) =>
+

Object

bindAll

Use Array.forEach() to return a function that uses Function.apply() to apply the given context (obj) to fn for each function specified.

const bindAll = (obj, ...fns) =>
   fns.forEach(
-    fn =>
-      (obj[fn] = function() {
-        return fn.apply(obj);
+    fn => (
+      (f = obj[fn]),
+      (obj[fn] = function() {
+        return f.apply(obj);
       })
+    )
   );
 
var view = {
   label: 'docs',
diff --git a/snippets/attempt.md b/snippets/attempt.md
new file mode 100644
index 000000000..c3dae169e
--- /dev/null
+++ b/snippets/attempt.md
@@ -0,0 +1,22 @@
+### attempt
+
+Attempts to invoke a function with the provided arguments, returning either the result or the caught error object.
+
+Use a `try... catch` block to return either the result of the function or an appropriate error.
+
+```js
+const attempt = (fn, ...args) => {
+  try {
+    return fn(args);
+  } catch (e) {
+    return e instanceof Error ? e : new Error(e);
+  }
+};
+```
+
+```js
+var elements = attempt(function(selector) {
+  return document.querySelectorAll(selector);
+}, '>_>');
+if (elements instanceof Error) elements = []; // elements = []
+```
diff --git a/snippets/bindAll.md b/snippets/bindAll.md
index e5e618ae0..da869957f 100644
--- a/snippets/bindAll.md
+++ b/snippets/bindAll.md
@@ -1,16 +1,16 @@
 ### bindAll
 
-Explain briefly what the snippet does.
-
 Use `Array.forEach()` to return a `function` that uses `Function.apply()` to apply the given context (`obj`) to `fn` for each function specified.
 
 ```js
 const bindAll = (obj, ...fns) =>
   fns.forEach(
-    fn =>
+    fn => (
+      (f = obj[fn]),
       (obj[fn] = function() {
-        return fn.apply(obj);
+        return f.apply(obj);
       })
+    )
   );
 ```
 
diff --git a/snippets/collectInto.md b/snippets/collectInto.md
index 3da1173bd..da37626a2 100644
--- a/snippets/collectInto.md
+++ b/snippets/collectInto.md
@@ -13,5 +13,5 @@ const Pall = collectInto(Promise.all.bind(Promise));
 let p1 = Promise.resolve(1);
 let p2 = Promise.resolve(2);
 let p3 = new Promise(resolve => setTimeout(resolve, 2000, 3));
-Pall(p1, p2, p3).then(console.log);
+Pall(p1, p2, p3).then(console.log); // [1, 2, 3] (after about 2 seconds)
 ```
diff --git a/snippets/debounce.md b/snippets/debounce.md
new file mode 100644
index 000000000..941ab59a3
--- /dev/null
+++ b/snippets/debounce.md
@@ -0,0 +1,29 @@
+### debounce
+
+Creates a debounced function that delays invoking the provided function until after `wait` milliseconds have elapsed since the last time the debounced function was invoked.
+
+Use `setTimeout()` and `clearTimeout()` to debounce the given method, `fn`.
+Use `Function.apply()` to apply the `this` context to the function and provide the necessary `arguments`.
+Omit the second argument, `wait`, to set the timeout at a default of 0 ms.
+
+```js
+const debounce = (fn, wait = 0) => {
+  let inDebounce;
+  return function() {
+    const context = this,
+      args = arguments;
+    clearTimeout(inDebounce);
+    inDebounce = setTimeout(() => fn.apply(context, args), wait);
+  };
+};
+```
+
+```js
+window.addEventListener(
+  'resize',
+  debounce(function(evt) {
+    console.log(window.innerWidth);
+    console.log(window.innerHeight);
+  }, 250)
+); // Will log the window dimensions at most every 250ms
+```
diff --git a/snippets/overArgs.md b/snippets/overArgs.md
new file mode 100644
index 000000000..9a913e049
--- /dev/null
+++ b/snippets/overArgs.md
@@ -0,0 +1,19 @@
+### overArgs
+
+Creates a function that invokes the provided function with its arguments transformed.
+
+Use `Array.map()` to apply `transforms` to `args` in combination with the spread operator (`...`) to pass the transformed arguments to `fn`.
+
+```js
+const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
+```
+
+```js
+var func = overArgs(
+  function(x, y) {
+    return [x, y];
+  },
+  [square, doubled]
+);
+func(9, 3); // [81, 6]
+```
diff --git a/snippets/pipeAsyncFunctions.md b/snippets/pipeAsyncFunctions.md
new file mode 100644
index 000000000..574591cb0
--- /dev/null
+++ b/snippets/pipeAsyncFunctions.md
@@ -0,0 +1,23 @@
+### pipeAsyncFunctions
+
+Performs left-to-right function composition for asynchronous functions.
+
+Use `Array.reduce()` with the spread operator (`...`) to perform left-to-right function composition using `Promise.then()`.
+The functions can return a combination of: simple values, `Promise`'s, or they can be defined as `async` ones returning through `await`.
+All functions must be unary.
+
+```js
+const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
+```
+
+```js
+const sum = pipeAsyncFunctions(
+  x => x + 1,
+  x => new Promise(resolve => setTimeout(() => resolve(x + 2), 1000)),
+  x => x + 3,
+  async x => (await x) + 4
+);
+(async () => {
+  console.log(await sum(5)); // 15 (after one second)
+})();
+```
diff --git a/snippets/rearg.md b/snippets/rearg.md
new file mode 100644
index 000000000..f58ea2f58
--- /dev/null
+++ b/snippets/rearg.md
@@ -0,0 +1,25 @@
+### rearg
+
+Creates a function that invokes the provided function with its arguments arranged according to the specified indexes.
+
+Use `Array.reduce()` and `Array.indexOf()` to reorder arguments based on `indexes` in combination with the spread operator (`...`) to pass the transformed arguments to `fn`.
+
+```js
+const rearg = (fn, indexes) => (...args) =>
+  fn(
+    ...args.reduce(
+      (acc, val, i) => ((acc[indexes.indexOf(i)] = val), acc),
+      Array.from({ length: indexes.length })
+    )
+  );
+```
+
+```js
+var rearged = rearg(
+  function(a, b, c) {
+    return [a, b, c];
+  },
+  [2, 0, 1]
+);
+rearged('b', 'c', 'a'); // ['a', 'b', 'c']
+```
diff --git a/snippets/throttle.md b/snippets/throttle.md
new file mode 100644
index 000000000..5e1d01fd7
--- /dev/null
+++ b/snippets/throttle.md
@@ -0,0 +1,41 @@
+### throttle
+
+Creates a throttled function that only invokes the provided function at most once per every `wait` milliseconds
+
+Use `setTimeout()` and `clearTimeout()` to throttle the given method, `fn`.
+Use `Function.apply()` to apply the `this` context to the function and provide the necessary `arguments`.
+Use `Date.now()` to keep track of the last time the throttled function was invoked.
+Omit the second argument, `wait`, to set the timeout at a default of 0 ms.
+
+```js
+const throttle = (fn, wait) => {
+  let inThrottle, lastFn, lastTime;
+  return function() {
+    const context = this,
+      args = arguments;
+    if (!inThrottle) {
+      fn.apply(context, args);
+      lastTime = Date.now();
+      inThrottle = true;
+    } else {
+      clearTimeout(lastFn);
+      lastFn = setTimeout(function() {
+        if (Date.now() - lastTime >= wait) {
+          fn.apply(context, args);
+          lastTime = Date.now();
+        }
+      }, wait - (Date.now() - lastTime));
+    }
+  };
+};
+```
+
+```js
+window.addEventListener(
+  'resize',
+  throttle(function(evt) {
+    console.log(window.innerWidth);
+    console.log(window.innerHeight);
+  }, 250)
+); // Will log the window dimensions at most every 250ms
+```
diff --git a/tag_database b/tag_database
index 0f8821946..4a5a0f084 100644
--- a/tag_database
+++ b/tag_database
@@ -2,6 +2,7 @@ anagrams:string,recursion
 arrayToHtmlList:browser,array
 ary:adapter,function
 atob:node,string,utility
+attempt:function
 average:math,array
 averageBy:math,array,function
 bind:function,object
@@ -32,6 +33,7 @@ createElement:browser,utility
 createEventHub:browser,event,advanced
 currentURL:browser,url
 curry:function,recursion
+debounce:function
 decapitalize:string,array
 deepClone:object,recursion
 deepFlatten:array,recursion
@@ -161,6 +163,7 @@ once:function
 onUserInputChange:browser,event,advanced
 orderBy:object,array
 over:adapter,function
+overArgs:adapter,function
 palindrome:string
 parseCookie:utility,string
 partial:function
@@ -169,6 +172,7 @@ partition:array,object,function
 percentile:math
 pick:object,array
 pickBy:object,array,function
+pipeAsyncFunctions:adapter,function,promise
 pipeFunctions:adapter,function
 pluralize:string
 powerset:math
@@ -184,6 +188,7 @@ randomIntArrayInRange:math,utility,random
 randomIntegerInRange:math,utility,random
 randomNumberInRange:math,utility,random
 readFileLines:node,array,string
+rearg:adapter,function
 redirect:browser,url
 reducedFilter:array
 reduceSuccessive:array,function
@@ -227,6 +232,7 @@ take:array
 takeRight:array
 takeRightWhile:array,function
 takeWhile:array,function
+throttle:function
 times:function
 timeTaken:utility
 toCamelCase:string,regexp
diff --git a/test/anagrams/anagrams.test.js b/test/anagrams/anagrams.test.js
index 4318f4c46..a7987d63f 100644
--- a/test/anagrams/anagrams.test.js
+++ b/test/anagrams/anagrams.test.js
@@ -6,9 +6,11 @@ test('Testing anagrams', (t) => {
   //Please go to https://github.com/substack/tape
   t.true(typeof anagrams === 'function', 'anagrams is a Function');
   t.deepEqual(anagrams('abc'), ['abc','acb','bac','bca','cab','cba'], "Generates all anagrams of a string");
+  t.deepEqual(anagrams('a'), ['a'], "Works for single-letter strings");
+  t.deepEqual(anagrams(''), [''], "Works for empty strings");
   //t.deepEqual(anagrams(args..), 'Expected');
   //t.equal(anagrams(args..), 'Expected');
   //t.false(anagrams(args..), 'Expected');
   //t.throws(anagrams(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/ary/ary.test.js b/test/ary/ary.test.js
index 445b40618..065b18a96 100644
--- a/test/ary/ary.test.js
+++ b/test/ary/ary.test.js
@@ -5,9 +5,11 @@ test('Testing ary', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof ary === 'function', 'ary is a Function');
+  const firstTwoMax = ary(Math.max, 2);
+  t.deepEquals([[2, 6, 'a'], [8, 4, 6], [10]].map(x => firstTwoMax(...x)), [6, 8, 10], 'Discards arguments with index >=n')
   //t.deepEqual(ary(args..), 'Expected');
   //t.equal(ary(args..), 'Expected');
   //t.false(ary(args..), 'Expected');
   //t.throws(ary(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/attempt/attempt.js b/test/attempt/attempt.js
new file mode 100644
index 000000000..6d079c71e
--- /dev/null
+++ b/test/attempt/attempt.js
@@ -0,0 +1,8 @@
+const attempt = (fn, ...args) => {
+try {
+return fn(args);
+} catch (e) {
+return e instanceof Error ? e : new Error(e);
+}
+};
+module.exports = attempt
\ No newline at end of file
diff --git a/test/attempt/attempt.test.js b/test/attempt/attempt.test.js
new file mode 100644
index 000000000..13ae65686
--- /dev/null
+++ b/test/attempt/attempt.test.js
@@ -0,0 +1,15 @@
+const test = require('tape');
+const attempt = require('./attempt.js');
+
+test('Testing attempt', (t) => {
+  //For more information on all the methods supported by tape
+  //Please go to https://github.com/substack/tape
+  t.true(typeof attempt === 'function', 'attempt is a Function');
+  t.equals(attempt(() => 0), 0, 'Returns a value');
+  t.true(attempt(() => {throw new Error()}) instanceof Error, 'Returns an error');
+  //t.deepEqual(attempt(args..), 'Expected');
+  //t.equal(attempt(args..), 'Expected');
+  //t.false(attempt(args..), 'Expected');
+  //t.throws(attempt(args..), 'Expected');
+  t.end();
+});
diff --git a/test/bind/bind.test.js b/test/bind/bind.test.js
index 6ad403682..e3ba1054c 100644
--- a/test/bind/bind.test.js
+++ b/test/bind/bind.test.js
@@ -5,9 +5,15 @@ test('Testing bind', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof bind === 'function', 'bind is a Function');
+  function greet(greeting, punctuation) {
+    return greeting + ' ' + this.user + punctuation;
+  }
+  const freddy = { user: 'fred' };
+  const freddyBound = bind(greet, freddy);
+  t.equals(freddyBound('hi', '!'),'hi fred!', 'Binds to an object context');
   //t.deepEqual(bind(args..), 'Expected');
   //t.equal(bind(args..), 'Expected');
   //t.false(bind(args..), 'Expected');
   //t.throws(bind(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/bindAll/bindAll.js b/test/bindAll/bindAll.js
index cf66ad583..507a4a9bc 100644
--- a/test/bindAll/bindAll.js
+++ b/test/bindAll/bindAll.js
@@ -1,8 +1,8 @@
 const bindAll = (obj, ...fns) =>
 fns.forEach(
 fn =>
-(obj[fn] = function() {
-return fn.apply(obj);
+(f = obj[fn], obj[fn] = function() {
+return f.apply(obj);
 })
 );
 module.exports = bindAll
\ No newline at end of file
diff --git a/test/bindAll/bindAll.test.js b/test/bindAll/bindAll.test.js
index 513eae230..90c9e23a8 100644
--- a/test/bindAll/bindAll.test.js
+++ b/test/bindAll/bindAll.test.js
@@ -5,9 +5,17 @@ test('Testing bindAll', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof bindAll === 'function', 'bindAll is a Function');
+  var view = {
+    label: 'docs',
+    'click': function() {
+      return 'clicked ' + this.label;
+    }
+  }
+  bindAll(view, 'click');
+  t.equal(view.click(), 'clicked docs', 'Binds to an object context')
   //t.deepEqual(bindAll(args..), 'Expected');
   //t.equal(bindAll(args..), 'Expected');
   //t.false(bindAll(args..), 'Expected');
   //t.throws(bindAll(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/bindKey/bindKey.test.js b/test/bindKey/bindKey.test.js
index 36619ebcd..2aed1fb1e 100644
--- a/test/bindKey/bindKey.test.js
+++ b/test/bindKey/bindKey.test.js
@@ -5,9 +5,17 @@ test('Testing bindKey', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof bindKey === 'function', 'bindKey is a Function');
+  const freddy = {
+    user: 'fred',
+    greet: function(greeting, punctuation) {
+      return greeting + ' ' + this.user + punctuation;
+    }
+  };
+  const freddyBound = bindKey(freddy, 'greet');
+  t.equal(freddyBound('hi', '!'), 'hi fred!', 'Binds function to an object context');
   //t.deepEqual(bindKey(args..), 'Expected');
   //t.equal(bindKey(args..), 'Expected');
   //t.false(bindKey(args..), 'Expected');
   //t.throws(bindKey(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/byteSize/byteSize.test.js b/test/byteSize/byteSize.test.js
index 32718fada..b79b83889 100644
--- a/test/byteSize/byteSize.test.js
+++ b/test/byteSize/byteSize.test.js
@@ -5,6 +5,9 @@ test('Testing byteSize', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof byteSize === 'function', 'byteSize is a Function');
+  // Blob is not part of Node apparently?
+  //t.equal(byteSize('Hello World'), 11, 'Works for text');
+  //t.equal(byteSize('😀'), 4, 'Works for emojis');
   // Works only in browser
   // t.equal(byteSize('Hello World'), 11, "Returns the length of a string in bytes");
   //t.deepEqual(byteSize(args..), 'Expected');
@@ -12,4 +15,4 @@ test('Testing byteSize', (t) => {
   //t.false(byteSize(args..), 'Expected');
   //t.throws(byteSize(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/collectInto/collectInto.test.js b/test/collectInto/collectInto.test.js
index a3d303e5a..557134336 100644
--- a/test/collectInto/collectInto.test.js
+++ b/test/collectInto/collectInto.test.js
@@ -5,9 +5,14 @@ test('Testing collectInto', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof collectInto === 'function', 'collectInto is a Function');
+  const Pall = collectInto(Promise.all.bind(Promise));
+  let p1 = Promise.resolve(1);
+  let p2 = Promise.resolve(2);
+  let p3 = new Promise(resolve => setTimeout(resolve, 2000, 3));
+  Pall(p1, p2, p3).then(function(val){ t.deepEqual(val, [1,2,3], 'Works with multiple promises')}, function(reason){});
   //t.deepEqual(collectInto(args..), 'Expected');
   //t.equal(collectInto(args..), 'Expected');
   //t.false(collectInto(args..), 'Expected');
   //t.throws(collectInto(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/countBy/countBy.test.js b/test/countBy/countBy.test.js
index ea6c3b748..94296d017 100644
--- a/test/countBy/countBy.test.js
+++ b/test/countBy/countBy.test.js
@@ -5,9 +5,11 @@ test('Testing countBy', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof countBy === 'function', 'countBy is a Function');
+  t.deepEqual(countBy([6.1, 4.2, 6.3], Math.floor), {4: 1, 6: 2}, 'Works for functions');
+  t.deepEqual(countBy(['one', 'two', 'three'], 'length'), {3: 2, 5: 1}, 'Works for property names');
   //t.deepEqual(countBy(args..), 'Expected');
   //t.equal(countBy(args..), 'Expected');
   //t.false(countBy(args..), 'Expected');
   //t.throws(countBy(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/debounce/debounce.js b/test/debounce/debounce.js
new file mode 100644
index 000000000..430bfeaed
--- /dev/null
+++ b/test/debounce/debounce.js
@@ -0,0 +1,10 @@
+const debounce = (fn, wait = 0) => {
+let inDebounce;
+return function() {
+const context = this,
+args = arguments;
+clearTimeout(inDebounce);
+inDebounce = setTimeout(() => fn.apply(context, args), wait);
+};
+};
+module.exports = debounce
\ No newline at end of file
diff --git a/test/debounce/debounce.test.js b/test/debounce/debounce.test.js
new file mode 100644
index 000000000..f1a35323c
--- /dev/null
+++ b/test/debounce/debounce.test.js
@@ -0,0 +1,13 @@
+const test = require('tape');
+const debounce = require('./debounce.js');
+
+test('Testing debounce', (t) => {
+  //For more information on all the methods supported by tape
+  //Please go to https://github.com/substack/tape
+  t.true(typeof debounce === 'function', 'debounce is a Function');
+  //t.deepEqual(debounce(args..), 'Expected');
+  //t.equal(debounce(args..), 'Expected');
+  //t.false(debounce(args..), 'Expected');
+  //t.throws(debounce(args..), 'Expected');
+  t.end();
+});
\ No newline at end of file
diff --git a/test/decapitalize/decapitalize.test.js b/test/decapitalize/decapitalize.test.js
index c18264447..83bf6b32a 100644
--- a/test/decapitalize/decapitalize.test.js
+++ b/test/decapitalize/decapitalize.test.js
@@ -5,9 +5,11 @@ test('Testing decapitalize', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof decapitalize === 'function', 'decapitalize is a Function');
+  t.equal(decapitalize('FooBar'), 'fooBar', 'Works with default parameter');
+  t.equal(decapitalize('FooBar', true), 'fOOBAR', 'Works with second parameter set to true');
   //t.deepEqual(decapitalize(args..), 'Expected');
   //t.equal(decapitalize(args..), 'Expected');
   //t.false(decapitalize(args..), 'Expected');
   //t.throws(decapitalize(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/dropWhile/dropWhile.test.js b/test/dropWhile/dropWhile.test.js
index 6e0ecf54e..198d8202a 100644
--- a/test/dropWhile/dropWhile.test.js
+++ b/test/dropWhile/dropWhile.test.js
@@ -10,4 +10,4 @@ test('Testing dropWhile', (t) => {
   //t.false(dropWhile(args..), 'Expected');
   //t.throws(dropWhile(args..), 'Expected');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/overArgs/overArgs.js b/test/overArgs/overArgs.js
new file mode 100644
index 000000000..41250eb89
--- /dev/null
+++ b/test/overArgs/overArgs.js
@@ -0,0 +1,2 @@
+const overArgs = (fn, transforms) => (...args) => fn(...args.map((val, i) => transforms[i](val)));
+module.exports = overArgs
\ No newline at end of file
diff --git a/test/overArgs/overArgs.test.js b/test/overArgs/overArgs.test.js
new file mode 100644
index 000000000..81c194c90
--- /dev/null
+++ b/test/overArgs/overArgs.test.js
@@ -0,0 +1,13 @@
+const test = require('tape');
+const overArgs = require('./overArgs.js');
+
+test('Testing overArgs', (t) => {
+  //For more information on all the methods supported by tape
+  //Please go to https://github.com/substack/tape
+  t.true(typeof overArgs === 'function', 'overArgs is a Function');
+  //t.deepEqual(overArgs(args..), 'Expected');
+  //t.equal(overArgs(args..), 'Expected');
+  //t.false(overArgs(args..), 'Expected');
+  //t.throws(overArgs(args..), 'Expected');
+  t.end();
+});
\ No newline at end of file
diff --git a/test/pipeAsyncFunctions/pipeAsyncFunctions.js b/test/pipeAsyncFunctions/pipeAsyncFunctions.js
new file mode 100644
index 000000000..09091affc
--- /dev/null
+++ b/test/pipeAsyncFunctions/pipeAsyncFunctions.js
@@ -0,0 +1,2 @@
+const pipeAsyncFunctions = (...fns) => arg => fns.reduce((p, f) => p.then(f), Promise.resolve(arg));
+module.exports = pipeAsyncFunctions
\ No newline at end of file
diff --git a/test/pipeAsyncFunctions/pipeAsyncFunctions.test.js b/test/pipeAsyncFunctions/pipeAsyncFunctions.test.js
new file mode 100644
index 000000000..7a4ae346e
--- /dev/null
+++ b/test/pipeAsyncFunctions/pipeAsyncFunctions.test.js
@@ -0,0 +1,24 @@
+const test = require('tape');
+const pipeAsyncFunctions = require('./pipeAsyncFunctions.js');
+
+test('Testing pipeAsyncFunctions', async (t) => {
+  //For more information on all the methods supported by tape
+  //Please go to https://github.com/substack/tape
+  t.true(typeof pipeAsyncFunctions === 'function', 'pipeAsyncFunctions is a Function');
+  //t.deepEqual(pipeAsyncFunctions(args..), 'Expected');
+  //t.equal(pipeAsyncFunctions(args..), 'Expected');
+  //t.false(pipeAsyncFunctions(args..), 'Expected');
+  //t.throws(pipeAsyncFunctions(args..), 'Expected');
+  t.equal(
+    await pipeAsyncFunctions(
+      (x) => x + 1,
+      (x) => new Promise((resolve) => setTimeout(() => resolve(x + 2), 0)),
+      (x) => x + 3,
+      async (x) => await x + 4,
+    )
+    (5),
+    15,
+    'pipeAsyncFunctions result should be 15'
+  );
+  t.end();
+});
\ No newline at end of file
diff --git a/test/rearg/rearg.js b/test/rearg/rearg.js
new file mode 100644
index 000000000..b2f97244c
--- /dev/null
+++ b/test/rearg/rearg.js
@@ -0,0 +1,8 @@
+const rearg = (fn, indexes) => (...args) =>
+fn(
+...args.reduce(
+(acc, val, i) => ((acc[indexes.indexOf(i)] = val), acc),
+Array.from({ length: indexes.length })
+)
+);
+module.exports = rearg
\ No newline at end of file
diff --git a/test/rearg/rearg.test.js b/test/rearg/rearg.test.js
new file mode 100644
index 000000000..9139d3f64
--- /dev/null
+++ b/test/rearg/rearg.test.js
@@ -0,0 +1,13 @@
+const test = require('tape');
+const rearg = require('./rearg.js');
+
+test('Testing rearg', (t) => {
+  //For more information on all the methods supported by tape
+  //Please go to https://github.com/substack/tape
+  t.true(typeof rearg === 'function', 'rearg is a Function');
+  //t.deepEqual(rearg(args..), 'Expected');
+  //t.equal(rearg(args..), 'Expected');
+  //t.false(rearg(args..), 'Expected');
+  //t.throws(rearg(args..), 'Expected');
+  t.end();
+});
\ No newline at end of file
diff --git a/test/round/round.test.js b/test/round/round.test.js
index 7af718c04..2aa705899 100644
--- a/test/round/round.test.js
+++ b/test/round/round.test.js
@@ -5,9 +5,19 @@ test('Testing round', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof round === 'function', 'round is a Function');
-  t.equal(round(1.005, 2), 1.01, "Rounds a number to a specified amount of digits.");
-  //t.equal(round(args..), 'Expected');
-  //t.false(round(args..), 'Expected');
-  //t.throws(round(args..), 'Expected');
+  t.equal(round(1.005, 2), 1.01, "round(1.005, 2) returns 1.01");
+  t.equal(round(123.3423345345345345344, 11), 123.34233453453, "round(123.3423345345345345344, 11) returns 123.34233453453");
+  t.equal(round(3.342, 11), 3.342, "round(3.342, 11) returns 3.342");
+  t.equal(round(1.005), 1, "round(1.005) returns 1");
+  t.true(isNaN(round([1.005, 2])), 'round([1.005, 2]) returns NaN');
+  t.true(isNaN(round('string')), 'round(string) returns NaN');
+  t.true(isNaN(round()), 'round() returns NaN');
+  t.true(isNaN(round(132, 413, 4134)), 'round(132, 413, 4134) returns NaN');
+  t.true(isNaN(round({a: 132}, 413)), 'round({a: 132}, 413) returns NaN');
+
+  let start = new Date().getTime();
+  round(123.3423345345345345344, 11);
+  let end = new Date().getTime();
+  t.true((end - start) < 2000, 'round(123.3423345345345345344, 11) takes less than 2s to run');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/testlog b/test/testlog
index 259d8d6f6..5f0aea7da 100644
--- a/test/testlog
+++ b/test/testlog
@@ -1,6 +1,6 @@
-Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
+Test log for: Sun Jan 28 2018 16:40:59 GMT+0200 (GTB Standard Time)
 
-> 30-seconds-of-code@0.0.1 test C:\Users\King David\Desktop\github-repo\30-seconds-of-code
+> 30-seconds-of-code@0.0.1 test G:\My Files\git Repositories\30-seconds-of-code
 > tape test/**/*.test.js | tap-spec
 
 
@@ -8,14 +8,20 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
 
     √ anagrams is a Function
     √ Generates all anagrams of a string
+    √ Works for single-letter strings
+    √ Works for empty strings
+
 
   Testing arrayToHtmlList
 
     √ arrayToHtmlList is a Function
+    √ Generates and fills a list element
 
   Testing ary
 
     √ ary is a Function
+    √ Discards arguments with index >=n
+
 
   Testing atob
 
@@ -23,6 +29,12 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
     √ atob("Zm9vYmFy") equals "foobar"
     √ atob("Z") returns ""
 
+  Testing attempt
+
+    √ attempt is a Function
+    √ Returns a value
+    √ Returns an error
+    
   Testing average
 
     √ average is a Function
@@ -51,14 +63,17 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing bind
 
     √ bind is a Function
+    √ Binds to an object context
 
   Testing bindAll
 
     √ bindAll is a Function
+    √ Binds to an object context
 
   Testing bindKey
 
     √ bindKey is a Function
+    √ Binds function to an object context
 
   Testing bottomVisible
 
@@ -173,6 +188,8 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing countBy
 
     √ countBy is a Function
+    √ Works for functions
+    √ Works for property names
 
   Testing countOccurrences
 
@@ -205,6 +222,16 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
 
     √ decapitalize is a Function
 
+  Testing debounce
+
+    √ debounce is a Function
+
+  Testing decapitalize
+
+    √ decapitalize is a Function
+    √ Works with default parameter
+    √ Works with second parameter set to true
+
   Testing deepClone
 
     √ deepClone is a Function
@@ -460,6 +487,7 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing hasClass
 
     √ hasClass is a Function
+    √ element has the specified class
 
   Testing hasFlags
 
@@ -957,6 +985,10 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
 
     √ over is a Function
 
+  Testing overArgs
+
+    √ overArgs is a Function
+
   Testing palindrome
 
     √ palindrome is a Function
@@ -994,6 +1026,11 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
 
     √ pickBy is a Function
 
+  Testing pipeAsyncFunctions
+
+    √ pipeAsyncFunctions is a Function
+    √ pipeAsyncFunctions result should be 15
+
   Testing pipeFunctions
 
     √ pipeFunctions is a Function
@@ -1075,6 +1112,10 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
 
     √ README is a Function
 
+  Testing rearg
+
+    √ rearg is a Function
+
   Testing redirect
 
     √ redirect is a Function
@@ -1118,7 +1159,16 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing round
 
     √ round is a Function
-    √ Rounds a number to a specified amount of digits.
+    √ round(1.005, 2) returns 1.01
+    √ round(123.3423345345345345344, 11) returns 123.34233453453
+    √ round(3.342, 11) returns 3.342
+    √ round(1.005) returns 1
+    √ round([1.005, 2]) returns NaN
+    √ round(string) returns NaN
+    √ round() returns NaN
+    √ round(132, 413, 4134) returns NaN
+    √ round({a: 132}, 413) returns NaN
+    √ round(123.3423345345345345344, 11) takes less than 2s to run
 
   Testing runAsync
 
@@ -1288,6 +1338,10 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
 
     √ takeWhile is a Function
 
+  Testing throttle
+
+    √ throttle is a Function
+
   Testing times
 
     √ times is a Function
@@ -1299,15 +1353,21 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing toCamelCase
 
     √ toCamelCase is a Function
-    √ Converts a string to camelCase
-    √ Converts a string to camelCase
-    √ Converts a string to camelCase
-    √ Converts a string to camelCase
+    √ toCamelCase('some_database_field_name') returns someDatabaseFieldName
+    √ toCamelCase('Some label that needs to be camelized') returns someLabelThatNeedsToBeCamelized
+    √ toCamelCase('some-javascript-property') return someJavascriptProperty
+    √ toCamelCase('some-mixed_string with spaces_underscores-and-hyphens') returns someMixedStringWithSpacesUnderscoresAndHyphens
+    √ toCamelCase() throws a error
+    √ toCamelCase([]) throws a error
+    √ toCamelCase({}) throws a error
+    √ toCamelCase(123) throws a error
+    √ toCamelCase(some-mixed_string with spaces_underscores-and-hyphens) takes less than 2s to run
 
   Testing toCurrency
 
     √ toCurrency is a Function
 
+
   Testing toDecimalMark
 
     √ toDecimalMark is a Function
@@ -1320,10 +1380,15 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing toKebabCase
 
     √ toKebabCase is a Function
-    √ string converts to snake case
-    √ string converts to snake case
-    √ string converts to snake case
-    √ string converts to snake case
+    √ toKebabCase('camelCase') returns camel-case
+    √ toKebabCase('some text') returns some-text
+    √ toKebabCase('some-mixed-string With spaces-underscores-and-hyphens') returns some-mixed-string-with-spaces-underscores-and-hyphens
+    √ toKebabCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML') returns i-am-listening-to-fm-while-loading-different-url-on-my-browser-and-also-editing-some-xml-and-html
+    √ toKebabCase() return undefined
+    √ toKebabCase([]) throws an error
+    √ toKebabCase({}) throws an error
+    √ toKebabCase(123) throws an error
+    √ toKebabCase(IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML) takes less than 2s to run
 
   Testing tomorrow
 
@@ -1340,19 +1405,30 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing toSafeInteger
 
     √ toSafeInteger is a Function
+    √ Number(toSafeInteger(3.2)) is a number
     √ Converts a value to a safe integer
-    √ Converts a value to a safe integer
-    √ Converts a value to a safe integer
-    √ Converts a value to a safe integer
-    √ Converts a value to a safe integer
+    √ toSafeInteger('4.2') returns 4
+    √ toSafeInteger(4.6) returns 5
+    √ toSafeInteger([]) returns 0
+    √ isNaN(toSafeInteger([1.5, 3124])) is true
+    √ isNaN(toSafeInteger('string')) is true
+    √ isNaN(toSafeInteger({})) is true
+    √ isNaN(toSafeInteger()) is true
+    √ toSafeInteger(Infinity) returns 9007199254740991
+    √ toSafeInteger(3.2) takes less than 2s to run
 
   Testing toSnakeCase
 
     √ toSnakeCase is a Function
-    √ string converts to snake case
-    √ string converts to snake case
-    √ string converts to snake case
-    √ string converts to snake case
+    √ toSnakeCase('camelCase') returns camel_case
+    √ toSnakeCase('some text') returns some_text
+    √ toSnakeCase('some-mixed_string With spaces_underscores-and-hyphens') returns some_mixed_string_with_spaces_underscores_and_hyphens
+    √ toSnakeCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML') returns i_am_listening_to_fm_while_loading_different_url_on_my_browser_and_also_editing_some_xml_and_html
+    √ toSnakeCase() returns undefined
+    √ toSnakeCase([]) throws an error
+    √ toSnakeCase({}) throws an error
+    √ toSnakeCase(123) throws an error
+    √ toSnakeCase(IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML) takes less than 2s to run
 
   Testing transform
 
@@ -1384,7 +1460,17 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing union
 
     √ union is a Function
-    √ Returns every element that exists in any of the two arrays once
+    √ union([1, 2, 3], [4, 3, 2]) returns [1, 2, 3, 4]
+    √ union('str', 'asd') returns [ 's', 't', 'r', 'a', 'd' ]
+    √ union([[], {}], [1, 2, 3]) returns [[], {}, 1, 2, 3]
+    √ union([], []) returns []
+    √ union() throws an error
+    √ union(true, str) throws an error
+    √ union(false, true) throws an error
+    √ union(123, {}) throws an error
+    √ union([], {}) throws an error
+    √ union(undefined, null) throws an error
+    √ union([1, 2, 3], [4, 3, 2]) takes less than 2s to run
 
   Testing unionBy
 
@@ -1397,7 +1483,18 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing uniqueElements
 
     √ uniqueElements is a Function
-    √ Returns all unique values of an array
+    √ uniqueElements([1, 2, 2, 3, 4, 4, 5]) returns [1,2,3,4,5]
+    √ uniqueElements([1, 23, 53]) returns [1, 23, 53]
+    √ uniqueElements([true, 0, 1, false, false, undefined, null, '']) returns [true, 0, 1, false, false, undefined, null, '']
+    √ uniqueElements() returns []
+    √ uniqueElements(null) returns []
+    √ uniqueElements(undefined) returns []
+    √ uniqueElements('strt') returns ['s', 't', 'r']
+    √ uniqueElements(1, 1, 2543, 534, 5) throws an error
+    √ uniqueElements({}) throws an error
+    √ uniqueElements(true) throws an error
+    √ uniqueElements(false) throws an error
+    √ uniqueElements([true, 0, 1, false, false, undefined, null]) takes less than 2s to run
 
   Testing untildify
 
@@ -1519,10 +1616,9 @@ Test log for: Sun Jan 28 2018 14:42:53 GMT-0500 (Eastern Standard Time)
   Testing zipWith
 
     √ zipWith is a Function
+    √ Works with multiple promises
 
 
-  total:     649
-  passing:   649
-  duration:  499ms
-
-
+  total:     721
+  passing:   721
+  duration:  3.1s
\ No newline at end of file
diff --git a/test/throttle/throttle.js b/test/throttle/throttle.js
new file mode 100644
index 000000000..b26b6b74b
--- /dev/null
+++ b/test/throttle/throttle.js
@@ -0,0 +1,21 @@
+const throttle = (fn, wait) => {
+let inThrottle, lastFn, lastTime;
+return function() {
+const context = this,
+args = arguments;
+if (!inThrottle) {
+fn.apply(context, args);
+lastTime = Date.now();
+inThrottle = true;
+} else {
+clearTimeout(lastFn);
+lastFn = setTimeout(function() {
+if (Date.now() - lastTime >= wait) {
+fn.apply(context, args);
+lastTime = Date.now();
+}
+}, wait - (Date.now() - lastTime));
+}
+};
+};
+module.exports = throttle
\ No newline at end of file
diff --git a/test/throttle/throttle.test.js b/test/throttle/throttle.test.js
new file mode 100644
index 000000000..4de75afdb
--- /dev/null
+++ b/test/throttle/throttle.test.js
@@ -0,0 +1,13 @@
+const test = require('tape');
+const throttle = require('./throttle.js');
+
+test('Testing throttle', (t) => {
+  //For more information on all the methods supported by tape
+  //Please go to https://github.com/substack/tape
+  t.true(typeof throttle === 'function', 'throttle is a Function');
+  //t.deepEqual(throttle(args..), 'Expected');
+  //t.equal(throttle(args..), 'Expected');
+  //t.false(throttle(args..), 'Expected');
+  //t.throws(throttle(args..), 'Expected');
+  t.end();
+});
\ No newline at end of file
diff --git a/test/toCamelCase/toCamelCase.test.js b/test/toCamelCase/toCamelCase.test.js
index b41794011..0f3efc557 100644
--- a/test/toCamelCase/toCamelCase.test.js
+++ b/test/toCamelCase/toCamelCase.test.js
@@ -5,13 +5,18 @@ test('Testing toCamelCase', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof toCamelCase === 'function', 'toCamelCase is a Function');
-  t.equal(toCamelCase('some_database_field_name'), 'someDatabaseFieldName', "Converts a string to camelCase");
-  t.equal(toCamelCase('Some label that needs to be camelized'), 'someLabelThatNeedsToBeCamelized', "Converts a string to camelCase");
-  t.equal(toCamelCase('some-javascript-property'), 'someJavascriptProperty', "Converts a string to camelCase");
-  t.equal(toCamelCase('some-mixed_string with spaces_underscores-and-hyphens'), 'someMixedStringWithSpacesUnderscoresAndHyphens', "Converts a string to camelCase");
-  //t.deepEqual(toCamelCase(args..), 'Expected');
-  //t.equal(toCamelCase(args..), 'Expected');
-  //t.false(toCamelCase(args..), 'Expected');
-  //t.throws(toCamelCase(args..), 'Expected');
+  t.equal(toCamelCase('some_database_field_name'), 'someDatabaseFieldName', "toCamelCase('some_database_field_name') returns someDatabaseFieldName");
+  t.equal(toCamelCase('Some label that needs to be camelized'), 'someLabelThatNeedsToBeCamelized', "toCamelCase('Some label that needs to be camelized') returns someLabelThatNeedsToBeCamelized");
+  t.equal(toCamelCase('some-javascript-property'), 'someJavascriptProperty', "toCamelCase('some-javascript-property') return someJavascriptProperty");
+  t.equal(toCamelCase('some-mixed_string with spaces_underscores-and-hyphens'), 'someMixedStringWithSpacesUnderscoresAndHyphens', "toCamelCase('some-mixed_string with spaces_underscores-and-hyphens') returns someMixedStringWithSpacesUnderscoresAndHyphens");
+  t.throws(() => toCamelCase(), 'toCamelCase() throws a error');
+  t.throws(() => toCamelCase([]), 'toCamelCase([]) throws a error');
+  t.throws(() => toCamelCase({}), 'toCamelCase({}) throws a error');
+  t.throws(() => toCamelCase(123), 'toCamelCase(123) throws a error');
+
+  let start = new Date().getTime();
+  toCamelCase('some-mixed_string with spaces_underscores-and-hyphens');
+  let end = new Date().getTime();
+  t.true((end - start) < 2000, 'toCamelCase(some-mixed_string with spaces_underscores-and-hyphens) takes less than 2s to run');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/toKebabCase/toKebabCase.test.js b/test/toKebabCase/toKebabCase.test.js
index fe305e2b2..e2dfd8891 100644
--- a/test/toKebabCase/toKebabCase.test.js
+++ b/test/toKebabCase/toKebabCase.test.js
@@ -5,13 +5,18 @@ test('Testing toKebabCase', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof toKebabCase === 'function', 'toKebabCase is a Function');
-  t.equal(toKebabCase('camelCase'), 'camel-case', "string converts to snake case");
-  t.equal(toKebabCase('some text'), 'some-text', "string converts to snake case");
-  t.equal(toKebabCase('some-mixed-string With spaces-underscores-and-hyphens'), 'some-mixed-string-with-spaces-underscores-and-hyphens', "string converts to snake case");
-  t.equal(toKebabCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML'), 'i-am-listening-to-fm-while-loading-different-url-on-my-browser-and-also-editing-some-xml-and-html', "string converts to snake case");
-  //t.deepEqual(toKebabCase(args..), 'Expected');
-  //t.equal(toKebabCase(args..), 'Expected');
-  //t.false(toKebabCase(args..), 'Expected');
-  //t.throws(toKebabCase(args..), 'Expected');
+  t.equal(toKebabCase('camelCase'), 'camel-case', "toKebabCase('camelCase') returns camel-case");
+  t.equal(toKebabCase('some text'), 'some-text', "toKebabCase('some text') returns some-text");
+  t.equal(toKebabCase('some-mixed-string With spaces-underscores-and-hyphens'), 'some-mixed-string-with-spaces-underscores-and-hyphens', "toKebabCase('some-mixed-string With spaces-underscores-and-hyphens') returns some-mixed-string-with-spaces-underscores-and-hyphens");
+  t.equal(toKebabCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML'), 'i-am-listening-to-fm-while-loading-different-url-on-my-browser-and-also-editing-some-xml-and-html', "toKebabCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML') returns i-am-listening-to-fm-while-loading-different-url-on-my-browser-and-also-editing-some-xml-and-html");
+  t.equal(toKebabCase(), undefined, 'toKebabCase() return undefined');
+  t.throws(() => toKebabCase([]), 'toKebabCase([]) throws an error');
+  t.throws(() => toKebabCase({}), 'toKebabCase({}) throws an error');
+  t.throws(() => toKebabCase(123), 'toKebabCase(123) throws an error');
+
+  let start = new Date().getTime();
+  toKebabCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML')
+  let end = new Date().getTime();
+  t.true((end - start) < 2000, 'toKebabCase(IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML) takes less than 2s to run');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/toSafeInteger/toSafeInteger.test.js b/test/toSafeInteger/toSafeInteger.test.js
index 508da718a..885f6e324 100644
--- a/test/toSafeInteger/toSafeInteger.test.js
+++ b/test/toSafeInteger/toSafeInteger.test.js
@@ -5,14 +5,20 @@ test('Testing toSafeInteger', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof toSafeInteger === 'function', 'toSafeInteger is a Function');
+  t.true(Number(toSafeInteger(3.2)), 'Number(toSafeInteger(3.2)) is a number');
   t.equal(toSafeInteger(3.2), 3, "Converts a value to a safe integer");
-  t.equal(toSafeInteger('4.2'), 4, "Converts a value to a safe integer");
-  t.equal(toSafeInteger(4.6), 5, "Converts a value to a safe integer");
-  t.equal(toSafeInteger(1.5), 2, "Converts a value to a safe integer");
-  t.equal(toSafeInteger(Infinity), 9007199254740991, "Converts a value to a safe integer");
-  //t.deepEqual(toSafeInteger(args..), 'Expected');
-  //t.equal(toSafeInteger(args..), 'Expected');
-  //t.false(toSafeInteger(args..), 'Expected');
-  //t.throws(toSafeInteger(args..), 'Expected');
+  t.equal(toSafeInteger('4.2'), 4, "toSafeInteger('4.2') returns 4");
+  t.equal(toSafeInteger(4.6), 5, "toSafeInteger(4.6) returns 5");
+  t.equal(toSafeInteger([]), 0, "toSafeInteger([]) returns 0");
+  t.true(isNaN(toSafeInteger([1.5, 3124])), "isNaN(toSafeInteger([1.5, 3124])) is true");
+  t.true(isNaN(toSafeInteger('string')), "isNaN(toSafeInteger('string')) is true");
+  t.true(isNaN(toSafeInteger({})), "isNaN(toSafeInteger({})) is true");
+  t.true(isNaN(toSafeInteger()), "isNaN(toSafeInteger()) is true");
+  t.equal(toSafeInteger(Infinity), 9007199254740991, "toSafeInteger(Infinity) returns 9007199254740991");
+
+  let start = new Date().getTime();
+  toSafeInteger(3.2);
+  let end = new Date().getTime();
+  t.true((end - start) < 2000, 'toSafeInteger(3.2) takes less than 2s to run');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/toSnakeCase/toSnakeCase.test.js b/test/toSnakeCase/toSnakeCase.test.js
index 14bed623d..72190fda2 100644
--- a/test/toSnakeCase/toSnakeCase.test.js
+++ b/test/toSnakeCase/toSnakeCase.test.js
@@ -5,14 +5,18 @@ test('Testing toSnakeCase', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof toSnakeCase === 'function', 'toSnakeCase is a Function');
-  t.equal(toSnakeCase('camelCase'), 'camel_case', "string converts to snake case");
-  t.equal(toSnakeCase('some text'), 'some_text', "string converts to snake case");
-  t.equal(toSnakeCase('some-mixed_string With spaces_underscores-and-hyphens'), 'some_mixed_string_with_spaces_underscores_and_hyphens', "string converts to snake case");
-  t.equal(toSnakeCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML'), 'i_am_listening_to_fm_while_loading_different_url_on_my_browser_and_also_editing_some_xml_and_html', "string converts to snake case");
+  t.equal(toSnakeCase('camelCase'), 'camel_case', "toSnakeCase('camelCase') returns camel_case");
+  t.equal(toSnakeCase('some text'), 'some_text', "toSnakeCase('some text') returns some_text");
+  t.equal(toSnakeCase('some-mixed_string With spaces_underscores-and-hyphens'), 'some_mixed_string_with_spaces_underscores_and_hyphens', "toSnakeCase('some-mixed_string With spaces_underscores-and-hyphens') returns some_mixed_string_with_spaces_underscores_and_hyphens");
+  t.equal(toSnakeCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML'), 'i_am_listening_to_fm_while_loading_different_url_on_my_browser_and_also_editing_some_xml_and_html', "toSnakeCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML') returns i_am_listening_to_fm_while_loading_different_url_on_my_browser_and_also_editing_some_xml_and_html");
+  t.equal(toSnakeCase(), undefined, 'toSnakeCase() returns undefined');
+  t.throws(() => toSnakeCase([]), 'toSnakeCase([]) throws an error');
+  t.throws(() => toSnakeCase({}), 'toSnakeCase({}) throws an error');
+  t.throws(() => toSnakeCase(123), 'toSnakeCase(123) throws an error');
 
-  //t.deepEqual(toSnakeCase(args..), 'Expected');
-  //t.equal(toSnakeCase(args..), 'Expected');
-  //t.false(toSnakeCase(args..), 'Expected');
-  //t.throws(toSnakeCase(args..), 'Expected');
+  let start = new Date().getTime();
+  toSnakeCase('IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML');
+  let end = new Date().getTime();
+  t.true((end - start) < 2000, 'toSnakeCase(IAmListeningToFMWhileLoadingDifferentURLOnMyBrowserAndAlsoEditingSomeXMLAndHTML) takes less than 2s to run');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/union/union.test.js b/test/union/union.test.js
index 73427934a..fd6157918 100644
--- a/test/union/union.test.js
+++ b/test/union/union.test.js
@@ -5,10 +5,20 @@ test('Testing union', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof union === 'function', 'union is a Function');
-  t.deepEqual(union([1, 2, 3], [4, 3, 2]), [1, 2, 3, 4], "Returns every element that exists in any of the two arrays once");
-  //t.deepEqual(union(args..), 'Expected');
-  //t.equal(union(args..), 'Expected');
-  //t.false(union(args..), 'Expected');
-  //t.throws(union(args..), 'Expected');
+  t.deepEqual(union([1, 2, 3], [4, 3, 2]), [1, 2, 3, 4], "union([1, 2, 3], [4, 3, 2]) returns [1, 2, 3, 4]");
+  t.deepEqual(union('str', 'asd'), [ 's', 't', 'r', 'a', 'd' ], "union('str', 'asd') returns [ 's', 't', 'r', 'a', 'd' ]");
+  t.deepEqual(union([[], {}], [1, 2, 3]), [[], {}, 1, 2, 3], "union([[], {}], [1, 2, 3]) returns [[], {}, 1, 2, 3]");
+  t.deepEqual(union([], []), [], "union([], []) returns []");
+  t.throws(() => union(), 'union() throws an error');
+  t.throws(() => union(true, 'str'), 'union(true, str) throws an error');
+  t.throws(() => union('false', true), 'union(false, true) throws an error');
+  t.throws(() => union(123, {}), 'union(123, {}) throws an error');
+  t.throws(() => union([], {}), 'union([], {}) throws an error');
+  t.throws(() => union(undefined, null), 'union(undefined, null) throws an error');
+
+  let start = new Date().getTime();
+  union([1, 2, 3], [4, 3, 2]);
+  let end = new Date().getTime();
+  t.true((end - start) < 2000, 'union([1, 2, 3], [4, 3, 2]) takes less than 2s to run');
   t.end();
-});
\ No newline at end of file
+});
diff --git a/test/uniqueElements/uniqueElements.test.js b/test/uniqueElements/uniqueElements.test.js
index 38d55aea5..137f791dc 100644
--- a/test/uniqueElements/uniqueElements.test.js
+++ b/test/uniqueElements/uniqueElements.test.js
@@ -5,10 +5,24 @@ test('Testing uniqueElements', (t) => {
   //For more information on all the methods supported by tape
   //Please go to https://github.com/substack/tape
   t.true(typeof uniqueElements === 'function', 'uniqueElements is a Function');
-  t.deepEqual(uniqueElements([1, 2, 2, 3, 4, 4, 5]), [1,2,3,4,5], "Returns all unique values of an array");
-  //t.deepEqual(uniqueElements(args..), 'Expected');
-  //t.equal(uniqueElements(args..), 'Expected');
-  //t.false(uniqueElements(args..), 'Expected');
-  //t.throws(uniqueElements(args..), 'Expected');
+  t.deepEqual(uniqueElements([1, 2, 2, 3, 4, 4, 5]), [1,2,3,4,5], "uniqueElements([1, 2, 2, 3, 4, 4, 5]) returns [1,2,3,4,5]");
+  t.deepEqual(uniqueElements([1, 23, 53]), [1, 23, 53], "uniqueElements([1, 23, 53]) returns [1, 23, 53]");
+  t.deepEqual(uniqueElements([true, 0, 1, false, false, undefined, null, '']), [true, 0, 1, false, undefined, null, ''], "uniqueElements([true, 0, 1, false, false, undefined, null, '']) returns [true, 0, 1, false, false, undefined, null, '']");
+  t.deepEqual(uniqueElements(), [], "uniqueElements() returns []");
+  t.deepEqual(uniqueElements(null), [], "uniqueElements(null) returns []");
+  t.deepEqual(uniqueElements(undefined), [], "uniqueElements(undefined) returns []");
+  t.deepEqual(uniqueElements('strt'), ['s', 't', 'r'], "uniqueElements('strt') returns ['s', 't', 'r']");
+  t.throws(() => uniqueElements(1, 1, 2543, 534, 5), 'uniqueElements(1, 1, 2543, 534, 5) throws an error');
+  t.throws(() => uniqueElements({}), 'uniqueElements({}) throws an error');
+  t.throws(() => uniqueElements(true), 'uniqueElements(true) throws an error');
+  t.throws(() => uniqueElements(false), 'uniqueElements(false) throws an error');
+
+  let start = new Date().getTime();
+  uniqueElements([true, 0, 1, false, false, undefined, null, ''])
+  let end = new Date().getTime();
+  t.true((end - start) < 2000, 'uniqueElements([true, 0, 1, false, false, undefined, null]) takes less than 2s to run');
+
   t.end();
-});
\ No newline at end of file
+});
+
+uniqueElements([1, 2, 2, '1', 4, 4, 4, 5, true]); // [1,2,3,4,5]