Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor and add new languages #526

Merged
merged 5 commits into from
Sep 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module.exports = {
ecmaVersion: 2018,
sourceType: 'module',
},
plugins: ['@typescript-eslint', 'jest'],
plugins: ['@typescript-eslint', 'jest', 'import'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [3.0.0-alpha.0](https://github.com/mastermunj/to-words/compare/v2.5.0...v3.0.0-alpha.0) (2021-09-04)


### Features

* refactor and new languages ([ec68e6c](https://github.com/mastermunj/to-words/commit/ec68e6c35a1d9d2ad68a6dd741cb71682681ed79))


### Bug Fixes

* remove default class export to keep import syntax same ([bc15df6](https://github.com/mastermunj/to-words/commit/bc15df67836750a010531281f39ff21d5e79773c))
* resolve rebase issue ([2d175f2](https://github.com/mastermunj/to-words/commit/2d175f2d6f8a9f088ed1679817ee29298164bed1))

## [2.5.0](https://github.com/mastermunj/to-words/compare/v2.4.0...v2.5.0) (2021-08-24)

## [2.4.0](https://github.com/mastermunj/to-words/compare/v2.3.2...v2.4.0) (2021-08-06)
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const toWords = new ToWords({
currency: true,
ignoreDecimal: false,
ignoreZeroCurrency: false,
doNotAddOnly: false,
}
});
```
Expand Down Expand Up @@ -88,10 +89,12 @@ let words = toWords.convert(0.572, { currency: true, ignoreZeroCurrency: true })
| currency | boolean | false | Whether the number to be converted into words written as currency.<br/>*Note: When currency:true, number will be rounded off to two decimals before converting to words* |
| ignoreDecimal | boolean | false | Whether to ignore fractional unit of number while converting into words. |
| ignoreZeroCurrency | boolean | false | Whether to ignore zero currency value while converting into words. |
| doNotAddOnly | boolean | false | Do not add `only` at the end of the words. This works only when currency = true |

## Supported Locale
| Country | Language | Locale |
| ------------- | ------------- | ------------- |
| Ghana | English | en-GH |
| India | English | en-IN (default) |
| Myanmar | English | en-MM |
| Mauritius | English | en-MU |
Expand All @@ -100,6 +103,9 @@ let words = toWords.convert(0.572, { currency: true, ignoreZeroCurrency: true })
| USA | English | en-US |
| Iran | Persian | fa-IR |
| France | French | fr-FR |
| India | Gujarati | gu-IN |
| India | Hindi | hi-IN |
| India | Marathi | mr-IN |

## Inspiration for core logic
[https://stackoverflow.com/a/46221860](https://stackoverflow.com/a/46221860)
8 changes: 4 additions & 4 deletions __tests__/to-words.test.ts → __tests__/ToWords.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ToWords } from '../src/to-words';
import { ToWords } from '../src/ToWords';

describe('Wrong Locale', () => {
const localeCode = 'en-INDIA';
const toWords = new ToWords({
localeCode: localeCode,
});
test(`With Locale: ${localeCode}`, () => {
expect(() => toWords.convert(1)).toThrow(/Unknown Locale /);
expect(() => toWords.convert(1)).toThrow(/Unknown Locale/);
});
});

Expand All @@ -24,7 +24,7 @@ describe('Test Wrong Inputs', () => {
Number.NEGATIVE_INFINITY,
];

test.each(testWrongInputs)('test input %s', (input) => {
expect(() => toWords.convert(input as number)).toThrow();
test.concurrent.each(testWrongInputs)('test input %s', (input) => {
expect(() => toWords.convert(input as number)).toThrow(/Invalid Number/);
});
});
198 changes: 124 additions & 74 deletions __tests__/en-GH.test.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
import { ToWords } from '../src/to-words';
import cloneDeep from 'lodash/cloneDeep';
import { cloneDeep } from 'lodash';
import { ToWords } from '../src/ToWords';
import enGh from '../src/locales/en-GH';

const localeCode = 'en-GH';
const toWords = new ToWords({
localeCode: 'en-GH',
localeCode,
});

describe('Test Locale', () => {
test(`Locale Class: ${localeCode}`, () => {
expect(toWords.getLocaleClass()).toBe(enGh);
});

const wrongLocaleCode = localeCode + '-wrong';
test(`Wrong Locale: ${wrongLocaleCode}`, () => {
const toWordsWrongLocale = new ToWords({
localeCode: wrongLocaleCode,
});
expect(() => toWordsWrongLocale.convert(1)).toThrow(/Unknown Locale/);
});
});

const testIntegers = [
[0, 'Zero'],
[137, 'One Hundred Thirty Seven'],
[700, 'Seven Hundred'],
[1100, 'One Thousand One Hundred'],
[4680, 'Four Thousand Six Hundred Eighty'],
[63892, 'Sixty Three Thousand Eight Hundred Ninety Two'],
[86100, 'Eighty Six Thousand One Hundred'],
[792581, 'Seven Hundred Ninety Two Thousand Five Hundred Eighty One'],
[2741034, 'Two Million Seven Hundred Forty One Thousand Thirty Four'],
[86429753, 'Eighty Six Million Four Hundred Twenty Nine Thousand Seven Hundred Fifty Three'],
Expand All @@ -35,42 +53,71 @@ const testIntegers = [
];

describe('Test Integers with options = {}', () => {
test.each(testIntegers)('convert %d => %s', (input, expected) => {
test.concurrent.each(testIntegers)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number)).toBe(expected);
});
});

const testNegativeIntegers = cloneDeep(testIntegers);
testNegativeIntegers.map((row, i) => {
if (i === 0) {
return;
}
row[0] = -row[0];
row[1] = `Minus ${row[1]}`;
});

describe('Test Negative Integers with options = {}', () => {
test.each(testNegativeIntegers)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number)).toBe(expected);
const testNegativeIntegers = cloneDeep(testIntegers);
testNegativeIntegers.map((row, i) => {
if (i === 0) {
return;
}
row[0] = -row[0];
row[1] = `Minus ${row[1]}`;
});
});

const testIntegersWithCurrency = cloneDeep(testIntegers);
testIntegersWithCurrency.map((row) => {
row[1] = `${row[1]} Cedis Only`;
test.concurrent.each(testNegativeIntegers)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number)).toBe(expected);
});
});

describe('Test Integers with options = { currency: true }', () => {
test.each(testIntegersWithCurrency)('convert %d => %s', (input, expected) => {
const testIntegersWithCurrency = cloneDeep(testIntegers);
testIntegersWithCurrency.map((row) => {
row[1] = `${row[1]} Cedis Only`;
});

test.concurrent.each(testIntegersWithCurrency)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true })).toBe(expected);
});
});

const testIntegersWithCurrencyAndIgnoreZeroCurrency = cloneDeep(testIntegersWithCurrency);
testIntegersWithCurrencyAndIgnoreZeroCurrency[0][1] = '';
describe('Test Integers with options = { currency: true, doNotAddOnly: true }', () => {
const testIntegersWithCurrency = cloneDeep(testIntegers);
testIntegersWithCurrency.map((row) => {
row[1] = `${row[1]} Cedis`;
});

test.concurrent.each(testIntegersWithCurrency)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true, doNotAddOnly: true })).toBe(expected);
});
});

describe('Test Negative Integers with options = { currency: true }', () => {
const testNegativeIntegersWithCurrency = cloneDeep(testIntegers);
testNegativeIntegersWithCurrency.map((row, i) => {
if (i === 0) {
row[1] = `${row[1]} Cedis Only`;
return;
}
row[0] = -row[0];
row[1] = `Minus ${row[1]} Cedis Only`;
});

test.concurrent.each(testNegativeIntegersWithCurrency)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true })).toBe(expected);
});
});

describe('Test Integers with options = { currency: true, ignoreZeroCurrency: true }', () => {
test.each(testIntegersWithCurrencyAndIgnoreZeroCurrency)('convert %d => %s', (input, expected) => {
const testIntegersWithCurrencyAndIgnoreZeroCurrency = cloneDeep(testIntegers);
testIntegersWithCurrencyAndIgnoreZeroCurrency.map((row, i) => {
row[1] = i === 0 ? '' : `${row[1]} Cedis Only`;
});

test.concurrent.each(testIntegersWithCurrencyAndIgnoreZeroCurrency)('convert %d => %s', (input, expected) => {
expect(
toWords.convert(input as number, {
currency: true,
Expand All @@ -95,45 +142,45 @@ const testFloats = [
];

describe('Test Floats with options = {}', () => {
test.each(testFloats)('convert %d => %s', (input, expected) => {
test.concurrent.each(testFloats)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number)).toBe(expected);
});
});

const testFloatsWithCurrency = [
[0.0, `Zero Cedis Only`],
[0.04, `Zero Cedis And Four Pasewas Only`],
[0.0468, `Zero Cedis And Five Pasewas Only`],
[0.4, `Zero Cedis And Forty Pasewas Only`],
[0.63, `Zero Cedis And Sixty Three Pasewas Only`],
[0.973, `Zero Cedis And Ninety Seven Pasewas Only`],
[0.04, `Zero Cedis And Four Pesewas Only`],
[0.0468, `Zero Cedis And Five Pesewas Only`],
[0.4, `Zero Cedis And Forty Pesewas Only`],
[0.63, `Zero Cedis And Sixty Three Pesewas Only`],
[0.973, `Zero Cedis And Ninety Seven Pesewas Only`],
[0.999, `One Cedis Only`],
[37.06, `Thirty Seven Cedis And Six Pasewas Only`],
[37.068, `Thirty Seven Cedis And Seven Pasewas Only`],
[37.68, `Thirty Seven Cedis And Sixty Eight Pasewas Only`],
[37.683, `Thirty Seven Cedis And Sixty Eight Pasewas Only`],
[37.06, `Thirty Seven Cedis And Six Pesewas Only`],
[37.068, `Thirty Seven Cedis And Seven Pesewas Only`],
[37.68, `Thirty Seven Cedis And Sixty Eight Pesewas Only`],
[37.683, `Thirty Seven Cedis And Sixty Eight Pesewas Only`],
];

describe('Test Floats with options = { currency: true }', () => {
test.each(testFloatsWithCurrency)('convert %d => %s', (input, expected) => {
test.concurrent.each(testFloatsWithCurrency)('convert %d => %s', (input, expected) => {
expect(toWords.convert(input as number, { currency: true })).toBe(expected);
});
});

const testFloatsWithCurrencyAndIgnoreZeroCurrency = cloneDeep(testFloatsWithCurrency);
testFloatsWithCurrencyAndIgnoreZeroCurrency[0][1] = '';
testFloatsWithCurrencyAndIgnoreZeroCurrency.map((row, i) => {
if (i === 0) {
row[1] = '';
return;
}
if (row[0] > 0 && row[0] < 1) {
row[1] = (row[1] as string).replace(`Zero Cedis And `, '');
}
});

describe('Test Floats with options = { currency: true, ignoreZeroCurrency: true }', () => {
test.each(testFloatsWithCurrencyAndIgnoreZeroCurrency)('convert %d => %s', (input, expected) => {
const testFloatsWithCurrencyAndIgnoreZeroCurrency = cloneDeep(testFloatsWithCurrency);
testFloatsWithCurrencyAndIgnoreZeroCurrency[0][1] = '';
testFloatsWithCurrencyAndIgnoreZeroCurrency.map((row, i) => {
if (i === 0) {
row[1] = '';
return;
}
if (row[0] > 0 && row[0] < 1) {
row[1] = (row[1] as string).replace(`Zero Cedis And `, '');
}
});

test.concurrent.each(testFloatsWithCurrencyAndIgnoreZeroCurrency)('convert %d => %s', (input, expected) => {
expect(
toWords.convert(input as number, {
currency: true,
Expand All @@ -143,17 +190,17 @@ describe('Test Floats with options = { currency: true, ignoreZeroCurrency: true
});
});

const testFloatsWithCurrencyAndIgnoreDecimal = cloneDeep(testFloatsWithCurrency);
testFloatsWithCurrencyAndIgnoreDecimal.map((row) => {
if (row[0] === 0.999) {
row[1] = `Zero Cedis Only`;
} else {
row[1] = (row[1] as string).replace(new RegExp(` And [\\w ]+ Pasewas`), '');
}
});

describe('Test Floats with options = { currency: true, ignoreDecimal: true }', () => {
test.each(testFloatsWithCurrencyAndIgnoreDecimal)('convert %d => %s', (input, expected) => {
const testFloatsWithCurrencyAndIgnoreDecimal = cloneDeep(testFloatsWithCurrency);
testFloatsWithCurrencyAndIgnoreDecimal.map((row) => {
if (row[0] === 0.999) {
row[1] = `Zero Cedis Only`;
} else {
row[1] = (row[1] as string).replace(new RegExp(` And [\\w ]+ Pesewas`), '');
}
});

test.concurrent.each(testFloatsWithCurrencyAndIgnoreDecimal)('convert %d => %s', (input, expected) => {
expect(
toWords.convert(input as number, {
currency: true,
Expand All @@ -163,23 +210,26 @@ describe('Test Floats with options = { currency: true, ignoreDecimal: true }', (
});
});

const testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals = cloneDeep(testFloatsWithCurrency);
testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals[0][1] = '';
testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals.map((row) => {
if (row[0] > 0 && row[0] < 1) {
row[1] = '';
}
row[1] = (row[1] as string).replace(new RegExp(` And [\\w ]+ Pasewas`), '');
});

describe('Test Floats with options = { currency: true, ignoreZeroCurrency: true, ignoreDecimal: true }', () => {
test.each(testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals)('convert %d => %s', (input, expected) => {
expect(
toWords.convert(input as number, {
currency: true,
ignoreZeroCurrency: true,
ignoreDecimal: true,
}),
).toBe(expected);
const testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals = cloneDeep(testFloatsWithCurrency);
testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals[0][1] = '';
testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals.map((row) => {
if (row[0] > 0 && row[0] < 1) {
row[1] = '';
}
row[1] = (row[1] as string).replace(new RegExp(` And [\\w ]+ Pesewas`), '');
});

test.concurrent.each(testFloatsWithCurrencyAndIgnoreZeroCurrencyAndIgnoreDecimals)(
'convert %d => %s',
(input, expected) => {
expect(
toWords.convert(input as number, {
currency: true,
ignoreZeroCurrency: true,
ignoreDecimal: true,
}),
).toBe(expected);
},
);
});
Loading