Repository: char0n/ramda-adjunct
Pull request #817 (2019-02-05 20:54:24)

feat: add ceil
Ref #748




Patch:
diff --git a/src/ceil.js b/src/ceil.js
new file mode 100644
index 0000000000..90effd2664
--- /dev/null
+++ b/src/ceil.js
@@ -0,0 +1,29 @@
+import { bind } from 'ramda';
+import curry1 from 'ramda/src/internal/_curry1';
+
+/**
+ * Returns the smallest integer greater than or equal to a given number.
+ *
+ * Note: ceil(null) returns integer 0 and does not give a NaN error.
+ *
+ * @func ceil
+ * @memberOf RA
+ * @since {@link https://char0n.github.io/ramda-adjunct/2.15.0|v2.15.0}
+ * @category Math
+ * @sig Number -> Number
+ * @param {*} number The number to ceil
+ * @return {number} The smallest integer greater than or equal to the given number.
+ * @example
+ *
+ * RA.ceil(.95); //=> 1
+ * RA.ceil(4); //=> 4
+ * RA.ceil(7.004); //=> 8
+ * RA.ceil(-0.95); //=> -0
+ * RA.ceil(-4); //=> -4
+ * RA.ceil(-7.004); //=> -7
+ * RA.ceil(null); //=> 0
+ */
+
+const ceil = curry1(bind(Math.ceil, Math));
+
+export default ceil;
diff --git a/src/index.d.ts b/src/index.d.ts
index aa72cad1c2..ab62737677 100644
--- a/src/index.d.ts
+++ b/src/index.d.ts
@@ -1058,7 +1058,14 @@ declare namespace RamdaAdjunct {
         /**
          * Returns the value of a number rounded to the nearest integer.
          */
-         round(val: number): number;
+        round(val: number): number;
+
+        /**
+         * Returns the smallest integer greater than or equal to a given number.
+         *
+         * Note: ceil(null) returns integer 0 and does not give a NaN error.
+         */
+        ceil(val: number): number;
 
         /**
          * Identity type.
diff --git a/src/index.js b/src/index.js
index cd3e2cd7b5..0ce31dfa34 100644
--- a/src/index.js
+++ b/src/index.js
@@ -164,5 +164,6 @@ export { default as argsPass } from './argsPass';
 export { default as dropArgs } from './dropArgs';
 // Math
 export { default as round } from './round';
+export { default as ceil } from './ceil';
 // Types
 export { default as Identity } from './fantasy-land/Identity';


Test patch:
diff --git a/test/ceil.js b/test/ceil.js
new file mode 100644
index 0000000000..83b6b91c9a
--- /dev/null
+++ b/test/ceil.js
@@ -0,0 +1,81 @@
+import * as R from 'ramda';
+import { assert } from 'chai';
+
+import * as RA from '../src';
+import eq from './shared/eq';
+import Symbol from './shared/Symbol';
+
+describe('ceil', function() {
+  it('should ceil float to nearest integer', function() {
+    eq(RA.ceil(0.9), 1);
+    eq(RA.ceil(5.95), 6);
+    eq(RA.ceil(5.5), 6);
+    eq(RA.ceil(5.05), 6);
+    eq(RA.ceil(-5.05), -5);
+    eq(RA.ceil(-5.5), -5);
+    eq(RA.ceil(-5.95), -5);
+  });
+
+  context('given integer number', function() {
+    specify('should return original integer number', function() {
+      eq(RA.ceil(0), 0);
+      eq(RA.ceil(1), 1);
+      eq(RA.ceil(-1), -1);
+    });
+  });
+
+  context('given value that is not a number', function() {
+    specify('should return NaN', function() {
+      eq(RA.ceil(undefined), NaN);
+      eq(RA.ceil(NaN), NaN);
+      eq(RA.ceil({}), NaN);
+      eq(RA.ceil(/a/), NaN);
+      eq(RA.ceil('test'), NaN);
+      eq(RA.ceil(new Error()), NaN);
+    });
+  });
+
+  context('given null', function() {
+    specify('should return 0', function() {
+      eq(RA.ceil(null), 0);
+    });
+  });
+
+  context('given Symbol value', function() {
+    specify('should throw TypeError', function() {
+      let shouldThrow;
+      try {
+        Math.round(Symbol(''));
+        shouldThrow = false;
+      } catch (e) {
+        shouldThrow = true;
+      }
+
+      if (shouldThrow) {
+        assert.throw(() => RA.ceil(Symbol('')));
+      }
+    });
+  });
+
+  context('given valid date object', function() {
+    specify(
+      'should return the number of milliseconds elapsed since January 1, 1970 00:00:00 UTC',
+      function() {
+        eq(RA.ceil(new Date(2)), 2);
+      }
+    );
+  });
+
+  context('given Infinity value', function() {
+    specify('should return untouched Infinity value', function() {
+      eq(RA.ceil(Infinity), Infinity);
+      eq(RA.ceil(-Infinity), -Infinity);
+    });
+  });
+
+  it('should support placeholder to specify "gaps"', function() {
+    const ceil = RA.ceil(R.__);
+
+    eq(ceil(0.9), 1);
+  });
+});