Skip to content

Commit

Permalink
Merge pull request #3 from yusufshakeel/dev
Browse files Browse the repository at this point in the history
v0.3.0
  • Loading branch information
yusufshakeel authored Mar 10, 2020
2 parents a733920 + 45685c7 commit f61a446
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 17 deletions.
54 changes: 53 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
This is a simple coupon creation project using NodeJS.

[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/yusufshakeel/couponjs)
[![npm version](https://img.shields.io/badge/npm-0.2.0-blue.svg)](https://www.npmjs.com/package/couponjs)
[![npm version](https://img.shields.io/badge/npm-0.3.0-blue.svg)](https://www.npmjs.com/package/couponjs)
[![Build Status](https://travis-ci.com/yusufshakeel/couponjs.svg?branch=master)](https://travis-ci.com/yusufshakeel/couponjs)

# Getting Started
Expand Down Expand Up @@ -41,6 +41,58 @@ const myCoupon = coupon.generate({
```
Where, 8 in the above code represent the total number of characters that will be present in the coupon.

Range of `length`:
* Min: 1
* Max: 128

If length is not passed then default value of 6 is considered.

### Coupon with prefix
To generate a coupon with a given prefix we pass the following option to the `generate` method.
```javascript
const myCoupon = coupon.generate({
prefix: 'SUPER'
});
```
The above code will generate coupon with prefix 'SUPER'. Default lenght of the coupon is 6. So, we will get coupon like the following.

`SUPERAAAAAA`

Note! Prefix characters are not counted.

If we want to generate coupon of length 3 with prefix 'SUPER' then our option will look like the following.
```javascript
const myCoupon = coupon.generate({
length: 3,
prefix: 'SUPER'
});
```
We will get coupon like the following `SUPERAAA`.

### Coupon with suffix
To create coupon with suffix pass the following option.
```javascript
const myCoupon = coupon.generate({
length: 3,
suffix: 'AWESOME'
});
```
The above code will generate coupon like the following `ZZZAWESOME`.

Note! Characters of the suffix is not counted. If length is note specified then default value of 6 is considered as the length.

### Coupon with prefix and suffix
To create coupon with prefix and suffix pass the following option.
```javascript
const myCoupon = coupon.generate({
length: 6,
prefix: 'SUPER',
suffix: 'AWESOME'
});
```
The above code will generate coupon like the following `SUPERZZZZZZAWESOME`.

Note! The characters of the prefix and suffix is not considered. If length is not specified then default value of 6 is considered.

## License
It's free :smiley:
Expand Down
6 changes: 5 additions & 1 deletion app/constants.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/**
* @type {{DEFAULT_LENGTH: number, ALPHABET_UPPERCASE: string}}
* @type {{DEFAULT_LENGTH: number, DEFAULT_PREFIX: string, DEFAULT_SUFFIX: string, ALPHABET_UPPERCASE: string}}
*/
module.exports = {
MAX_LENGTH: 128,
MIN_LENGTH: 1,
DEFAULT_LENGTH: 6,
DEFAULT_PREFIX: '',
DEFAULT_SUFFIX: '',
ALPHABET_UPPERCASE: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
};
32 changes: 26 additions & 6 deletions app/engine.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
const { DEFAULT_LENGTH } = require('./constants.js');
const {MAX_LENGTH, MIN_LENGTH, DEFAULT_LENGTH, DEFAULT_PREFIX, DEFAULT_SUFFIX} = require('./constants.js');
/**
* Engine to produce coupon.
* @param {string} characters This is the set of characters used to generate coupon.
* @param {function} randomInteger This is the function that will generate random integer value.
* @param {number} length This is the length of the coupon.
* @param {number} length This is the length of the coupon excluding prefix and suffix characters if any.
* @param {string} prefix This is the set of characters that is added at the start of the coupon.
* @param {string} suffix This is the set of characters that is added at the end of the coupon.
* @constructor
*/
const Engine = function (characters, randomInteger, length = DEFAULT_LENGTH) {
const Engine = function (characters, randomInteger, length = DEFAULT_LENGTH, prefix = DEFAULT_PREFIX, suffix = DEFAULT_SUFFIX) {

/**
* This will validate options
* @param length
*/
const validate = function ({length}) {
if (length <= MIN_LENGTH) throw new Error(`Minimum value for "length" is ${MIN_LENGTH}.`);
if (length >= MAX_LENGTH) throw new Error(`Maximum value for "length" is ${MAX_LENGTH}.`);
};

/**
* This will return array of characters.
* @returns {string[]}
*/
function characterSet() {
return characters.split('');
}

/**
* This will generate the coupon.
* @returns {string}
*/
function generateCoupon() {
const generatedCouponCharacters = [];
const charSet = characterSet();
for(let i = 0; i < length; i++) {
for (let i = 0; i < length; i++) {
generatedCouponCharacters.push(
charSet[randomInteger(0, length - 1)]
);
Expand All @@ -28,8 +47,9 @@ const Engine = function (characters, randomInteger, length = DEFAULT_LENGTH) {
* @returns {string}
*/
this.run = function () {
return generateCoupon();
}
validate({length});
return `${prefix}${generateCoupon()}${suffix}`;
};
};

module.exports = Engine;
4 changes: 3 additions & 1 deletion app/option.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
const { DEFAULT_LENGTH, ALPHABET_UPPERCASE } = require('./constants.js');
const {DEFAULT_LENGTH, DEFAULT_PREFIX, DEFAULT_SUFFIX, ALPHABET_UPPERCASE} = require('./constants.js');

module.exports = {
length: DEFAULT_LENGTH,
prefix: DEFAULT_PREFIX,
suffix: DEFAULT_SUFFIX,
characters: ALPHABET_UPPERCASE
};
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ const randomInteger = require('./app/random-integer.js');
* @constructor
*/
const Coupon = function () {

/**
* This will generate coupons.
*
* @param {object} option This is the configuration option.
* @returns {string}
*/
this.generate = function (option) {
const { length, characters } = Object.assign(defaultOptions, option);
const engine = new Engine(characters, randomInteger, length);
const {length, characters, prefix, suffix} = Object.assign({}, defaultOptions, option);
const engine = new Engine(characters, randomInteger, length, prefix, suffix);
return engine.run();
};
};
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "couponjs",
"version": "0.2.0",
"version": "0.3.0",
"description": "This is a simple coupon creation project using NodeJS.",
"main": "index.js",
"scripts": {
Expand Down
57 changes: 54 additions & 3 deletions tests/app/engine.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
const Engine = require('../../app/engine.js');

test('Should throw error if length is less than 1', () => {
expect(() => {
const characters = 'A';
const mockRandomInteger = jest.fn((min, max) => {
return 0;
});
const engine = new Engine(characters, mockRandomInteger, 0);
engine.run();
throw new Error('Should have failed.');
}).toThrow('Minimum value for "length" is 1.');
});

test('Should throw error if length is greater than 128', () => {
expect(() => {
const characters = 'A';
const mockRandomInteger = jest.fn((min, max) => {
return 0;
});
const engine = new Engine(characters, mockRandomInteger, 200);
engine.run();
throw new Error('Should have failed.');
}).toThrow('Maximum value for "length" is 128.');
});

test('Should return AAAAAA as coupon when character set is "A" and randomInteger generates always 0', () => {
const characters = "A";
const characters = 'A';
const mockRandomInteger = jest.fn((min, max) => {
return 0;
});
Expand All @@ -10,7 +34,7 @@ test('Should return AAAAAA as coupon when character set is "A" and randomInteger
});

test('Should return zzzzzz as coupon when character set is "z" and randomInteger generates always 0', () => {
const characters = "z";
const characters = 'z';
const mockRandomInteger = jest.fn((min, max) => {
return 0;
});
Expand All @@ -19,10 +43,37 @@ test('Should return zzzzzz as coupon when character set is "z" and randomInteger
});

test('Should return aaa as coupon when character set is "a" and rendomInteger generates always 0 and length is 3', () => {
const characters = "a";
const characters = 'a';
const mockRandomInteger = jest.fn((min, max) => {
return 0;
});
const engine = new Engine(characters, mockRandomInteger, 3);
expect(engine.run()).toBe('aaa');
});

test('Should return PREFIXaaa as coupon when character set is "a" and rendomInteger generates always 0 and length is 3', () => {
const characters = 'a';
const mockRandomInteger = jest.fn((min, max) => {
return 0;
});
const engine = new Engine(characters, mockRandomInteger, 3, 'PREFIX');
expect(engine.run()).toBe('PREFIXaaa');
});

test('Should return aaaSUFFIX as coupon when character set is "a" and rendomInteger generates always 0 and length is 3', () => {
const characters = 'a';
const mockRandomInteger = jest.fn((min, max) => {
return 0;
});
const engine = new Engine(characters, mockRandomInteger, 3, '', 'SUFFIX');
expect(engine.run()).toBe('aaaSUFFIX');
});

test('Should return PREFIXaaaSUFFIX as coupon when character set is "a" and rendomInteger generates always 0 and length is 3', () => {
const characters = 'a';
const mockRandomInteger = jest.fn((min, max) => {
return 0;
});
const engine = new Engine(characters, mockRandomInteger, 3, 'PREFIX', 'SUFFIX');
expect(engine.run()).toBe('PREFIXaaaSUFFIX');
});
60 changes: 59 additions & 1 deletion tests/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,64 @@ test('Should generate coupon code using uppercase alphabet A-Z of length 6.', ()

test('Should generate coupon code using uppercase alphabet A-Z of length 8.', () => {
const coupon = new Coupon();
const result = coupon.generate({ length: 8 });
const result = coupon.generate({length: 8});
expect(/^[A-Z]{8}$/.test(result)).toBeTruthy();
});

test('Should generate coupon code using uppercase alphabet A-Z of length 6,7,8,9,10.', () => {
const coupon = new Coupon();
expect(/^[A-Z]{6}$/.test(coupon.generate({length: 6}))).toBeTruthy();
expect(/^[A-Z]{7}$/.test(coupon.generate({length: 7}))).toBeTruthy();
expect(/^[A-Z]{8}$/.test(coupon.generate({length: 8}))).toBeTruthy();
expect(/^[A-Z]{9}$/.test(coupon.generate({length: 9}))).toBeTruthy();
expect(/^[A-Z]{10}$/.test(coupon.generate({length: 10}))).toBeTruthy();
});

test('Should generate coupon code using uppercase alphabet A-Z of length 6 including prefix "SUPER"', () => {
const coupon = new Coupon();
const result = coupon.generate({length: 6, prefix: 'SUPER'});
expect(/^SUPER[A-Z]{6}$/.test(result)).toBeTruthy();
});

test('Should generate coupon code using uppercase alphabet A-Z of length 6 including prefix "SUPER" and suffix "AWESOME"', () => {
const coupon = new Coupon();
const result = coupon.generate({length: 6, prefix: 'SUPER', suffix: 'AWESOME'});
expect(/^SUPER[A-Z]{6}AWESOME$/.test(result)).toBeTruthy();
});

test('Should generate coupon code using uppercase alphabet A-Z of length 6 including suffix "AWESOME"', () => {
const coupon = new Coupon();
const result = coupon.generate({length: 6, suffix: 'AWESOME'});
expect(/^[A-Z]{6}AWESOME$/.test(result)).toBeTruthy();
});

test('Should generate coupon code using uppercase alphabet A-Z of length 6,7,8,9,10 including prefix "SUPER"', () => {
const coupon = new Coupon();
expect(/^SUPER[A-Z]{6}$/.test(coupon.generate({length: 6, prefix: 'SUPER'}))).toBeTruthy();
expect(/^SUPER[A-Z]{7}$/.test(coupon.generate({length: 7, prefix: 'SUPER'}))).toBeTruthy();
expect(/^SUPER[A-Z]{8}$/.test(coupon.generate({length: 8, prefix: 'SUPER'}))).toBeTruthy();
expect(/^SUPER[A-Z]{9}$/.test(coupon.generate({length: 9, prefix: 'SUPER'}))).toBeTruthy();
expect(/^SUPER[A-Z]{10}$/.test(coupon.generate({length: 10, prefix: 'SUPER'}))).toBeTruthy();
});

test('Should generate coupon code using uppercase alphabet A-Z of length 6,7,8,9,10 including prefix "SUPER" and suffix "AWESOME"', () => {
const coupon = new Coupon();
expect(/^SUPER[A-Z]{6}AWESOME$/.test(coupon.generate({length: 6, prefix: 'SUPER', suffix: 'AWESOME'}))).toBeTruthy();
expect(/^SUPER[A-Z]{7}AWESOME$/.test(coupon.generate({length: 7, prefix: 'SUPER', suffix: 'AWESOME'}))).toBeTruthy();
expect(/^SUPER[A-Z]{8}AWESOME$/.test(coupon.generate({length: 8, prefix: 'SUPER', suffix: 'AWESOME'}))).toBeTruthy();
expect(/^SUPER[A-Z]{9}AWESOME$/.test(coupon.generate({length: 9, prefix: 'SUPER', suffix: 'AWESOME'}))).toBeTruthy();
expect(/^SUPER[A-Z]{10}AWESOME$/.test(coupon.generate({
length: 10,
prefix: 'SUPER',
suffix: 'AWESOME'
}))).toBeTruthy();
});

test('Should generate coupon code using uppercase alphabet A-Z of length 6,7,8,9,10 including suffix "AWESOME"', () => {
const coupon = new Coupon();
expect(/^[A-Z]{6}AWESOME$/.test(coupon.generate({length: 6, suffix: 'AWESOME'}))).toBeTruthy();
expect(/^[A-Z]{7}AWESOME$/.test(coupon.generate({length: 7, suffix: 'AWESOME'}))).toBeTruthy();
expect(/^[A-Z]{8}AWESOME$/.test(coupon.generate({length: 8, suffix: 'AWESOME'}))).toBeTruthy();
expect(/^[A-Z]{9}AWESOME$/.test(coupon.generate({length: 9, suffix: 'AWESOME'}))).toBeTruthy();
expect(/^[A-Z]{10}AWESOME$/.test(coupon.generate({length: 10, suffix: 'AWESOME'}))).toBeTruthy();
});

0 comments on commit f61a446

Please sign in to comment.