Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/util/common/test/result.spec.ts
13401 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { describe, expect, it } from 'vitest';
7
import { Result } from '../result';
8
9
describe('Result', () => {
10
11
describe('Result.ok', () => {
12
it('creates an ok result', () => {
13
const r = Result.ok(42);
14
expect(r.isOk()).toBe(true);
15
expect(r.isError()).toBe(false);
16
expect(r.val).toBe(42);
17
});
18
});
19
20
describe('Result.error', () => {
21
it('creates an error result', () => {
22
const r = Result.error('bad');
23
expect(r.isOk()).toBe(false);
24
expect(r.isError()).toBe(true);
25
expect(r.err).toBe('bad');
26
});
27
});
28
29
describe('Result.fromString', () => {
30
it('creates an error result with an Error instance', () => {
31
const r = Result.fromString('something failed');
32
expect(r.isError()).toBe(true);
33
expect(r.err).toBeInstanceOf(Error);
34
expect(r.err.message).toBe('something failed');
35
});
36
});
37
38
describe('Result.tryWith', () => {
39
it('returns ok when the function succeeds', () => {
40
const r = Result.tryWith(() => 10 + 5);
41
expect(r.isOk()).toBe(true);
42
if (r.isOk()) {
43
expect(r.val).toBe(15);
44
}
45
});
46
47
it('returns error when the function throws', () => {
48
const r = Result.tryWith(() => { throw new Error('boom'); });
49
expect(r.isError()).toBe(true);
50
if (r.isError()) {
51
expect(r.err.message).toBe('boom');
52
}
53
});
54
});
55
56
describe('Result.tryWithAsync', () => {
57
it('returns ok when the async function resolves', async () => {
58
const r = await Result.tryWithAsync(async () => 99);
59
expect(r.isOk()).toBe(true);
60
if (r.isOk()) {
61
expect(r.val).toBe(99);
62
}
63
});
64
65
it('returns error when the async function rejects', async () => {
66
const r = await Result.tryWithAsync(async () => { throw new Error('async boom'); });
67
expect(r.isError()).toBe(true);
68
if (r.isError()) {
69
expect(r.err.message).toBe('async boom');
70
}
71
});
72
});
73
74
describe('map', () => {
75
it('transforms the value of an ok result', () => {
76
const r = Result.ok(3).map(x => x * 2);
77
expect(r.isOk()).toBe(true);
78
if (r.isOk()) {
79
expect(r.val).toBe(6);
80
}
81
});
82
83
it('is a no-op on an error result', () => {
84
const r: Result<number, string> = Result.error('fail');
85
const mapped = r.map(x => x * 2);
86
expect(mapped.isError()).toBe(true);
87
if (mapped.isError()) {
88
expect(mapped.err).toBe('fail');
89
}
90
});
91
});
92
93
describe('mapError', () => {
94
it('is a no-op on an ok result', () => {
95
const r: Result<number, string> = Result.ok(5);
96
const mapped = r.mapError(e => new Error(e));
97
expect(mapped.isOk()).toBe(true);
98
if (mapped.isOk()) {
99
expect(mapped.val).toBe(5);
100
}
101
});
102
103
it('transforms the error of an error result', () => {
104
const r = Result.error('oops');
105
const mapped = r.mapError(e => ({ reason: e }));
106
expect(mapped.isError()).toBe(true);
107
if (mapped.isError()) {
108
expect(mapped.err).toEqual({ reason: 'oops' });
109
}
110
});
111
});
112
113
describe('flatMap', () => {
114
it('chains ok results', () => {
115
const r = Result.ok(10).flatMap(x =>
116
x > 0 ? Result.ok(x.toString()) : Result.error('negative' as const)
117
);
118
expect(r.isOk()).toBe(true);
119
if (r.isOk()) {
120
expect(r.val).toBe('10');
121
}
122
});
123
124
it('chains to an error result', () => {
125
const r = Result.ok(-1).flatMap(x =>
126
x > 0 ? Result.ok(x.toString()) : Result.error('negative' as const)
127
);
128
expect(r.isError()).toBe(true);
129
if (r.isError()) {
130
expect(r.err).toBe('negative');
131
}
132
});
133
134
it('is a no-op on an error result', () => {
135
const r: Result<number, string> = Result.error('already bad');
136
const chained = r.flatMap(x => Result.ok(x * 2));
137
expect(chained.isError()).toBe(true);
138
if (chained.isError()) {
139
expect(chained.err).toBe('already bad');
140
}
141
});
142
});
143
144
describe('unwrap', () => {
145
it('returns the value for ok results', () => {
146
expect(Result.ok('hello').unwrap()).toBe('hello');
147
});
148
149
it('throws for error results with an Error', () => {
150
const r: Result<string, Error> = Result.error(new Error('fail'));
151
expect(() => r.unwrap()).toThrow('fail');
152
});
153
154
it('throws a wrapped error for non-Error error values', () => {
155
const r: Result<string, string> = Result.error('string error');
156
expect(() => r.unwrap()).toThrow('string error');
157
});
158
});
159
160
describe('unwrapOr', () => {
161
it('returns the value for ok results', () => {
162
const r: Result<number, string> = Result.ok(42);
163
expect(r.unwrapOr(0)).toBe(42);
164
});
165
166
it('returns the default for error results', () => {
167
const r: Result<number, string> = Result.error('nope');
168
expect(r.unwrapOr(0)).toBe(0);
169
});
170
});
171
172
describe('type narrowing', () => {
173
it('narrows to ok after isOk check', () => {
174
const r: Result<number, string> = Result.ok(1);
175
if (r.isOk()) {
176
// TypeScript should know r.val exists here
177
const _v: number = r.val;
178
expect(_v).toBe(1);
179
}
180
});
181
182
it('narrows to error after isError check', () => {
183
const r: Result<number, string> = Result.error('e');
184
if (r.isError()) {
185
// TypeScript should know r.err exists here
186
const _e: string = r.err;
187
expect(_e).toBe('e');
188
}
189
});
190
});
191
});
192
193