I'm trying to test a form submit, the problem is that I'm using a Material-ui Slider, and I'm not sure on how to trigger a value change on it.
This is my form component:
/* eslint-disable react/jsx-props-no-spreading */
import React from "react";
import { Formik, Form, Field, useFormikContext, FieldProps } from "formik";
import * as Yup from "yup";
import {
Button,
Grid,
Slider as MuiSlider,
Switch,
TextField,
Typography,
} from "@material-ui/core";
import { useDispatch } from "react-redux";
import Currency from "../../utils/Currency";
import api from "../../services/api";
import { openSnackbar } from "../../actions/snackbarActions";
import { IForm, IChannelResponse, ISliderProps, IProps } from "./interfaces";
const initialValues: IForm = {
publicKey: "",
socket: "",
tokens: 0,
private: false,
};
const validationSchema = Yup.object().shape({
publicKey: Yup.string().defined("You need to fill you node's public id"),
socket: Yup.string().defined(
"You need to fill your node's IP or onion address"
),
tokens: Yup.number()
.max(500000, "The maximum amount is 500,000 sats")
.min(10000, "The minimum amount is 10,000 sats"),
private: Yup.boolean(),
});
const Slider: React.FC<ISliderProps & FieldProps> = ({
field: { name, value },
label,
valueLabel,
error,
helperText,
...rest
}) => {
const { setFieldValue } = useFormikContext();
const handleChange = (
event: React.ChangeEvent<unknown>,
newValue: number | number[]
) => {
if (name) {
setFieldValue(name, newValue, true);
}
};
return (
<Grid container spacing={1}>
{label && (
<Grid item xs={12}>
<Typography>{label}</Typography>
</Grid>
)}
<Grid item xs={12}>
<MuiSlider name={name} onChange={handleChange} {...rest} />
{error && (
<Typography
color="error"
style={{ fontSize: "0.75rem", lineHeight: 1.66 }}
>
{helperText}
</Typography>
)}
</Grid>
<Grid item xs={12}>
<Typography align="right">
{Currency(value, { precision: 0 }).format()} {valueLabel}
</Typography>
</Grid>
</Grid>
);
};
export const ChannelOpen: React.FC<IProps> = ({ walletBalance }) => {
const dispatch = useDispatch();
const handleOpenChannel = async ({
values,
}: {
values: IForm;
}): Promise<void> => {
try {
const { data } = await api.post<IChannelResponse>(
"/lightning/openchannel",
{
tokens: values.tokens,
is_private: values.private,
public_key: values.publicKey,
socket: values.socket,
}
);
dispatch(
openSnackbar({
message: `Channel opened! Funding TXID: ${data.transactionId}`,
status: "success",
})
);
} catch (e) {
dispatch(
openSnackbar({ message: "Failed to open the channel", status: "error" })
);
}
};
return (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={async (values, { setSubmitting }) => {
await handleOpenChannel({ values });
setSubmitting(false);
}}
>
{({ isSubmitting, errors, touched }) => (
<Form>
<Grid container spacing={2}>
<Grid item xs={12}>
<Field
name="publicKey"
label="Your node's public key"
as={TextField}
fullWidth
placeholder="02a4ee943caeb847398960230bccc19937dd04834e768472b711a4ce0e2c77cd98"
error={!!(touched.publicKey && errors.publicKey)}
helperText={touched.publicKey && errors.publicKey}
/>
</Grid>
<Grid item xs={12}>
<Field
name="socket"
label="Your IP and port or onion and port"
as={TextField}
fullWidth
placeholder="g4xc7yl2shtllx564dv7wqelnqh2gjco6k5vd77upz3rgzozugpkmkad.onion:9735"
error={!!(touched.socket && errors.socket)}
helperText={touched.socket && errors.socket}
/>
</Grid>
<Grid item xs={12}>
<Field
name="tokens"
label="Amount"
component={Slider}
min={10000}
max={walletBalance > 500000 ? 500000 : walletBalance}
step={10000}
valueLabel="sats"
error={!!(touched.tokens && errors.tokens)}
helperText={touched.tokens && errors.tokens}
/>
</Grid>
<Grid item xs={12} container>
<Grid item xs={6}>
<Typography>Make this channel private</Typography>
</Grid>
<Grid item xs={6} container justify="flex-end">
<Field name="private" as={Switch} color="primary" />
</Grid>
</Grid>
<Grid item xs={12}>
<Button
type="submit"
fullWidth
variant="outlined"
disabled={isSubmitting}
>
Open channel
</Button>
</Grid>
</Grid>
</Form>
)}
</Formik>
);
};
And this is the test I'm trying to make it work:
it("should submit a form to open a channel", async () => {
const { container } = render(
<Provider store={store}>
<ChannelOpen walletBalance={1000000} />
</Provider>
);
userEvent.type(
screen.getByPlaceholderText(
"02a4ee943caeb847398960230bccc19937dd04834e768472b711a4ce0e2c77cd98"
),
"100000"
);
userEvent.type(
screen.getByPlaceholderText(
"g4xc7yl2shtllx564dv7wqelnqh2gjco6k5vd77upz3rgzozugpkmkad.onion:9735"
),
"192.168.0.100:9735"
);
const sliderElement = container.querySelector("input[name='tokens']");
if (sliderElement) {
await waitFor(() =>
fireEvent.change(sliderElement, { target: { value: 500000 } })
);
}
userEvent.click(screen.getByText("Open channel"));
await waitFor(() =>
expect(screen.getByText(/Channel opened!/i)).toBeInTheDOM()
);
});
Whenever I run the test, the value of the slider is NaN. How should I trigger a value change on it?
Thanks in advance!