Repository: pbiswas101/Mathball
Pull request #4 (2019-01-19 12:36:52)

Added factorial feature
### Do the checklist before submitting the PR:

- [x] Have you read the guidelines mentioned in **CONTRIBUTING.md**?
- [x] Have you squashed your commits?

**Q**: What version of *Node.js* you've used in the project?
**A**: `Node v9.4.0`

**Q**: Mention the *Issue Number*!
**A**: ` #2 `


aleemuddin13: Cool noted the error handling part.

Quick question, why are you terminating the node js process if an error comes instead of just throwing it?
Users like me will not use this library in apps because it will terminate my application.
 

pbiswas101: I think uncaught error terminates the process too; But I also think that killing the process makes writing unit test for errors less approachable! So, yeah on the next minor release I am thinking of those changes! Plus I also want one error handling file tgat gets called in all modules for minimizing redundancy of course! But for now let's just maintain the consistency within the codebase.
aleemuddin13: Errors thrown by the library will be caught on the application level 
If a developer does not implement any catch mechanism on the application then it will terminate the process
For now, I will make changes according to the consistency within the codebase.  :)
aleemuddin13: Is there any way to whitelist usage of single quotes in codacy? If yes then half of your repo issues will go away.
pbiswas101: Yes, I unchecked the strict usage of double quotes along with parentheses around single argument in arrow functions! From next PR onwards this won't bother anyone!

Patch:
diff --git a/README.md b/README.md
index 6bfb995..40a8fe5 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,7 @@ $ npm install mathball --save
 - **Find nth Number**
 	- [fibonacci()][8]
 	- [magic()][9]
+	- [factorial()][21]
 
 - **Mathematical Utilities**
 	- [gcd()][10]
@@ -92,3 +93,4 @@ The MIT License 2018 - [Priyabrata Biswas][20].
 [18]: https://github.com/pbiswas101/Mathball/blob/master/src/sum/index.js
 [19]: https://github.com/pbiswas101/Mathball/blob/master/CONTRIBUTING.md
 [20]: https://github.com/pbiswas101
+[21]: https://github.com/pbiswas101/Mathball/blob/master/src/factorial/index.js
diff --git a/src/factorial/index.js b/src/factorial/index.js
new file mode 100644
index 0000000..a247944
--- /dev/null
+++ b/src/factorial/index.js
@@ -0,0 +1,52 @@
+/* Factorial of a Number
+ * Function: factorial()
+ */
+
+function handleError(type) {
+	if (typeof type == 'undefined') {
+		try {
+			throw new Error("'factorial()' didn't receive any valid argument!");
+		} catch (err) {
+			console.error('\x1b[36m%s\x1b[0m', err);
+			process.exit(0);
+		}
+	} else {
+		try {
+			throw new TypeError("Pass a positive integer to 'factorial()'!");
+		} catch (err) {
+			console.log(process.env);
+			console.error(
+				'\x1b[36m%s\x1b[0m',
+				err,
+				`\x1b[5m\nDo not include a '${type}'\x1b[0m`
+			);
+			process.exit(0);
+		}
+	}
+}
+
+/**
+ *
+ * @param {number} number
+ * @returns {number}
+ */
+function factorial(number) {
+	let i = 1,
+		result = 1;
+	for (; i <= number; i++) {
+		result = result * i;
+	}
+	return result;
+}
+
+exports.factorial = num => {
+	if (typeof num == 'undefined') handleError();
+	else if (typeof num == 'number' && parseInt(num, 10) == num && num >= 0) {
+		return factorial(num);
+	} else if (num != num) handleError('NaN');
+	else if (num + 1 == num) handleError('Infinity');
+	else if (typeof num == 'number' && parseInt(num, 10) != num)
+		handleError('floating point');
+	else if (typeof num == 'number' && num < 0) handleError('negative number');
+	else handleError(typeof num);
+};
diff --git a/src/index.js b/src/index.js
index f7b0e37..60503ac 100644
--- a/src/index.js
+++ b/src/index.js
@@ -6,7 +6,8 @@ const armstrong = require('./armstrong'),
 	magic = require('./magic'),
 	neon = require('./neon'),
 	palindrome = require('./palindrome'),
-	prime = require('./prime');
+	prime = require('./prime'),
+	factorial = require('./factorial');
 
 /* Mathematical Utilities */
 
@@ -27,8 +28,17 @@ module.exports = {
 	isAutomorphic: automorphic.isAutomorphic,
 	fibonacci: fibonacci.fibonacci,
 	magic: magic.magic,
+	factorial: factorial.factorial,
 	isNeon: neon.isNeon,
 	isPalindrome: palindrome.isPalindrome,
 	isPrime: prime.isPrime,
-	gcd, isEven, isOdd, lcm, length, max, min, sort, sum
+	gcd,
+	isEven,
+	isOdd,
+	lcm,
+	length,
+	max,
+	min,
+	sort,
+	sum
 };


Test patch:
diff --git a/test/factorial-spec.js b/test/factorial-spec.js
new file mode 100644
index 0000000..9abaf90
--- /dev/null
+++ b/test/factorial-spec.js
@@ -0,0 +1,36 @@
+const assert = require('assert'),
+	factorial = require('../src/factorial').factorial;
+
+describe('[Function: factorial]', () => {
+	it('should be a function', () => {
+		assert.strictEqual(typeof factorial, 'function');
+	});
+
+	it('should return 120 when 5 is passed', () => {
+		assert.strictEqual(factorial(5), 120);
+	});
+
+	it('should return 1 when 0 is passed', () => {
+		assert.strictEqual(factorial(0), 1);
+	});
+
+	it('should return 1 when 1 is passed', () => {
+		assert.strictEqual(factorial(1), 1);
+	});
+
+	// it('should throw an error when negative integers passed', () => {
+	// 	assert.throws(() => factorial(-20), TypeError);
+	// });
+
+	// it('should throw an error when non integer value passed', () => {
+	// 	assert.throws(() => factorial(31.101996), TypeError);
+	// });
+
+	// it('should throw an error when string passed', () => {
+	// 	assert.throws(() => factorial('31'), TypeError);
+	// });
+
+	// it('should throw an error when no arguments passed', () => {
+	// 	assert.throws(() => factorial(), TypeError);
+	// });
+});