I have created a register
component using react-bootstrap
. It has email
, password
and submit button
fields in a form. At the end, it has an Alert
component which should not be visible initially but should show success/failure once the form has been submitted
import React from 'react';
import {Col, Row, Container, Card,Button, Alert} from 'react-bootstrap'
import Form from 'react-bootstrap/Form';
import { useState } from 'react';
import User from '../models/user';
let Register = () => {
let [state,setState] = useState(new User('',''));
let submitresponse='';
let alertvariant='';
let updateInput = (e) =>{
setState({
...state, //state defined above in useState call. Expand the current state and then override the propoerty which target represents
[e.target.name] : e.target.value
})
}
let register = (e) =>{
e.preventDefault();
console.log(`registerclick: ${JSON.stringify(state)}`)
fetch(process.env.REACT_APP_REGISTER_USER_URL,{
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify(state)
}) //move to separate funcion in separate file to make it easy to test and reuse?
.then((res) => {
console.log(`got response: ${JSON.stringify(res)}`);
return res.json(); //return json from res
})
.then((data) => { //data is the json returned previously. Promise chaining
console.log(`data after register user request: ${JSON.stringify(data)}`);
if(data.result == "success") {
setState(new User(data.user,data.email)) //override previous value of data object with value of received json object.
this.submitresponse = "User Registered"
} else {
setState(new User('','')) //override previous value of data object with value of received json object.
this.submitresponse = "User Couldn't be Registered"
}
});
}
return (
<>
<Container className='mt-3'>
<Row>
<Col xs={3}>
<Card className="shadow-lg">
<Card.Header className='p-3'>
Register
</Card.Header>
<Card.Body>
<Form>
<Form.Group className="mb-3">
<Form.Control name="email" onChange={updateInput} type="text" placeholder="email" aria-label="aria-email" />
</Form.Group>
<Form.Group className="mb-3">
<Form.Control name="password" onChange={updateInput} type="password" placeholder="password" aria-label="aria-password" />
</Form.Group>
<Form.Group className="mb-3">
<Button onClick={register} type="submit" name="submit-button" aria-label="aria-submit">Register Button</Button>
</Form.Group>
<Form.Group className="mb-3">
<Alert name="submit-response-alert" key={this.alertvariant} variant={this.alertvariant} >{this.submitresponse}</Alert>
</Form.Group>
</Form>
</Card.Body>
</Card>
</Col>
</Row>
</Container>
</>
)
}
export default Register;
How could I
Alert
initially? What is the way to dynamically set display:none
for exampleIn the tests, I want to test
Alert
shouldn't be in document initially
it('Should not show Alert field', async () => { render(); expect(screen.getByName("submit-response-alert")).not.toBeInTheDocument(); //Is this the right way? });
Once server response is received (mocked), Alert
should be visible with right message
it('Should successfully submit the form', async () => { const { getByText } = render();
await act(async () => {
fireEvent.click(getByText("Register Button"))
})
expect(screen.getByName("submit-response-alert")).toBeInTheDocument();
//how to test that the Alert has the right message });
set a state that tracks the progress of the request You can also add a message to it.
const [requestState , setRequestState] = useState({completed:false , message:""})
add this condition into jsx
{requestState.completed && <Alert name="submit-response-alert" key={this.alertvariant} variant={this.alertvariant} >{this.submitresponse}</Alert>}