diff --git a/lib/RateLimiterStoreAbstract.js b/lib/RateLimiterStoreAbstract.js index 8a2cd48..94f882a 100644 --- a/lib/RateLimiterStoreAbstract.js +++ b/lib/RateLimiterStoreAbstract.js @@ -192,7 +192,17 @@ module.exports = class RateLimiterStoreAbstract extends RateLimiterAbstract { * @returns Promise */ consume(key, pointsToConsume = 1, options = {}) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { + if( + typeof pointsToConsume == 'string' + ){ + if(!RegExp("^[1-9][0-9]*$").test(pointsToConsume)){ + reject(new Error("Consuming string different than integer values is not supported by this package")); + } + } else if (!Number.isInteger(pointsToConsume)){ + reject(new Error("Consuming decimal number of points is not supported by this package")); + } + const rlKey = this.getKey(key); const inMemoryBlockMsBeforeExpire = this.getInMemoryBlockMsBeforeExpire(rlKey); diff --git a/test/RateLimiterRedis.ioredis.test.js b/test/RateLimiterRedis.ioredis.test.js index 44d0e87..96e0ab8 100644 --- a/test/RateLimiterRedis.ioredis.test.js +++ b/test/RateLimiterRedis.ioredis.test.js @@ -153,6 +153,91 @@ describe('RateLimiterRedis with fixed window', function RateLimiterRedisTest() { }); }); + describe('when points are passed as decimal numbers', () => { + it('thows error', (done) => { + const testKey = 'consume2'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 1, + duration: 5 + }); + + rateLimiter + .consume(testKey, 1.1) + .then(() => { + done(new Error('must not')); + }) + .catch((err) => { + expect(err.message).to.equal('Consuming decimal number of points is not supported by this package') + done(); + }); + }); + }); + + describe('when passing points as float without decimal values', () => { + it('does not throw an error', (done) => { + const testKey = 'consume1'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 3, + duration: 5, + }); + rateLimiter + .consume(testKey, 2.0) + .then(() => { + redisMockClient.get(rateLimiter.getKey(testKey)).then((consumedPoints)=>{ + expect(consumedPoints).to.equal('2'); + done(); + }); + }) + .catch((err) => { + done(err); + }); + }); + }); + + describe('when passing points as string with decimal values', () => { + it('throws error', (done) => { + const testKey = 'consume1'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 3, + duration: 5, + }); + rateLimiter + .consume(testKey, "2.0") + .then(() => { + done(new Error('must not')); + }) + .catch((err) => { + expect(err.message).to.equal('Consuming string different than integer values is not supported by this package') + done(); + }); + }); + }); + + describe('when passing points as string without decimal values', () => { + it('does not throw an error', (done) => { + const testKey = 'consume1'; + const rateLimiter = new RateLimiterRedis({ + storeClient: redisMockClient, + points: 3, + duration: 5, + }); + rateLimiter + .consume(testKey, "2") + .then(() => { + redisMockClient.get(rateLimiter.getKey(testKey)).then((consumedPoints)=>{ + expect(consumedPoints).to.equal('2'); + done(); + }); + }) + .catch((err) => { + done(err); + }); + }); + }); + it('execute evenly over duration', (done) => { const testKey = 'consumeEvenly'; const rateLimiter = new RateLimiterRedis({