Skip to content

Commit

Permalink
feat: support inspectAsync and inspectErrAsync methods
Browse files Browse the repository at this point in the history
  • Loading branch information
yifanwww committed Mar 17, 2024
1 parent 3c32f3e commit 01cce7c
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 4 deletions.
104 changes: 100 additions & 4 deletions src/__tests__/result.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,9 +516,9 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot

describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspect.name}\``, () => {
it('should return itself', () => {
const fn = jest.fn(() => {
const fn = () => {
// do something
});
};
const okResult = Ok(1);
const errResult = Err(0);
expect(okResult.inspect(fn)).toBe(okResult);
Expand Down Expand Up @@ -546,11 +546,59 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot
});
});

describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspectErr.name}\``, () => {
it('should return itself', () => {
describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspectAsync.name}\``, () => {
it('should return itself', async () => {
const fn1 = () => {
// do something
};
const fn2 = () => {
// do something
return Promise.resolve();
};

const okResult = Ok(1);
const errResult = Err(0);

await expect(okResult.inspectAsync(fn1)).resolves.toStrictEqual(okResult);
await expect(errResult.inspectAsync(fn1)).resolves.toStrictEqual(errResult);
await expect(okResult.inspectAsync(fn2)).resolves.toStrictEqual(okResult);
await expect(errResult.inspectAsync(fn2)).resolves.toStrictEqual(errResult);
});

it('should inspect ok value', async () => {
const fn1 = jest.fn((value: number) => expect(value).toBe(1));
const fn2 = jest.fn((value: number) => {
expect(value).toBe(1);
return Promise.resolve();
});
expect(fn1).toHaveBeenCalledTimes(0);
expect(fn2).toHaveBeenCalledTimes(0);
await Ok(1).inspectAsync(fn1);
await Ok(1).inspectAsync(fn2);
expect(fn1).toHaveBeenCalledTimes(1);
expect(fn2).toHaveBeenCalledTimes(1);
});

it('should not inspect err value', async () => {
const fn = jest.fn(() => {
// do something
});
expect(fn).toHaveBeenCalledTimes(0);
await Err(1).inspectAsync(fn);
expect(fn).toHaveBeenCalledTimes(0);
});

it('should panic if fn panic', async () => {
await expect(() => Ok(1).inspectAsync(panicFn1)).rejects.toThrow(Error('error'));
await expect(() => Ok(1).inspectAsync(panicFn2)).rejects.toThrow(Error('error'));
});
});

describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspectErr.name}\``, () => {
it('should return itself', () => {
const fn = () => {
// do something
};
const okResult = Ok(1);
const errResult = Err(0);
expect(okResult.inspectErr(fn)).toBe(okResult);
Expand Down Expand Up @@ -578,6 +626,54 @@ describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.protot
});
});

describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.inspectErrAsync.name}\``, () => {
it('should return itself', async () => {
const fn1 = () => {
// do something
};
const fn2 = () => {
// do something
return Promise.resolve();
};

const okResult = Ok(1);
const errResult = Err(0);

await expect(okResult.inspectErrAsync(fn1)).resolves.toBe(okResult);
await expect(errResult.inspectErrAsync(fn1)).resolves.toBe(errResult);
await expect(okResult.inspectErrAsync(fn2)).resolves.toBe(okResult);
await expect(errResult.inspectErrAsync(fn2)).resolves.toBe(errResult);
});

it('should not inspect ok value', async () => {
const fn = jest.fn(() => {
// do something
});
expect(fn).toHaveBeenCalledTimes(0);
await Ok(1).inspectErrAsync(fn);
expect(fn).toHaveBeenCalledTimes(0);
});

it('should inspect err value', async () => {
const fn1 = jest.fn((value: number) => expect(value).toBe(1));
const fn2 = jest.fn((value: number) => {
expect(value).toBe(1);
return Promise.resolve();
});
expect(fn1).toHaveBeenCalledTimes(0);
expect(fn2).toHaveBeenCalledTimes(0);
await Err(1).inspectErrAsync(fn1);
await Err(1).inspectErrAsync(fn2);
expect(fn1).toHaveBeenCalledTimes(1);
expect(fn2).toHaveBeenCalledTimes(1);
});

it('should panic if fn panic', async () => {
await expect(() => Err('err').inspectErrAsync(panicFn1)).rejects.toThrow(Error('error'));
await expect(() => Err('err').inspectErrAsync(panicFn2)).rejects.toThrow(Error('error'));
});
});

describe(`Test method \`${RustlikeResult.name}.prototype.${RustlikeResult.prototype.expect.name}\``, () => {
it('should unwrap itself to get the contained `Ok` value', () => {
expect(Ok(1).expect('Operation type should be correct')).toBe(1);
Expand Down
24 changes: 24 additions & 0 deletions src/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,18 @@ export class RustlikeResult<T, E> implements Result<T, E> {
return this;
}

/**
* Asynchronously calls the provided closure with a reference to the contained value if `Ok`.
*
* ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect
*/
async inspectAsync(fn: (value: T) => void | Promise<void>): Promise<this> {
if (this.isOk()) {
await fn(this.unwrapUnchecked());
}
return this;
}

/**
* Calls the provided closure with a reference to the contained value if `Err`.
*
Expand All @@ -234,6 +246,18 @@ export class RustlikeResult<T, E> implements Result<T, E> {
return this;
}

/**
* Asynchronously calls the provided closure with a reference to the contained value if `Err`.
*
* ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect_err
*/
async inspectErrAsync(fn: (err: E) => void | Promise<void>): Promise<this> {
if (this.isErr()) {
await fn(this.unwrapErrUnchecked());
}
return this;
}

private _unwrapFailed(msg: string, err: unknown): never {
throw new Error(`${msg}: ${String(err)}`);
}
Expand Down
14 changes: 14 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,27 @@ export interface Result<T, E> {
*/
inspect(fn: (value: T) => void): this;

/**
* Asynchronously calls the provided closure with a reference to the contained value if `Ok`.
*
* ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect
*/
inspectAsync(fn: (value: T) => void | Promise<void>): Promise<this>;

/**
* Calls the provided closure with a reference to the contained value if `Err`.
*
* ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect_err
*/
inspectErr(fn: (err: E) => void): this;

/**
* Asynchronously calls the provided closure with a reference to the contained value if `Err`.
*
* ref: https://doc.rust-lang.org/std/result/enum.Result.html#method.inspect_err
*/
inspectErrAsync(fn: (err: E) => void | Promise<void>): Promise<this>;

/**
* Returns the contained `Ok` value.
*
Expand Down

0 comments on commit 01cce7c

Please sign in to comment.