Skip to content

Commit

Permalink
Tighten up KeyGenerators API (fixes #3)
Browse files Browse the repository at this point in the history
  • Loading branch information
dlh3 committed Jul 7, 2020
1 parent 19090d7 commit 12822c7
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 6 deletions.
15 changes: 13 additions & 2 deletions src/keyGenerators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,24 @@ import {GeneratorFunc} from './types';
* A selection of predefined {@link GeneratorFunc} functions to choose from.
*/
export class KeyGenerators {
/**
* Validates and normalizes a key candidate. Keys must be strings or convertible to strings (number, boolean, etc).
*
* @param {unknown} key - The key candidate.
* @return string
*/
private static normalizeKey = (key: unknown) =>
key === undefined || typeof key === 'object' ? '' : String(key);

/**
* Use the existing key. Useful when adding elements to an array that already has keys.
* If used, will usually be the first generator provided.
*
* @return GeneratorFunc
*/
static existingKey = (): GeneratorFunc => (obj: any) => obj.key || undefined; // eslint-disable-line @typescript-eslint/no-explicit-any
static existingKey = (): GeneratorFunc => (
obj: any // eslint-disable-line @typescript-eslint/no-explicit-any
) => KeyGenerators.normalizeKey(obj.key);

/**
* A property extractor, allowing the objects to be walked until the leaf node is extracted.
Expand All @@ -26,7 +37,7 @@ export class KeyGenerators {

const target = path.reduce((prev, prop) => prev[prop], obj);

return !target || typeof target === 'object' ? '' : String(target);
return KeyGenerators.normalizeKey(target);
};

/**
Expand Down
58 changes: 54 additions & 4 deletions test/keyGenerators.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,32 @@ describe('existingKey', () => {
expect(generator(elementWithKey)).toBe(existingKey);
});

it('is undefined for blank key', () => {
it('is blank for blank key', () => {
const elementWithKey = {...testElement};
elementWithKey.key = '';

expect(generator(elementWithKey)).toBeUndefined();
expect(generator(elementWithKey)).toBe('');
});

it('is undefined for non-existing key', () => {
it('is blank for non-existing key', () => {
const elementWithKey = {...testElement};
elementWithKey.key = undefined;

expect(generator(elementWithKey)).toBeUndefined();
expect(generator(elementWithKey)).toBe('');
});

it('works with the number 0', () => {
const elementWithKey = {...testElement} as any;
elementWithKey.key = 0;

expect(generator(elementWithKey)).toBe(String(elementWithKey.key));
});

it('works with the boolean false', () => {
const elementWithKey = {...testElement} as any;
elementWithKey.key = false;

expect(generator(elementWithKey)).toBe(String(elementWithKey.key));
});
});

Expand Down Expand Up @@ -74,6 +88,24 @@ describe('fromPropertyPath', () => {
expect(generator(elementWithProp)).toBe(String(elementWithProp.id));
});

it('works with the number 0', () => {
const generator = KeyGenerators.fromPropertyPath("id");

const elementWithProp = {...testElement};
elementWithProp.id = 0;

expect(generator(elementWithProp)).toBe(String(elementWithProp.id));
});

it('works with the boolean false', () => {
const generator = KeyGenerators.fromPropertyPath("id");

const elementWithProp = {...testElement};
elementWithProp.id = false;

expect(generator(elementWithProp)).toBe(String(elementWithProp.id));
});

it('works for nested properties', () => {
const generator = KeyGenerators.fromPropertyPath("profile.dob.month");

Expand Down Expand Up @@ -119,6 +151,24 @@ describe('fromPropertyPath', () => {
expect(generator(elementWithProp)).toBe(String(elementWithProp.id));
});

it('works with the number 0', () => {
const generator = KeyGenerators.fromPropertyPath(["id"]);

const elementWithProp = {...testElement};
elementWithProp.id = 0;

expect(generator(elementWithProp)).toBe(String(elementWithProp.id));
});

it('works with the boolean false', () => {
const generator = KeyGenerators.fromPropertyPath(["id"]);

const elementWithProp = {...testElement};
elementWithProp.id = false;

expect(generator(elementWithProp)).toBe(String(elementWithProp.id));
});

it('works for nested properties', () => {
const generator = KeyGenerators.fromPropertyPath(["profile", "dob", "month"]);

Expand Down

0 comments on commit 12822c7

Please sign in to comment.