Skip to content

Commit

Permalink
[LP-37] - Added support for suffixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
tabuckner committed Oct 3, 2019
1 parent 650e2f3 commit c592da3
Show file tree
Hide file tree
Showing 20 changed files with 316 additions and 135 deletions.
4 changes: 2 additions & 2 deletions examples/browser/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
<script src="../../dist/doggo-translator-ts.min.js"></script>
<script>

const myTranslator = new DTT.DoggoTranslator({ userTranslationsMap: { hey: 'hi', friend: 'frenn', run: 'floop' } });
const text = 'Hey friend, do you want to go for a run?'
const myTranslator = new DTT.DoggoTranslator({ userTranslationsMap: { words: { hey: 'hi', friend: 'frenn', run: 'floop' } }, suffixes: { ing: 'in' } });
const text = 'Hey friend, do you want to go for a run? I like running too!'
const translated = myTranslator.translateSentence(text)
document.querySelector('#text').innerHTML = text;
document.querySelector('#translated').innerHTML = translated;
Expand Down
33 changes: 22 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,29 @@
"node": ">=6.0.0"
},
"scripts": {
"lint": "tslint --project tsconfig.json -t codeFrame 'src/**/*.ts' 'test/**/*.ts'",
"build": "yarn build:ts && yarn build:rollup && yarn build:docs",
"build:docs": "typedoc --tsconfig './tsconfig.src.json' --exclude **/*.spec.ts --out docs --target es6 --theme minimal --mode file src",
"build:rollup": "yarn rollup",
"build:ts": "tsc --project tsconfig.prod.json",
"commit": "git-cz",
"deploy-docs": "ts-node tools/gh-pages-publish --exclude 'src/**/*.spec.ts'",
"lint": "yarn lint:src && yarn lint:spec",
"lint:fix": "yarn lint:src:fix && yarn lint:spec:fix",
"lint:src": "tslint --project tsconfig.src.json -t codeFrame 'src/**/*.ts'",
"lint:src:fix": "tslint --project tsconfig.src.json -t codeFrame 'src/**/*.ts' --fix",
"lint:spec": "tslint --project tsconfig.spec.json -t codeFrame 'src/**/*.ts' 'test/**/*.ts'",
"lint:spec:fix": "tslint --project tsconfig.spec.json -t codeFrame 'src/**/*.ts' 'test/**/*.ts' --fix",
"prebuild": "rimraf dist",
"build": "tsc --module commonjs && rollup -c rollup.config.ts && typedoc --out docs --target es6 --theme minimal --mode file src",
"start": "rollup -c rollup.config.ts -w",
"test": "jest --coverage",
"test:watch": "jest --coverage --watch",
"test:prod": "npm run lint && npm run test -- --no-cache",
"deploy-docs": "ts-node tools/gh-pages-publish",
"precommit": "lint-staged",
"report-coverage": "cat ./coverage/lcov.info | coveralls",
"commit": "git-cz",
"rollup": "rollup -c rollup.config.ts",
"rollup:watch": "yarn rollup --watch",
"semantic-release": "semantic-release",
"semantic-release-prepare": "ts-node tools/semantic-release-prepare",
"precommit": "lint-staged",
"start": "rollup:watch",
"test": "jest --coverage",
"test:prod": "npm run lint && npm run test -- --no-cache",
"test:watch": "jest --coverage --watchAll",
"travis-deploy-once": "travis-deploy-once"
},
"lint-staged": {
Expand Down Expand Up @@ -72,14 +82,15 @@
],
"coverageThreshold": {
"global": {
"branches": 90,
"branches": 87,
"functions": 95,
"lines": 95,
"statements": 95
}
},
"collectCoverageFrom": [
"src/**/*.{js,ts}"
"src/**/*.{js,ts}",
"!src/i18n/locales/**/*.ts"
]
},
"prettier": {
Expand Down
2 changes: 1 addition & 1 deletion rollup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default {
// Allow json resolution
json(),
// Compile TypeScript files
typescript({ useTsconfigDeclarationDir: true }),
typescript({ useTsconfigDeclarationDir: true, tsconfig: './tsconfig.src.json' }),
// Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs)
commonjs(),
// Allow node_modules resolution, so you can use 'external' to control
Expand Down
3 changes: 2 additions & 1 deletion src/doggo-translator-ts/doggo-translator-config.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { LANGUAGE_TOKENS_ENUM } from '../i18n';
import { TranslationMapInterface } from '../i18n/models/translation.model';

export interface DoggoTranslatorConfig {
languageToken?: LANGUAGE_TOKENS_ENUM;
userTranslationsMap?: { [key: string]: string };
userTranslationsMap?: TranslationMapInterface;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { DoggoTranslator, LANGUAGE_TOKENS_ENUM } from '../index';
import { TokensService } from '../i18n';
import { ErrorService } from '../util/error.service';
import { DoggoTranslatorConfig } from './doggo-translator-config.interface';
import { TranslationMapInterface } from '../i18n/models/translation.model';

/**
* DoggoTranslator
Expand Down Expand Up @@ -37,35 +38,36 @@ describe('DoggoTranslator', () => {
expect(instance['localeLoaderService'].getTranslationsMap).toHaveBeenCalled();
});

it('should be able to translate english => doggo', () => {
const mockLanguageFile = { barking: 'borking' };
it('should delegate to whole words method', () => {
const mockLanguageFile: TranslationMapInterface = { words: { barking: 'borking' } };
spyOnPrivate(instance['localeLoaderService'], 'getTranslationsMap').and.returnValue(
mockLanguageFile
);
spyOnPrivate(instance, 'translateSingleEntry').and.returnValue(true);
const mockLanguageKey = Object.keys(mockLanguageFile)[0];
const input = mockLanguageKey;
instance.translateSentence(input);
expect(instance['translateSingleEntry']).toHaveBeenCalledWith(
input,
mockLanguageKey,
mockLanguageFile.barking
spyOnPrivate(instance, 'replaceWholeWords').and.returnValue(true);
const mockInput = 'testing sentence';
instance.translateSentence(mockInput, true);
expect(instance['replaceWholeWords']).toHaveBeenCalledWith(
mockLanguageFile.words,
true,
mockInput
);
});

it('should be able to translate english => doggo', () => {
const mockLanguageFile = { barking: 'borking' };
it('should delegate to suffixes method', () => {
const mockLanguageFile: TranslationMapInterface = {
words: { barking: 'borking' },
suffixes: { ing: 'in' }
};
spyOnPrivate(instance['localeLoaderService'], 'getTranslationsMap').and.returnValue(
mockLanguageFile
);
spyOnPrivate(instance, 'translateSingleEntry').and.returnValue(true);
const mockLanguageKey = Object.keys(mockLanguageFile)[0];
const input = mockLanguageKey;
instance.translateSentence(input, true);
expect(instance['translateSingleEntry']).toHaveBeenCalledWith(
input,
mockLanguageFile.barking,
mockLanguageKey
spyOnPrivate(instance, 'replaceSuffixes').and.returnValue(true);
const mockInput = 'testing sentence';
instance.translateSentence(mockInput, true);
expect(instance['replaceSuffixes']).toHaveBeenCalledWith(
mockLanguageFile.suffixes,
true,
mockInput
);
});
});
Expand Down Expand Up @@ -127,7 +129,9 @@ describe('DoggoTranslator', () => {
it('should allow user defined translation maps', () => {
spyOn(instance, 'setLanguage').and.returnValue(true);
spyOnPrivate(instance['localeLoaderService'], 'setTranslationsMap').and.returnValue(true);
const mockConfig: DoggoTranslatorConfig = { userTranslationsMap: { test: 'true' } };
const mockConfig: DoggoTranslatorConfig = {
userTranslationsMap: { words: { test: 'true' } }
};
instance['setUpTranslator'](mockConfig);
expect(instance.setLanguage).toHaveBeenCalledWith(LANGUAGE_TOKENS_ENUM.userDefined);
expect(instance['localeLoaderService'].setTranslationsMap).toHaveBeenCalledWith(
Expand All @@ -144,26 +148,82 @@ describe('DoggoTranslator', () => {
});
});

describe('#translateSingleEntry', () => {
describe('#replaceWholeWords', () => {
const mockLanguageFile: TranslationMapInterface = { words: { barking: 'borking' } };
const mockLanguageKey = Object.keys(mockLanguageFile.words)[0];
const input = mockLanguageKey;

beforeEach(() => {
spyOnPrivate(instance, 'translateWholeWord').and.returnValue(true);
});

it('should delegate whole words from english => doggo to #translateWholeWord', () => {
instance['replaceWholeWords'](mockLanguageFile.words, false, input);
expect(instance['translateWholeWord']).toHaveBeenCalledWith(
input,
mockLanguageKey,
mockLanguageFile.words.barking
);
});

it('should delegate whole words from doggo => english to #translateWholeWord', () => {
instance['replaceWholeWords'](mockLanguageFile.words, true, input);
expect(instance['translateWholeWord']).toHaveBeenCalledWith(
input,
mockLanguageFile.words.barking,
mockLanguageKey
);
});
});

describe('#replaceSuffixes', () => {
const mockSuffixes = { ing: 'in' };
const mockLanguageKey = Object.keys(mockSuffixes)[0];
const input = mockLanguageKey;

beforeEach(() => {
spyOnPrivate(instance, 'transformSuffixes').and.returnValue(true);
});

it('should delegate whole words from english => doggo to #transformSuffixes', () => {
instance['replaceSuffixes'](mockSuffixes, false, input);
expect(instance['transformSuffixes']).toHaveBeenCalledWith(
input,
mockLanguageKey,
mockSuffixes.ing
);
});

it('should delegate whole words from doggo => english to #transformSuffixes', () => {
instance['replaceSuffixes'](mockSuffixes, true, input);
expect(instance['transformSuffixes']).toHaveBeenCalledWith(
input,
mockSuffixes.ing,
mockLanguageKey
);
});
});

describe('#translateWholeWord', () => {
const mockInput = 'testing string test';
const mockRegex = 'string';
const mockReplacement = 'test';

it('should escape input regex', () => {
spyOnPrivate(instance, 'escapeRegex').and.returnValue(true);
instance['translateSingleEntry'](mockInput, mockRegex, mockReplacement);
instance['translateWholeWord'](mockInput, mockRegex, mockReplacement);
expect(instance['escapeRegex']).toHaveBeenCalled();
});

it('should use string.replace', () => {
spyOn(String.prototype, 'replace').and.callThrough();
instance['translateSingleEntry'](mockInput, mockRegex, mockReplacement);
instance['translateWholeWord'](mockInput, mockRegex, mockReplacement);
expect(mockInput.replace).toHaveBeenCalled();
});

it('should handle all caps', () => {
spyOn(String.prototype, 'replace').and.callThrough();
const testEval = instance['translateSingleEntry'](
const testEval = instance['translateWholeWord'](
mockInput.toUpperCase(),
mockRegex,
mockReplacement
Expand All @@ -173,11 +233,44 @@ describe('DoggoTranslator', () => {

it('should handle capitalized words', () => {
const localMockInput = 'Testing';
const testEval = instance['translateSingleEntry'](localMockInput, 'testing', mockReplacement);
const testEval = instance['translateWholeWord'](localMockInput, 'testing', mockReplacement);
expect(testEval).toBe('Test');
});
});

describe('#transformSuffixes', () => {
const mockInput = 'Running Jumping and Swimming.';
const mockRegex = 'ing';
const mockReplacement = 'in';

it('should escape input regex', () => {
spyOnPrivate(instance, 'escapeRegex').and.returnValue(true);
instance['transformSuffixes'](mockInput, mockRegex, mockReplacement);
expect(instance['escapeRegex']).toHaveBeenCalled();
});

it('should use string.replace', () => {
spyOn(String.prototype, 'replace').and.callThrough();
instance['transformSuffixes'](mockInput, mockRegex, mockReplacement);
expect(mockInput.replace).toHaveBeenCalled();
});

it('should handle all caps', () => {
spyOn(String.prototype, 'replace').and.callThrough();
const testEval = instance['transformSuffixes'](
mockInput.toUpperCase(),
mockRegex,
mockReplacement
);
expect(testEval).toBe(testEval.toUpperCase());
});

it('should replace suffixes of words in place', () => {
const testEval = instance['transformSuffixes'](mockInput, mockRegex, mockReplacement);
expect(testEval).toBe('Runnin Jumpin and Swimmin.');
});
});

describe('#capitalizeFirstCharacter', () => {
it('should do that...', () => {
const mockInput = 'testing';
Expand Down
Loading

0 comments on commit c592da3

Please sign in to comment.