Skip to content

Commit

Permalink
feat: add kanji, kana and japanese validators
Browse files Browse the repository at this point in the history
  • Loading branch information
arjunvegda committed Feb 7, 2022
1 parent c6b2a3c commit 29027ce
Show file tree
Hide file tree
Showing 31 changed files with 1,149 additions and 3 deletions.
41 changes: 41 additions & 0 deletions __tests__/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { UnicodeRange } from '../src';

export const MockKatakanaRange: UnicodeRange = {
start: '\u30a0',
end: '\u30ff',
};

export const MockKatakanaPhoneticExtensionRange: UnicodeRange = {
start: '\u31f0',
end: '\u31FF',
};

export const MockHiraganaRange: UnicodeRange = {
start: '\u3040',
end: '\u309f',
};

export const MockRareKanjiRange: UnicodeRange = {
start: '\u3400',
end: '\u4dbf',
};

export const MockCJKPunctuationsRange: UnicodeRange = {
start: '\u3000',
end: '\u303f',
};

export const MockKanjiCompatibilityIdeographsRange: UnicodeRange = {
start: '\uf900',
end: '\ufaff',
};

export const MockCommonUncommonKanjiRange: UnicodeRange = {
start: '\u4e00',
end: '\u9fdf',
};

export const MockRomanHalfwidthKatakanaRange: UnicodeRange = {
start: '\uff00',
end: '\uffef',
};
134 changes: 134 additions & 0 deletions __tests__/create-match-score-calculator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { CharacterSet, createMatchScoreCalculator, CreateValidatorOptions } from '../src';
import {
escapeUnicode,
escapeUnicodeRange,
generateCharactersFromRange,
getRandomString,
toFixedNumber,
} from './utils';
import { MockHiraganaRange, MockKatakanaRange } from './constants';

describe('createMatchScoreCalculator', () => {
const mockOptions: CreateValidatorOptions = {
characterSets: [CharacterSet.Katakana],
};

const fullKanaString = generateCharactersFromRange(
MockKatakanaRange.start,
MockKatakanaRange.end,
);

const fullHiraganaString = generateCharactersFromRange(
MockHiraganaRange.start,
MockHiraganaRange.end,
);

const invalidString = getRandomString(100);

describe('errors', () => {
test('should throw an error if options is not provided', () => {
// @ts-ignore
expect(() => createMatchScoreCalculator()).toThrow(
'[japanese-moji]: createMatchScoreCalculator: requires "options" to be supplied',
);
});
test('should throw an error if options.characterSets is not provided', () => {
// @ts-ignore
expect(() => createMatchScoreCalculator({})).toThrow(
'[japanese-moji]: createMatchScoreCalculator: requires "options.characterSets" to be supplied',
);
});
});
describe('characterSets', () => {
test('should return a function', () => {
const result = createMatchScoreCalculator(mockOptions);
expect(typeof result).toBe('function');
});

test('should throw an error when invalid character sets are provided', () => {
// Disabled ts intentionally to test the error message
// @ts-ignore
expect(() => createMatchScoreCalculator({ characterSets: ['invalid'] })).toThrow(
'[japanese-moji]: createRegexGroups: key "invalid" not found in the "characterSetMap',
);
});

test('should validate a string with 100% for the provided character sets', () => {
const isValidKana = createMatchScoreCalculator(mockOptions);
const result = isValidKana(fullKanaString);
expect(toFixedNumber(result)).toBe(100);
});
});
describe('customRanges', () => {
test('should add custom unicode range and return 100% for fully valid string', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customRanges: [escapeUnicodeRange(MockHiraganaRange)],
};
const isValidKanaWithHiragana = createMatchScoreCalculator(mergedOptions);
const result = isValidKanaWithHiragana(fullKanaString + fullHiraganaString);
expect(toFixedNumber(result)).toBe(100);
});

test('should add custom unicode ranges and return 49% for invalid string', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customRanges: [escapeUnicodeRange(MockHiraganaRange)],
};
const isValidKanaWithHiragana = createMatchScoreCalculator(mergedOptions);
const result = isValidKanaWithHiragana(fullHiraganaString + invalidString);
expect(toFixedNumber(result)).toBe(49);
});

test('should throw an error when invalid custom unicode ranges are provided', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customRanges: [
{
start: 'invalid stuff',
// This will not get printed since "start" throws
end: 'invalid stuff',
},
],
};
// Disabled ts intentionally to test the error message
// @ts-ignore
expect(() => createMatchScoreCalculator(mergedOptions)).toThrow(
'[japanese-moji]: createRange: invalid unicode value supplied for start of the range',
);
});
});
describe('customUnicodes', () => {
test('should add custom unicode and return 100% for fully valid string', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customUnicodes: [escapeUnicode(MockHiraganaRange.start)],
};
const isValidKanaWithHiragana = createMatchScoreCalculator(mergedOptions);
const result = isValidKanaWithHiragana(MockHiraganaRange.start);
expect(toFixedNumber(result)).toBe(100);
});

test('should add custom unicode and return 33% for invalid string', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customUnicodes: [escapeUnicode(MockHiraganaRange.start)],
};
const calculateScore = createMatchScoreCalculator(mergedOptions);
const result = calculateScore(fullKanaString + fullHiraganaString + invalidString);
expect(toFixedNumber(result)).toBe(33);
});

test('should throw an error when invalid custom unicodes are provided', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customUnicodes: [''],
};
// Disabled ts intentionally to test the error message
// @ts-ignore
expect(() => createMatchScoreCalculator(mergedOptions)).toThrow(
'[japanese-moji]: createUnicode: invalid unicode value supplied',
);
});
});
});
133 changes: 133 additions & 0 deletions __tests__/create-strict-validator.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { CharacterSet, createStrictValidator, CreateValidatorOptions } from '../src';
import {
escapeUnicode,
escapeUnicodeRange,
generateCharactersFromRange,
getRandomString,
} from './utils';
import { MockHiraganaRange, MockKatakanaRange } from './constants';

describe('createStrictValidator', () => {
const mockOptions: CreateValidatorOptions = {
characterSets: [CharacterSet.Katakana],
};

const fullKanaString = generateCharactersFromRange(
MockKatakanaRange.start,
MockKatakanaRange.end,
);

const fullHiraganaString = generateCharactersFromRange(
MockHiraganaRange.start,
MockHiraganaRange.end,
);

const invalidString = getRandomString(100);

describe('errors', () => {
test('should throw an error if options is not provided', () => {
// @ts-ignore
expect(() => createStrictValidator()).toThrow(
'[japanese-moji]: createStrictValidator: requires "options" to be supplied',
);
});
test('should throw an error if options.characterSets is not provided', () => {
// @ts-ignore
expect(() => createStrictValidator({})).toThrow(
'[japanese-moji]: createStrictValidator: requires "options.characterSets" to be supplied',
);
});
});
describe('characterSets', () => {
test('should return a function', () => {
const result = createStrictValidator(mockOptions);
expect(typeof result).toBe('function');
});

test('should throw an error when invalid character sets are provided', () => {
// Disabled ts intentionally to test the error message
// @ts-ignore
expect(() => createStrictValidator({ characterSets: ['invalid'] })).toThrow(
'[japanese-moji]: createRegexGroups: key "invalid" not found in the "characterSetMap',
);
});

test('should validate a string with the provided character sets', () => {
const isValidKana = createStrictValidator(mockOptions);
const result = isValidKana(fullKanaString);
expect(result).toBe(true);
});
});
describe('customRanges', () => {
test('should add custom unicode range and return true for valid string', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customRanges: [escapeUnicodeRange(MockHiraganaRange)],
};
const isValidKanaWithHiragana = createStrictValidator(mergedOptions);
const result = isValidKanaWithHiragana(fullKanaString + fullHiraganaString);
expect(result).toBe(true);
});

test('should add custom unicode ranges and return false for invalid string', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customRanges: [escapeUnicodeRange(MockHiraganaRange)],
};
const isValidKanaWithHiragana = createStrictValidator(mergedOptions);
const result = isValidKanaWithHiragana(invalidString);
expect(result).toBe(false);
});

test('should throw an error when invalid custom unicode ranges are provided', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customRanges: [
{
start: 'invalid stuff',
// This will not get printed since "start" throws
end: 'invalid stuff',
},
],
};
// Disabled ts intentionally to test the error message
// @ts-ignore
expect(() => createStrictValidator(mergedOptions)).toThrow(
'[japanese-moji]: createRange: invalid unicode value supplied for start of the range',
);
});
});
describe('customUnicodes', () => {
test('should add custom unicode and return true for valid string', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customUnicodes: [escapeUnicode(MockHiraganaRange.start)],
};
const isValidKanaWithHiragana = createStrictValidator(mergedOptions);
const result = isValidKanaWithHiragana(MockHiraganaRange.start);
expect(result).toBe(true);
});

test('should add custom unicode and return false for invalid string', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customUnicodes: [escapeUnicode(MockHiraganaRange.start)],
};
const isValidKanaWithHiragana = createStrictValidator(mergedOptions);
const result = isValidKanaWithHiragana(invalidString);
expect(result).toBe(false);
});

test('should throw an error when invalid custom unicodes are provided', () => {
const mergedOptions: CreateValidatorOptions = {
...mockOptions,
customUnicodes: [''],
};
// Disabled ts intentionally to test the error message
// @ts-ignore
expect(() => createStrictValidator(mergedOptions)).toThrow(
'[japanese-moji]: createUnicode: invalid unicode value supplied',
);
});
});
});
Loading

0 comments on commit 29027ce

Please sign in to comment.