Browse Source

chore: improvers filtering by "skip" and "limit" options

e22m4u 2 years ago
parent
commit
6e1184cd35
2 changed files with 96 additions and 55 deletions
  1. 4 4
      src/filter/slice-clause-tool.js
  2. 92 51
      src/filter/slice-clause-tool.spec.js

+ 4 - 4
src/filter/slice-clause-tool.js

@@ -20,12 +20,12 @@ export class SliceClauseTool extends Service {
           'should be an Array, but %v given.',
         entities,
       );
-    if (skip && typeof skip !== 'number')
+    if (skip != null && typeof skip !== 'number')
       throw new InvalidArgumentError(
         'The provided option "skip" should be a Number, but %v given.',
         skip,
       );
-    if (limit && typeof limit !== 'number')
+    if (limit != null && typeof limit !== 'number')
       throw new InvalidArgumentError(
         'The provided option "limit" should be a Number, but %v given.',
         limit,
@@ -41,7 +41,7 @@ export class SliceClauseTool extends Service {
    * @param {number|undefined} skip
    */
   static validateSkipClause(skip) {
-    if (!skip) return;
+    if (skip == null) return;
     if (typeof skip !== 'number')
       throw new InvalidArgumentError(
         'The provided option "skip" should be a Number, but %v given.',
@@ -55,7 +55,7 @@ export class SliceClauseTool extends Service {
    * @param {number|undefined} limit
    */
   static validateLimitClause(limit) {
-    if (!limit) return;
+    if (limit == null) return;
     if (typeof limit !== 'number')
       throw new InvalidArgumentError(
         'The provided option "limit" should be a Number, but %v given.',

+ 92 - 51
src/filter/slice-clause-tool.spec.js

@@ -5,39 +5,100 @@ import {SliceClauseTool} from './slice-clause-tool.js';
 const S = new SliceClauseTool();
 
 describe('SliceClauseTool', function () {
-  describe('filter', function () {
-    it('does nothing if no clauses provided', function () {
+  describe('slice', function () {
+    it('requires the first argument to be an array', function () {
+      const throwable = v => () => S.slice(v);
+      const error = v =>
+        format(
+          'The first argument of SliceClauseTool.slice ' +
+            'should be an Array, but %s given.',
+          v,
+        );
+      expect(throwable('str')).to.throw(error('"str"'));
+      expect(throwable('')).to.throw(error('""'));
+      expect(throwable(10)).to.throw(error('10'));
+      expect(throwable(0)).to.throw(error('0'));
+      expect(throwable(true)).to.throw(error('true'));
+      expect(throwable(false)).to.throw(error('false'));
+      expect(throwable({})).to.throw(error('Object'));
+      expect(throwable(undefined)).to.throw(error('undefined'));
+      expect(throwable(null)).to.throw(error('null'));
+      expect(throwable([{foo: 'bar'}])()).to.be.eql([{foo: 'bar'}]);
+      expect(throwable([])()).to.be.eql([]);
+    });
+
+    it('requires the provided second argument to be a number', function () {
+      const items = [{foo: 'bar'}];
+      const throwable = v => () => S.slice(items, v);
+      const error = v =>
+        format(
+          'The provided option "skip" should be a Number, but %s given.',
+          v,
+        );
+      expect(throwable('str')).to.throw(error('"str"'));
+      expect(throwable('')).to.throw(error('""'));
+      expect(throwable(true)).to.throw(error('true'));
+      expect(throwable(false)).to.throw(error('false'));
+      expect(throwable({})).to.throw(error('Object'));
+      expect(throwable([])).to.throw(error('Array'));
+      expect(throwable(10)()).to.be.eql([]);
+      expect(throwable(0)()).to.be.eql(items);
+      expect(throwable(undefined)()).to.be.eql(items);
+      expect(throwable(null)()).to.be.eql(items);
+    });
+
+    it('requires the provided third argument to be a number', function () {
+      const items = [{foo: 'bar'}];
+      const throwable = v => () => S.slice(items, undefined, v);
+      const error = v =>
+        format(
+          'The provided option "limit" should be a Number, but %s given.',
+          v,
+        );
+      expect(throwable('str')).to.throw(error('"str"'));
+      expect(throwable('')).to.throw(error('""'));
+      expect(throwable(true)).to.throw(error('true'));
+      expect(throwable(false)).to.throw(error('false'));
+      expect(throwable({})).to.throw(error('Object'));
+      expect(throwable([])).to.throw(error('Array'));
+      expect(throwable(10)()).to.be.eql(items);
+      expect(throwable(0)()).to.be.eql(items);
+      expect(throwable(undefined)()).to.be.eql(items);
+      expect(throwable(null)()).to.be.eql(items);
+    });
+
+    it('does nothing if no "skip" and "limit" options provided', function () {
       const objects = [{id: 1}, {id: 2}, {id: 3}];
       const result = S.slice(objects);
       expect(result).to.be.eql(objects);
     });
 
-    it('does nothing if a given skip is zero', function () {
+    it('does nothing if the given "skip" option is zero', function () {
       const objects = [{id: 1}, {id: 2}, {id: 3}];
       const result = S.slice(objects, 0);
       expect(result).to.be.eql(objects);
     });
 
-    it('uses a given skip to exclude array elements from start', function () {
+    it('uses the given "skip" option to exclude array elements from start', function () {
       const objects = [{id: 1}, {id: 2}, {id: 3}];
       const result = S.slice(objects, 2);
       expect(result).to.have.length(1);
       expect(result[0]).to.be.eql(objects[2]);
     });
 
-    it('returns an empty array if skipping too much', function () {
+    it('returns an empty array when "skip" option overflows a size of the given array ', function () {
       const objects = [{id: 1}, {id: 2}, {id: 3}];
       const result = S.slice(objects, 10);
       expect(result).to.have.length(0);
     });
 
-    it('does nothing if a given limit is zero', function () {
+    it('does nothing if the given "limit" option is zero', function () {
       const objects = [{id: 1}, {id: 2}, {id: 3}];
       const result = S.slice(objects, undefined, 0);
       expect(result).to.be.eql(objects);
     });
 
-    it('uses a given limit to trim a given array', function () {
+    it('uses the given "limit" option to trim the given array', function () {
       const objects = [{id: 1}, {id: 2}, {id: 3}];
       const result = S.slice(objects, undefined, 2);
       expect(result).to.have.length(2);
@@ -45,73 +106,53 @@ describe('SliceClauseTool', function () {
       expect(result[1]).to.be.eql(objects[1]);
     });
 
-    it('able to combine a skip and a limit option together', function () {
+    it('uses the "skip" and "limit" options to slice the given array', function () {
       const objects = [{id: 1}, {id: 2}, {id: 3}];
       const result = S.slice(objects, 1, 1);
       expect(result).to.have.length(1);
       expect(result[0]).to.be.eql(objects[1]);
     });
-
-    it('throws an error if a first argument is not an array', function () {
-      const throwable = () => S.slice(10);
-      expect(throwable).to.throw(
-        'The first argument of SliceClauseTool.slice ' +
-          'should be an Array, but 10 given.',
-      );
-    });
-
-    it('throws an error if the given "skip" option is not a number', function () {
-      const throwable = () => S.slice([], 'invalid');
-      expect(throwable).to.throw(
-        'The provided option "skip" should be a Number, but "invalid" given.',
-      );
-    });
-
-    it('throws an error if the given "limit" option is not a number', function () {
-      const throwable = () => S.slice([], undefined, 'invalid');
-      expect(throwable).to.throw(
-        'The provided option "limit" should be a Number, but "invalid" given.',
-      );
-    });
   });
 
   describe('validateSkipClause', function () {
-    it('requires a number value or a falsy value', function () {
-      const validate = v => () => SliceClauseTool.validateSkipClause(v);
+    it('requires a number value', function () {
+      const throwable = v => () => SliceClauseTool.validateSkipClause(v);
       const error = v =>
         format(
           'The provided option "skip" should be a Number, but %s given.',
           v,
         );
-      expect(validate('str')).to.throw(error('"str"'));
-      expect(validate(true)).to.throw(error('true'));
-      expect(validate([])).to.throw(error('Array'));
-      validate('')();
-      validate(false)();
-      validate(undefined)();
-      validate(null)();
-      validate(10)();
-      validate(0)();
+      expect(throwable('str')).to.throw(error('"str"'));
+      expect(throwable('')).to.throw(error('""'));
+      expect(throwable(true)).to.throw(error('true'));
+      expect(throwable(false)).to.throw(error('false'));
+      expect(throwable({})).to.throw(error('Object'));
+      expect(throwable([])).to.throw(error('Array'));
+      throwable(10)();
+      throwable(0)();
+      throwable(undefined)();
+      throwable(null)();
     });
   });
 
   describe('validateLimitClause', function () {
     it('requires a number value or a falsy value', function () {
-      const validate = v => () => SliceClauseTool.validateLimitClause(v);
+      const throwable = v => () => SliceClauseTool.validateLimitClause(v);
       const error = v =>
         format(
           'The provided option "limit" should be a Number, but %s given.',
           v,
         );
-      expect(validate('str')).to.throw(error('"str"'));
-      expect(validate(true)).to.throw(error('true'));
-      expect(validate([])).to.throw(error('Array'));
-      validate('')();
-      validate(false)();
-      validate(undefined)();
-      validate(null)();
-      validate(10)();
-      validate(0)();
+      expect(throwable('str')).to.throw(error('"str"'));
+      expect(throwable('')).to.throw(error('""'));
+      expect(throwable(true)).to.throw(error('true'));
+      expect(throwable(false)).to.throw(error('false'));
+      expect(throwable({})).to.throw(error('Object'));
+      expect(throwable([])).to.throw(error('Array'));
+      throwable(10)();
+      throwable(0)();
+      throwable(undefined)();
+      throwable(null)();
     });
   });
 });