Skip to content

Commit ccfe194

Browse files
committed
fix raising errors from JSON parse to be strings
1 parent eaae672 commit ccfe194

2 files changed

Lines changed: 168 additions & 150 deletions

File tree

core/src/TeaCup/Decode.test.ts

Lines changed: 135 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ import { just, nothing } from './Maybe';
2929
const num = Decode.num;
3030
const field = Decode.field;
3131

32+
test('syntax error', () => {
33+
expect(num.decodeString(' { broken ')).toEqual(err('Unexpected token b in JSON at position 3'));
34+
});
35+
3236
test('primitives', () => {
3337
expect(num.decodeValue(1)).toEqual(ok(1));
3438
expect(num.decodeValue('yeah')).toEqual(err('value is not a number : "yeah"'));
@@ -154,95 +158,104 @@ test('map8', () => {
154158
field('h', num),
155159
).decodeValue(o),
156160
).toEqual(ok(o));
157-
158161
});
159162

160163
describe('mapObject', () => {
161164
type MyType = {
162-
foo: string,
163-
bar: number
165+
foo: string;
166+
bar: number;
164167
};
165168
const expected: MyType = {
166169
foo: 'a foo',
167-
bar: 13
168-
}
170+
bar: 13,
171+
};
169172

170173
test('simple', () => {
171-
const value = { foo: 'a foo', bar: 13 }
172-
expect(Decode.mapObject<MyType>({
173-
foo: Decode.field('foo', Decode.str),
174-
bar: Decode.field('bar', Decode.num)
175-
}).decodeValue(value)).toEqual(ok(expected));
176-
})
177-
174+
const value = { foo: 'a foo', bar: 13 };
175+
expect(
176+
Decode.mapObject<MyType>({
177+
foo: Decode.field('foo', Decode.str),
178+
bar: Decode.field('bar', Decode.num),
179+
}).decodeValue(value),
180+
).toEqual(ok(expected));
181+
});
178182

179183
test('simpler', () => {
180-
const value = { foo: 'a foo', bar: 13 }
181-
expect(Decode.mapObject<MyType>(Decode.mapRequiredFields({
182-
foo: Decode.str,
183-
bar: Decode.num
184-
})).decodeValue(value)).toEqual(ok(expected));
185-
})
186-
184+
const value = { foo: 'a foo', bar: 13 };
185+
expect(
186+
Decode.mapObject<MyType>(
187+
Decode.mapRequiredFields({
188+
foo: Decode.str,
189+
bar: Decode.num,
190+
}),
191+
).decodeValue(value),
192+
).toEqual(ok(expected));
193+
});
187194

188195
test('missing field', () => {
189-
const value = { foo: 'a foo' }
190-
expect(Decode.mapObject<MyType>({
191-
foo: Decode.field('foo', Decode.str),
192-
bar: Decode.field('bar', Decode.num)
193-
}).decodeValue(value)).toEqual(err('path not found [bar] on {"foo":"a foo"}'));
194-
})
196+
const value = { foo: 'a foo' };
197+
expect(
198+
Decode.mapObject<MyType>({
199+
foo: Decode.field('foo', Decode.str),
200+
bar: Decode.field('bar', Decode.num),
201+
}).decodeValue(value),
202+
).toEqual(err('path not found [bar] on {"foo":"a foo"}'));
203+
});
195204

196205
test('superfluous field', () => {
197-
const value = { foo: 'a foo', bar: 13, toto: true }
198-
expect(Decode.mapObject<MyType>({
199-
foo: Decode.field('foo', Decode.str),
200-
bar: Decode.field('bar', Decode.num)
201-
}).decodeValue(value)).toEqual(ok(expected));
202-
})
206+
const value = { foo: 'a foo', bar: 13, toto: true };
207+
expect(
208+
Decode.mapObject<MyType>({
209+
foo: Decode.field('foo', Decode.str),
210+
bar: Decode.field('bar', Decode.num),
211+
}).decodeValue(value),
212+
).toEqual(ok(expected));
213+
});
203214

204215
test('optional field', () => {
205216
type MyType2 = {
206-
foo: string,
207-
bar?: number
217+
foo: string;
218+
bar?: number;
208219
};
209220
const expected: MyType2 = {
210221
foo: 'a foo',
211-
}
222+
};
212223

213-
const value = { foo: 'a foo', toto: true }
214-
expect(Decode.mapObject<MyType2>({
215-
foo: Decode.field('foo', Decode.str),
216-
bar: Decode.optionalField('bar', Decode.num)
217-
}).decodeValue(value)).toEqual(ok(expected));
224+
const value = { foo: 'a foo', toto: true };
225+
expect(
226+
Decode.mapObject<MyType2>({
227+
foo: Decode.field('foo', Decode.str),
228+
bar: Decode.optionalField('bar', Decode.num),
229+
}).decodeValue(value),
230+
).toEqual(ok(expected));
218231

219232
// the type system will compile fail this test:
220233
// expect(Decode.mapObject<MyType2>({
221234
// foo: Decode.field('foo', Decode.str),
222235
// }).decodeValue(value)).toEqual(ok(expected));
223-
})
236+
});
224237

225238
test('simpler optional field', () => {
226239
type MyType2 = {
227-
foo: string,
228-
bar?: number
240+
foo: string;
241+
bar?: number;
229242
};
230243
const expected: MyType2 = {
231244
foo: 'a foo',
232-
}
245+
};
233246

234247
const decoder: DecoderObject<MyType2> = {
235248
...Decode.mapRequiredFields({
236249
foo: Decode.str,
237250
}),
238251
...Decode.mapOptionalFields({
239252
bar: Decode.num,
240-
})
241-
}
253+
}),
254+
};
242255

243-
const value = { foo: 'a foo', toto: true }
256+
const value = { foo: 'a foo', toto: true };
244257
expect(Decode.mapObject<MyType2>(decoder).decodeValue(value)).toEqual(ok(expected));
245-
})
258+
});
246259

247260
it('decode array of mapObject', () => {
248261
type MyItem = { gnu: number; foo: string };
@@ -268,30 +281,23 @@ describe('mapObject', () => {
268281
const r = Decode.array(MyItemDecoder).decodeValue(payload);
269282
expect(r).toEqual(ok(payload));
270283
});
271-
})
284+
});
272285

273286
describe('mapArray', () => {
274-
type MyType = [
275-
string,
276-
number
277-
]
278-
const expected: MyType = [
279-
'a foo',
280-
13
281-
]
287+
type MyType = [string, number];
288+
const expected: MyType = ['a foo', 13];
282289

283290
test('simple', () => {
284-
type ValueType = [string, number]
285-
const value: ValueType = ['a foo', 13]
286-
expect(Decode.mapTuple<ValueType>([
287-
Decode.str,
288-
Decode.num
289-
]).decodeValue(value)).toEqual(ok(expected));
290-
})
291+
type ValueType = [string, number];
292+
const value: ValueType = ['a foo', 13];
293+
expect(
294+
Decode.mapTuple<ValueType>([Decode.str, Decode.num]).decodeValue(value),
295+
).toEqual(ok(expected));
296+
});
291297

292298
test('type mismatch', () => {
293-
type ValueType = [string, number]
294-
const value: ValueType = ['a foo', 13]
299+
type ValueType = [string, number];
300+
const value: ValueType = ['a foo', 13];
295301

296302
// the type system will compile fail this test:
297303
// expect(Decode.mapArray<ValueType>([
@@ -300,38 +306,33 @@ describe('mapArray', () => {
300306
// ]).decodeValue(value)).toEqual(err('ran into decoder error at [1] : value is not a string : 13'));
301307

302308
// the type system will let though to runtime:
303-
expect(Decode.mapTuple([
304-
Decode.str,
305-
Decode.str
306-
]).decodeValue(value)).toEqual(err('ran into decoder error at [1] : value is not a string : 13'));
307-
})
309+
expect(Decode.mapTuple([Decode.str, Decode.str]).decodeValue(value)).toEqual(
310+
err('ran into decoder error at [1] : value is not a string : 13'),
311+
);
312+
});
308313

309314
test('missing item', () => {
310-
type ValueType = [string, number]
315+
type ValueType = [string, number];
311316
// the type system will compile fail this test:
312317
// const value: ValueType = ['a foo']
313318

314319
// the type system will let though to runtime:
315-
const value = ['a foo']
316-
expect(Decode.mapTuple([
317-
Decode.str,
318-
Decode.num
319-
]).decodeValue(value)).toEqual(err('path not found [1] on [\"a foo\"]'));
320-
})
320+
const value = ['a foo'];
321+
expect(Decode.mapTuple([Decode.str, Decode.num]).decodeValue(value)).toEqual(
322+
err('path not found [1] on ["a foo"]'),
323+
);
324+
});
321325

322326
test('too many items', () => {
323-
type ValueType = [string, number]
327+
type ValueType = [string, number];
324328
// the type system will compile fail this test:
325329
// const value: ValueType = ['a foo', 13, true]
326330

327331
// the type system will let though to runtime:
328-
const value = ['a foo', 13, true]
329-
expect(Decode.mapTuple([
330-
Decode.str,
331-
Decode.num
332-
]).decodeValue(value)).toEqual(ok(expected));
333-
})
334-
})
332+
const value = ['a foo', 13, true];
333+
expect(Decode.mapTuple([Decode.str, Decode.num]).decodeValue(value)).toEqual(ok(expected));
334+
});
335+
});
335336

336337
test('andThen', () => {
337338
type Stuff = { readonly tag: 'stuff1'; readonly foo: string } | { readonly tag: 'stuff2'; readonly bar: string };
@@ -444,78 +445,87 @@ test('any value', () => {
444445
});
445446

446447
describe('optional field', () => {
447-
test("is present", () => {
448+
test('is present', () => {
448449
const value = { foo: 'bar', gnu: 13 };
449450
expect(Decode.optionalField('gnu', Decode.num).decodeValue(value)).toEqual(ok(13));
450-
})
451-
test("is missing", () => {
451+
});
452+
test('is missing', () => {
452453
const value = { foo: 'bar' };
453454
expect(Decode.optionalField('gnu', Decode.num).decodeValue(value)).toEqual(ok(undefined));
454-
})
455+
});
455456

456-
test("typical use case", () => {
457+
test('typical use case', () => {
457458
type MyType = {
458459
foo: string;
459460
gnu?: number;
460-
}
461+
};
461462
const value = { foo: 'bar' };
462463
const expected: MyType = {
463-
foo: 'bar'
464+
foo: 'bar',
464465
};
465-
expect(Decode.map2(
466-
(foo, gnu) => { return { foo, gnu } },
467-
Decode.field('foo', Decode.str),
468-
Decode.optionalField('gnu', Decode.num)).decodeValue(value)
466+
expect(
467+
Decode.map2(
468+
(foo, gnu) => {
469+
return { foo, gnu };
470+
},
471+
Decode.field('foo', Decode.str),
472+
Decode.optionalField('gnu', Decode.num),
473+
).decodeValue(value),
469474
).toEqual(ok(expected));
470-
})
475+
});
471476

472477
test('simpler optional field', () => {
473478
type MyType2 = {
474-
foo: string,
475-
bar?: number
479+
foo: string;
480+
bar?: number;
476481
};
477482
const expected: MyType2 = {
478483
foo: 'a foo',
479-
}
484+
};
480485

481-
const value = { foo: 'a foo', toto: true }
482-
expect(Decode.mapObject<MyType2>({
483-
...Decode.mapRequiredFields({
484-
foo: Decode.str,
485-
}),
486-
bar: Decode.optionalField('bar', Decode.num)
487-
}).decodeValue(value)).toEqual(ok(expected));
488-
})
486+
const value = { foo: 'a foo', toto: true };
487+
expect(
488+
Decode.mapObject<MyType2>({
489+
...Decode.mapRequiredFields({
490+
foo: Decode.str,
491+
}),
492+
bar: Decode.optionalField('bar', Decode.num),
493+
}).decodeValue(value),
494+
).toEqual(ok(expected));
495+
});
489496
});
490497

491498
describe('null types', () => {
492-
test("non null value", () => {
499+
test('non null value', () => {
493500
const value = { foo: 'bar' };
494-
const result: Result<string, string | null> = Decode.orNull(Decode.field('foo', Decode.str)).decodeValue(value)
501+
const result: Result<string, string | null> = Decode.orNull(Decode.field('foo', Decode.str)).decodeValue(value);
495502
expect(result).toEqual(ok('bar'));
496-
})
503+
});
497504

498-
test("null value", () => {
505+
test('null value', () => {
499506
const value = { foo: null };
500-
const result: Result<string, string | null> = (Decode.field('foo', Decode.orNull(Decode.str))).decodeValue(value)
507+
const result: Result<string, string | null> = Decode.field('foo', Decode.orNull(Decode.str)).decodeValue(value);
501508
expect(result).toEqual(ok(null));
502-
})
509+
});
503510

504-
test("typical use case", () => {
511+
test('typical use case', () => {
505512
type MyType = {
506513
gnu: number | null;
507-
foo: string | null
508-
}
514+
foo: string | null;
515+
};
509516
const value = { foo: null, gnu: null };
510517
const expected: MyType = {
511518
foo: null,
512-
gnu: null
519+
gnu: null,
513520
};
514-
expect(Decode.map2(
515-
(foo, gnu) => { return { foo, gnu } },
516-
Decode.field('foo', Decode.orNull(Decode.str)),
517-
Decode.field('gnu', Decode.orNull(Decode.num)))
518-
.decodeValue(value)
521+
expect(
522+
Decode.map2(
523+
(foo, gnu) => {
524+
return { foo, gnu };
525+
},
526+
Decode.field('foo', Decode.orNull(Decode.str)),
527+
Decode.field('gnu', Decode.orNull(Decode.num)),
528+
).decodeValue(value),
519529
).toEqual(ok(expected));
520-
})
521-
})
530+
});
531+
});

0 commit comments

Comments
 (0)