Skip to content

Commit

Permalink
feat: Introduce way to get return-value of first of many functions th…
Browse files Browse the repository at this point in the history
…at matches an input-value
  • Loading branch information
Iku-turso committed Oct 16, 2023
1 parent c0b9cd1 commit c939461
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/fp/index.d.ts
Expand Up @@ -122,3 +122,5 @@ export const getFrom: GetFrom;
export const getSafeFrom: GetFrom;

export const pipelineBreak: Symbol;

export { firstMatchValue } from './src/firstMatchValue/firstMatchValue';
2 changes: 2 additions & 0 deletions packages/fp/index.js
Expand Up @@ -6,6 +6,7 @@ import pipeline from './src/pipeline/pipeline';
import mapValuesDeep from './src/mapValuesDeep/mapValuesDeep';
import getSafeFrom from './src/getSafeFrom/getSafeFrom';
import getFrom from './src/getFrom/getFrom';
import firstMatchValue from './src/firstMatchValue/firstMatchValue';

export {
awaitAll,
Expand All @@ -17,4 +18,5 @@ export {
getFrom,
getSafeFrom,
pipelineBreak,
firstMatchValue,
};
1 change: 1 addition & 0 deletions packages/fp/package.json
Expand Up @@ -33,6 +33,7 @@
"scripts": {
"build": "ogre-tools-build-js",
"test": "ogre-tools-test",
"test:types": "tsd --files ./src/**/*.test-d.ts",
"code-style:verify": "ogre-tools-verify-code-style",
"code-style:fix": "ogre-tools-fix-code-style"
},
Expand Down
3 changes: 3 additions & 0 deletions packages/fp/src/firstMatchValue/firstMatchValue.d.ts
@@ -0,0 +1,3 @@
export function firstMatchValue<TInput, TOutput>(
...functions: ((input: TInput) => TOutput | undefined)[]
): (input: TInput) => TOutput | undefined;
11 changes: 11 additions & 0 deletions packages/fp/src/firstMatchValue/firstMatchValue.js
@@ -0,0 +1,11 @@
export const firstMatchValue =
(...functions) =>
data => {
for (const f of functions) {
const value = f(data);

if (value !== undefined) {
return value;
}
}
};
11 changes: 11 additions & 0 deletions packages/fp/src/firstMatchValue/firstMatchValue.test-d.ts
@@ -0,0 +1,11 @@
import { expectType } from 'tsd';
import { firstMatchValue as firstMatchValueFor } from './firstMatchValue';

const firstMatchValue = firstMatchValueFor(
x => 'some-string',
x => 'some-other-string',
);

const actual = firstMatchValue(true);

expectType<string | undefined>(actual);
53 changes: 53 additions & 0 deletions packages/fp/src/firstMatchValue/firstMatchValue.test.js
@@ -0,0 +1,53 @@
import { firstMatchValue as firstMatchValueFor } from './firstMatchValue';
import { constant, get } from 'lodash/fp';

describe('firstMatchValue', () => {
describe('given array of functions used for finding', () => {
let firstMatchValue;
let finderMock;

beforeEach(() => {
finderMock = jest.fn();

firstMatchValue = firstMatchValueFor(
constant(undefined),
get('someProperty'),
finderMock,
);
});

describe('when called with data containing a match', () => {
let actual;

beforeEach(() => {
actual = firstMatchValue({ someProperty: 'some-value' });
});

it('returns the matched value from the matcher of highest priority', () => {
expect(actual).toBe('some-value');
});

it('does not call matchers of less priority than the one matching', () => {
expect(finderMock).not.toHaveBeenCalled();
});
});

describe('when called with data not containing a match', () => {
let actual;

beforeEach(() => {
actual = firstMatchValue({ someOtherProperty: 'irrelevant' });
});

it('returns undefined', () => {
expect(actual).toBeUndefined();
});

it('calls all matchers', () => {
expect(finderMock).toHaveBeenCalledWith({
someOtherProperty: 'irrelevant',
});
});
});
});
});

0 comments on commit c939461

Please sign in to comment.