Mirror of https://github.com/roostorg/coop
github.com/roostorg/coop
1import { isContainerField } from '@roostorg/types';
2import fc from 'fast-check';
3
4import {
5 ArrayFieldWithValueArbitrary,
6 FieldArbitrary,
7 MapFieldWithValueArbitrary,
8 ScalarFieldWithValueArbitrary,
9 ValidItemDataWithSchema,
10} from '../../test/arbitraries/ContentType.js';
11import { instantiateOpaqueType } from '../../utils/typescript-types.js';
12import {
13 getFieldValueOrValues,
14 getValuesFromFields,
15} from './extractItemDataValues.js';
16import { type NormalizedItemData } from './toNormalizedItemDataOrErrors.js';
17
18describe('getFieldValueOrValues', () => {
19 test('should return single values for scalar type fields', () => {
20 fc.assert(
21 fc.property(ScalarFieldWithValueArbitrary, ([field, value]) => {
22 // Manually instantiate opaque type because we trust our arbitraries to
23 // return field values that match the field type's normalized form.
24 const normalizedContent = instantiateOpaqueType<NormalizedItemData>({
25 x: true,
26 [field.name]: value,
27 });
28
29 expect(getFieldValueOrValues(normalizedContent, field)).toEqual({
30 type: field.type,
31 value,
32 });
33 }),
34 );
35 });
36
37 test('should return arrays for array type fields', () => {
38 fc.assert(
39 fc.property(ArrayFieldWithValueArbitrary, ([field, value]) => {
40 const normalizedContent = instantiateOpaqueType<NormalizedItemData>({
41 x: true,
42 [field.name]: value,
43 });
44
45 expect(getFieldValueOrValues(normalizedContent, field)).toEqual(
46 value.map((it) => ({
47 type: field.container.valueScalarType,
48 value: it,
49 })),
50 );
51 }),
52 );
53 });
54
55 test('should return value arrays for map type fields', () => {
56 fc.assert(
57 fc.property(MapFieldWithValueArbitrary, ([field, value]) => {
58 const normalizedContent = instantiateOpaqueType<NormalizedItemData>({
59 x: true,
60 [field.name]: value,
61 });
62
63 expect(getFieldValueOrValues(normalizedContent, field)).toEqual(
64 Object.values(value).map((it) => ({
65 type: field.container.valueScalarType,
66 value: it,
67 })),
68 );
69 }),
70 );
71 });
72
73 test("should return undefined or empty array if a field is missing in the submission, based on field's scalar-ness", () => {
74 fc.assert(
75 fc.property(FieldArbitrary, (field) => {
76 expect(
77 getFieldValueOrValues(
78 instantiateOpaqueType<NormalizedItemData>({}),
79 field,
80 ),
81 ).toEqual(isContainerField(field) ? [] : undefined);
82 }),
83 );
84 });
85});
86
87describe('getValuesFromFields', () => {
88 test("should always return an array that's the concatenation of the individual results", () => {
89 fc.assert(
90 fc.property(ValidItemDataWithSchema, ({ schema, data }) => {
91 // some subset of the final (merged) keys to check
92 const fieldsToCheck = schema.slice(0, 3);
93 const allValues = getValuesFromFields(data, fieldsToCheck);
94
95 const valuesOneByOne = fieldsToCheck.flatMap(
96 (field) => getFieldValueOrValues(data, field) ?? [],
97 );
98
99 expect(allValues).toEqual(valuesOneByOne);
100 }),
101 );
102 });
103});