When working with fp-ts
, and conducting unit tests using Jest, I often come across scenarios where I need to test nullable results, typically represented by Option
or Either
(usually in array find
operations). What is the most efficient way to ensure that the test fails if the result is 'none' (taking Option
as an example), and continue without interruption if the result is 'some'?
Let's consider a solution I currently utilize:
function someFunc(input: string): Option.Option<string> {
return Option.some(input);
}
describe(`Some suite`, () => {
it(`should perform actions with a "some" result`, () => {
const result = someFunc('abcd');
// This is a failure scenario, expecting result to be Some
if(Option.isNone(result)) {
expect(Option.isSome(result)).toEqual(true);
return;
}
expect(result.value).toEqual('abcd');
});
});
However, including an if statement with an early return can be cumbersome.
Another approach could involve using an as
assertion:
// ...
it(`should perform actions with a "some" result`, () => {
const result = someFunc('abcd') as Option.Some<string>;
expect(result.value).toEqual('abcd');
});
// ...
Yet, this method requires rewriting the type associated with some
. In many instances, this may be arduous, necessitating the creation and export of interfaces solely for testing purposes (which is not very user-friendly).
Is there a simpler way to streamline this type of testing?
Edit: Here's a test case that closely resembles real-world conditions:
interface SomeComplexType {
id: string,
inputAsArray: string[],
input: string;
}
function someFunc(input: string): Option.Option<SomeComplexType> {
return Option.some({
id: '5',
inputAsArray: input.split(''),
input,
});
}
describe(`Some suite`, () => {
it(`should perform actions with a "some" result`, () => {
const result = someFunc('abcd');
// This step lacks efficiency
if(Option.isNone(result)) {
expect(Option.isSome(result)).toEqual(true);
return;
}
// Ideally, only this would be necessary:
expect(Option.isSome(result)).toEqual(true);
// Since no further steps will be executed if the result is not "some"
// Though, it might be challenging for TS to deduce this from Jest expects
// With knowledge of the actual value's type, numerous actions can be taken
// Eliminating the need to check for nullability or specify its type
const myValue = result.value;
expect(myValue.inputAsArray).toEqual(expect.arrayContaining(['a', 'b', 'c', 'd']));
const someOtherThing = getTheOtherThing(myValue.id);
expect(someOtherThing).toMatchObject({
another: 'thing',
});
});
});