• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cartesi / rollups-explorer / 10491533758

21 Aug 2024 02:11PM CUT coverage: 93.391% (-0.4%) from 93.766%
10491533758

Pull #232

github

nevendyulgerov
test(apps/web): Add unit tests for specifications v1 validator
Pull Request #232: #229 Add import and export for specifications

1211 of 1433 branches covered (84.51%)

Branch coverage included in aggregate %.

487 of 570 new or added lines in 9 files covered. (85.44%)

50 existing lines in 10 files now uncovered.

12863 of 13637 relevant lines covered (94.32%)

45.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.17
/apps/web/src/components/specification/form/SpecificationForm.tsx
1
import {
1✔
2
    Button,
1✔
3
    Card,
1✔
4
    Group,
1✔
5
    SegmentedControl,
1✔
6
    Stack,
1✔
7
    TextInput,
1✔
8
} from "@mantine/core";
1✔
9
import { FC, useCallback, useEffect, useRef, useState } from "react";
1✔
10

1✔
11
import { useScrollIntoView } from "@mantine/hooks";
1✔
12
import { formatAbi } from "abitype";
1✔
13
import { clone, pathOr, propOr } from "ramda";
1✔
14
import { isFunction, isNotNilOrEmpty } from "ramda-adjunct";
1✔
15
import { Abi } from "viem";
1✔
16
import { SpecificationModeInfo } from "../components/ModeInfo";
1✔
17
import { useSpecification } from "../hooks/useSpecification";
1✔
18
import { Modes, Predicate, SliceInstruction, Specification } from "../types";
1✔
19
import { buildSpecification } from "../utils";
1✔
20
import { SpecFormValues, useSpecFormContext } from "./context";
1✔
21
import { ByteSlices, byteSlicesFormActions } from "./fields/ByteSlices";
1✔
22
import { Conditions, conditionsFormActions } from "./fields/Conditions";
1✔
23
import {
1✔
24
    HumanReadableABI,
1✔
25
    humanReadableABIFormActions,
1✔
26
} from "./fields/HumanReadableABI";
1✔
27
import {
1✔
28
    HumanReadableABIParameter,
1✔
29
    humanReadableABIParameterFormActions,
1✔
30
} from "./fields/HumanReadableABIParameter";
1✔
31

1✔
32
const editModeStartup = (transformedValues: SpecFormValues) => {
1✔
33
    humanReadableABIFormActions.setFieldValue(
2✔
34
        "humanABIEntry",
2✔
35
        formatAbi(transformedValues.abi ?? []).join("\n"),
2!
36
    );
2✔
37
    humanReadableABIParameterFormActions.setFieldValue(
2✔
38
        "entries",
2✔
39
        transformedValues.abiParams,
2✔
40
    );
2✔
41

2✔
42
    byteSlicesFormActions.setValues((prev) => {
2✔
43
        return {
×
44
            slices: propOr(prev.slices, "sliceInstructions", transformedValues),
×
45
            sliceTarget: propOr(
×
46
                prev.sliceTarget,
×
47
                "sliceTarget",
×
48
                transformedValues,
×
49
            ),
×
50
            sliceTargetChecked: isNotNilOrEmpty(transformedValues.sliceTarget),
×
51
        };
×
52
    });
2✔
53

2✔
54
    conditionsFormActions.setValues((prev) => ({
2✔
55
        conditions: pathOr(
2✔
56
            prev.conditions,
2✔
57
            ["conditionals", "0", "conditions"],
2✔
58
            transformedValues,
2✔
59
        ),
2✔
60
        logicalOperator: pathOr(
2✔
61
            prev.logicalOperator,
2✔
62
            ["conditionals", "0", "logicalOperator"],
2✔
63
            transformedValues,
2✔
64
        ),
2✔
65
    }));
2✔
66
};
2✔
67

1✔
68
interface SpecificationFormProps {
1✔
69
    onSuccess: (newSpecification: Specification) => void;
1✔
70
    onFailure: (reason: Error) => void;
1✔
71
}
1✔
72

1✔
73
export const SpecificationForm: FC<SpecificationFormProps> = ({
1✔
74
    onFailure,
135✔
75
    onSuccess,
135✔
76
}) => {
135✔
77
    const [submitting, setSubmitting] = useState(false);
135✔
78
    const { addSpecification, updateSpecification } = useSpecification();
135✔
79
    const form = useSpecFormContext();
135✔
80
    const transformedValues = form.getTransformedValues();
135✔
81
    const { scrollIntoView, targetRef } = useScrollIntoView<HTMLInputElement>({
135✔
82
        duration: 700,
135✔
83
        offset: 150,
135✔
84
        cancelable: true,
135✔
85
    });
135✔
86

135✔
87
    const initialValRef = useRef<SpecFormValues | null>(null);
135✔
88
    const { mode } = transformedValues;
135✔
89
    const { setFieldValue } = form;
135✔
90

135✔
91
    if (transformedValues.formMode === "EDITION" && !initialValRef.current)
135✔
92
        initialValRef.current = clone(transformedValues);
135✔
93

135✔
94
    const onAbiChange = useCallback(
135✔
95
        (abi: Abi) => {
135✔
96
            setFieldValue("abi", abi);
30✔
97
        },
30✔
98
        [setFieldValue],
135✔
99
    );
135✔
100

135✔
101
    const onConditionalsChange = useCallback(
135✔
102
        (conditionals: Predicate[]) => {
135✔
103
            setFieldValue("conditionals", conditionals);
6✔
104
        },
6✔
105
        [setFieldValue],
135✔
106
    );
135✔
107

135✔
108
    const onConditionalSwitch = useCallback(
135✔
109
        (active: boolean) => {
135✔
110
            setFieldValue("conditionalsOn", active);
1✔
111
        },
1✔
112
        [setFieldValue],
135✔
113
    );
135✔
114

135✔
115
    const onSlicesSwitch = useCallback(
135✔
116
        (active: boolean) => {
135✔
117
            setFieldValue("sliceInstructionsOn", active);
7✔
118
        },
7✔
119
        [setFieldValue],
135✔
120
    );
135✔
121

135✔
122
    const onSliceInstructionsChange = useCallback(
135✔
123
        (slices: SliceInstruction[]) =>
135✔
124
            setFieldValue("sliceInstructions", slices),
13✔
125
        [setFieldValue],
135✔
126
    );
135✔
127

135✔
128
    const onSliceTargetChange = useCallback(
135✔
129
        (target?: string) => setFieldValue("sliceTarget", target),
135✔
130
        [setFieldValue],
135✔
131
    );
135✔
132

135✔
133
    const onAbiParamsChange = useCallback(
135✔
134
        (params: string[]) => setFieldValue("abiParams", params),
135✔
135
        [setFieldValue],
135✔
136
    );
135✔
137

135✔
138
    const { errors } = form;
135✔
139

135✔
140
    const onComplete = (specification: Specification) => {
135✔
141
        isFunction(onSuccess) && onSuccess(specification);
3✔
142

3✔
143
        scrollIntoView({ alignment: "center" });
3✔
144
        initialValRef.current = null;
3✔
145
        form.reset();
3✔
146
        humanReadableABIFormActions.reset();
3✔
147
        byteSlicesFormActions.reset();
3✔
148
        humanReadableABIParameterFormActions.reset();
3✔
149
        conditionsFormActions.reset();
3✔
150
    };
3✔
151

135✔
152
    useEffect(() => {
135✔
153
        if (initialValRef.current) {
22✔
154
            editModeStartup(initialValRef.current);
2✔
155
        }
2✔
156
    }, []);
135✔
157

135✔
158
    return (
135✔
159
        <Card shadow="sm" withBorder>
135✔
160
            <form
135✔
161
                onSubmit={form.onSubmit((values) => {
135✔
162
                    const specification = buildSpecification(values);
5✔
163
                    if (form.isValid() && specification !== null) {
5✔
164
                        setSubmitting(true);
5✔
165
                        const lifecycle = {
5✔
166
                            onFinished: () => setSubmitting((v) => !v),
5✔
167
                            onSuccess: () => onComplete(specification),
5✔
168
                            onFailure,
5✔
169
                        };
5✔
170

5✔
171
                        values.formMode === "EDITION"
5✔
172
                            ? updateSpecification(specification, lifecycle)
2✔
173
                            : addSpecification(specification, lifecycle);
3✔
174
                    } else {
5!
UNCOV
175
                        form.validate();
×
UNCOV
176
                    }
×
177
                })}
135✔
178
            >
135✔
179
                <Stack>
135✔
180
                    <TextInput
135✔
181
                        ref={targetRef}
135✔
182
                        data-testid="specification-name-input"
135✔
183
                        label="Name"
135✔
184
                        description="Specification name for ease identification"
135✔
185
                        placeholder="My Spec name"
135✔
186
                        withAsterisk
135✔
187
                        {...form.getInputProps("name")}
135✔
188
                    />
135✔
189

135✔
190
                    <SegmentedControl
135✔
191
                        aria-labelledby="specification-mode-label"
135✔
192
                        aria-label="Specification Mode"
135✔
193
                        data={[
135✔
194
                            {
135✔
195
                                label: "JSON ABI",
135✔
196
                                value: "json_abi",
135✔
197
                            },
135✔
198
                            {
135✔
199
                                label: "ABI Parameters",
135✔
200
                                value: "abi_params",
135✔
201
                            },
135✔
202
                        ]}
135✔
203
                        {...form.getInputProps("mode")}
135✔
204
                        onChange={(value) => {
135✔
205
                            const mode = value as Modes;
13✔
206
                            const changes =
13✔
207
                                mode === "json_abi"
13!
UNCOV
208
                                    ? { mode, abiParams: [] }
×
209
                                    : mode === "abi_params"
13✔
210
                                    ? { mode, abi: undefined }
13!
UNCOV
211
                                    : { mode };
×
212

13✔
213
                            form.setValues(changes);
13✔
214
                        }}
13✔
215
                    />
135✔
216
                    <SpecificationModeInfo mode={mode} />
135✔
217
                    {mode === "json_abi" ? (
135✔
218
                        <HumanReadableABI
92✔
219
                            onAbiChange={onAbiChange}
92✔
220
                            error={errors.abi}
92✔
221
                        />
92✔
222
                    ) : mode === "abi_params" ? (
43✔
223
                        <>
43✔
224
                            <HumanReadableABIParameter
43✔
225
                                error={errors.abiParams}
43✔
226
                                onAbiParamsChange={onAbiParamsChange}
43✔
227
                            />
43✔
228
                            <ByteSlices
43✔
229
                                onSliceInstructionsChange={
43✔
230
                                    onSliceInstructionsChange
43✔
231
                                }
43✔
232
                                onSliceTargetChange={onSliceTargetChange}
43✔
233
                                onSwitchChange={onSlicesSwitch}
43✔
234
                                error={errors.sliceInstructions}
43✔
235
                                isActive={transformedValues.sliceInstructionsOn}
43✔
236
                            />
43✔
237
                        </>
43!
UNCOV
238
                    ) : (
×
UNCOV
239
                        <></>
×
240
                    )}
135✔
241
                    <Conditions
135✔
242
                        onConditionalsChange={onConditionalsChange}
135✔
243
                        onSwitchChange={onConditionalSwitch}
135✔
244
                        error={errors.conditionals}
135✔
245
                        isActive={transformedValues.conditionalsOn}
135✔
246
                    />
135✔
247
                    <Group justify="flex-end">
135✔
248
                        <Button
135✔
249
                            type="submit"
135✔
250
                            loading={submitting}
135✔
251
                            data-testid="specification-form-save"
135✔
252
                        >
135✔
253
                            {transformedValues.formMode === "EDITION"
135✔
254
                                ? "Update"
15✔
255
                                : "Save"}
120✔
256
                        </Button>
135✔
257
                    </Group>
135✔
258
                </Stack>
135✔
259
            </form>
135✔
260
        </Card>
135✔
261
    );
135✔
262
};
135✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc