I'm using fp-ts
, and I write unit tests with Jest. In many cases, I'm testing nullable results, often represented with Option
or Either
(typically, array find
s). What is the most ergonomic way to make the test fail if the result is none (taking Option
as an example), and keep on going knowing that this result is some?
Here's an example of how I can solve the problem at the moment:
function someFunc(input: string): Option.Option<string> {
return Option.some(input);
}
describe(`Some suite`, () => {
it(`should do something with a "some" result`, () => {
const result = someFunc('abcd');
// This is a fail case, here I'm expecting result to be Some
if(Option.isNone(result)) {
expect(Option.isSome(result)).toEqual(true);
return;
}
expect(result.value).toEqual('abcd');
});
});
But having to write an if with an early return is not very ergonomic.
I could alternatively write an as
assertion:
// ...
it(`should do something with a "some" result`, () => {
const result = someFunc('abcd') as Option.Some<string>;
expect(result.value).toEqual('abcd');
});
// ...
But the downside there is that I have to rewrite the some
's type. In many cases, having to write it is heavy, requiring to write and export interface for the sole purpose of testing (which is not ergonomic either).
Is there any way to simplify this kind of test?
Edit: Here is a test case that's closer to real 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 do something with a "some" result`, () => {
const result = someFunc('abcd');
// This is the un-ergonomic step
if(Option.isNone(result)) {
expect(Option.isSome(result)).toEqual(true);
return;
}
// Ideally, I would only need this:
expect(Option.isSome(result)).toEqual(true);
// Since nothing will be ran after it if the result is not "some"
// But I can imagine it's unlikely that TS could figure that out from Jest expects
// Since I now have the value's actual type, I can do a lot with it
// I don't have to check it for nullability, and I don't have to write 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',
});
});
});