how to test fetch request url in jest react test library - reactjs

var checkBox = document.getElementById("myCheck");
var checkBoxChecked = "false";
if (checkBox.checked == true){
checkBoxChecked = "true";
}
const uri = 'https://jsonplaceholder.typicode.com/posts?exact' + checkBoxChecked;
const initDetails = {
method: 'get',
headers: {
"Content-Type": "application/json; charset=utf-8"
},
mode: "cors"
}
function getData() {
fetch(uri, initDetails)
.then(response => {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
console.log(response.headers.get("Content-Type"));
return response.json();
}
)
.then(myJson => {
console.log(JSON.stringify(myJson));
})
.catch(err => {
console.log('Fetch Error :-S', err);
});
}
window.onload=function() {
let myButton = document.getElementById("getData");
myButton.addEventListener('click', getData);
}
<!DOCTYPE html>
<html>
<body>
<h2>HTML Forms</h2>
<form action="/action_page.php">
<label for="fname">Search:</label><br>
<input type="text" id="fname" name="fname" value="John">
  <input type="radio" id="myCheck" name="fav_language" value="HTML">
  <label for="html">Exact</label><br><br>
<input type="submit" id="getData" value="Submit">
</form>
<script>
</script>
</body>
</html>
I have one text box and radio button name is exact
Onsubmit i call fetch api.
I need to check fetch api request url have exact query parameter
if exact parameter is not added in request fetch api call it will be error.
if exact parameter not added in fetch api request i need to throw error in rtl test case.
URL: https://jsonplaceholder.typicode.com/posts?exact=true
EX: expect(fetch.url()).toContain('?exact=true');

Related

Buildfire: Plugin Functions on Android But Not On iOS

1We have a plugin deployed on the buildfire platform that is a standalone model. We use OAuth from the login screen presented upon accessing the plugin within our app. This plugin is made up of API calls into one of our vendor partners platforms. The entire plugin is written using JavaScript, HTML and CSS. It functions perfectly on Android devices and in testing from Windows PCs, however, iOS devices do not work. Using the same credentials, verified on an Android device, iOS devices immediately throw a login error. Need direction on what might be causing this. Login code in post. screenshot of error
function setToken() {
let header = document.getElementById("loginHeader");
let user = document.getElementById("username");
let pw = document.getElementById("password");
const bodyText = 'grant_type=cloud_contact&username=' + user.value + '&password=' + pw.value;
console.log(bodyText);
fetch('https://example.cloud.com/oauth/token', {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
timeout: 0,
mode: 'cors', // no-cors, *cors, same-origin
headers: {
'Content-Type': 'text/plain'
},
body: bodyText
})
.then(response => response.json())
.then(data => {
header.innerHTML = 'logging in...';
let token = data.access_token;
if (token) {
authManager.enforceLogin();
buildfire.userData.save({ token }, "myToken", (err, result) => {
if (err) console.log("error in setToken(): " + err);
});
header.innerHTML = "Login successful";
console.log('login successful and token saved successfully');
} else {
header.innerHTML = "Login failed";
}
})
.then(noObject => {
navHome();
})
.catch(error => console.log('try again', error));
}
function loggedIn() {
console.log("checking login...");
authManager.enforceLogin();
buildfire.userData.get("myToken", (err, response) => {
if (err) console.log('login error in loggedIn(): ' + err);
if (response) {
if (!response.data.token) {
navToLogin();
}
console.log("we have a response token");
fetch('https://example.cloud.com/api/userinfo?token=' + response.data.token, {
method: 'GET', // *GET, POST, PUT, DELETE, etc.timeout: 0,
mode: 'cors', // no-cors, *cors, same-origin
})
.then(response => response.json())
.then(result => {
let contexts = result.contexts;
buildfire.userData.save({ contexts }, "contexts", (err, result) => {
if (err) console.log("error saving contexts: " + err);
});
})
.catch(error => redoLogin('error using token to verify login', error));
}
});
return checkLogin();
}
function checkLogin() {
var retVal = true;
buildfire.userData.get("myToken", (err, response) => {
if (err) console.log('error in checkLogin(): ' + err);
if (response) {
console.log("we have a response token");
fetch('https://example.cloud.com/api/customers/0/activity/search?token=' + response.data.token, {
method: 'GET', // *GET, POST, PUT, DELETE, etc.timeout: 0,
mode: 'cors', // no-cors, *cors, same-origin
})
.then(response => response.json())
.catch(error => redoLogin('error using token to verify login', error));
console.log("token is valid");
retVal = true;
} else {
console.log("invalid response");
retVal = false;
}
});
return retVal;
}
function redoLogin(message) {
console.log(message);
logoutAndNavToLogin();
}
function console.log(data) {
let logBox = document.getElementById("logBox");
if (logBox) {
logBox.innerHTML += 'Log: ' + data + '. ';
}
console.log(data);
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="../../../scripts/buildfire.js"></script>
<body>
<div>
<p class="page-header text-center text-info" id="loginHeader">Enter your BoldNet credentials</p>
</div>
<form action="setToken()">
<div class="container">
<div class="form-group">
<p class="text-muted">Username:</p>
<input class="form-control" id="username"></input>
<p class="text-muted">Password:</p>
<input class="form-control" type="password" id="password"></input>
</div>
<form-button class="btn btn-primary" type="submit" onclick="setToken()">Login</form-button>
</div>
</form>
<div>
<p id="logBox"></p>
</div>
<script src="login.js"></script>
<script src="nav.js"></script>
<script src="authManager.js"></script>
<script src="dal.js"></script>
</body>
</html>
This does not seem like an issue with BuildFire OAuth since it does not seem to be using BuildFire OAuth but rather a custom code setting user data to the standard BuildFire login user.
You can troubleshoot by creating a testing version of the plugin with some logging on the UI to see where it is exactly failing on iOS.
Here is also link that explains how to integrate with BuildFire OAuth 2 https://sdk.buildfire.com/docs/using-oauth2-sign-in-integration/

Struggling with PUT request

I'm on React for 2 months, and still struggling with CRUD operations such as EDIT.
I've been trying couple different ways, but every time I send nothing to my API.
I do not manage to grab the information correctly in order to push it to the server.
The route is working with Postman, there are no issues there, it's only React and me ^^.
I would be grateful if someone could read my code and tell me where the problem might come from, thanks !
1st try
const usernamelEl = React.useRef(null)
const timezoneEl = React.useRef(null)
const handleEditProfile = async () => {
const creds = {
user: {
username: usernameEl.current.value,
timezone: timezoneEl.current.value
}
};
const config = {
method: 'PUT',
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"Authorization": `Bearer ${Cookies.get('token')}`
},
body: JSON.stringify(creds)
};
const res = await fetch(`${process.env.REACT_APP_API_URL}api/users/${id}`, config);
const user = await res.json();
console.log(user)
}
return (
<form onSubmit={handleEditProfile} className="form">
<div className="input-group">
<label htmlFor="username">username</label>
<input type="text" id="username" ref={usernameEl}/>
</div>
<div className="input-group">
<label htmlFor="timezone">timezone</label>
<input type="text" id="timezone" ref={timezoneEl}/>
</div>
<div className="input-group">
<SubmitButtonComponent type="submit">
Submit
</SubmitButtonComponent>
</div>
</form>
)
2nd try
const [usernameEl, setUsernameEl] = useState('')
const [timezoneEl, setTimezoneEl] = useState('')
const handleChangeUsername = e => {
setUsernameEl(e.target.value)
}
const handleChangeTimezone= e => {
setTimezoneEl(e.target.value)
}
const handleEditProfile = async (e) => {
const creds = {
user: {
username: usernameEl,
timezone: timezoneEl
}
};
const config = {
method: 'PUT',
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"Authorization": `Bearer ${Cookies.get('token')}`
},
body: JSON.stringify(creds)
};
const res = await fetch(`${process.env.REACT_APP_API_URL}api/users/${id}`, config);
const data = await res.json();
console.log(data)
try {
setUsernameEl('')
setTimezoneEl('')
}
catch(err) {
console.log(err)
}
}
return (
<form className="form" onSubmit={handleEditProfile}>
<div className="input-group">
<label htmlFor="username">username</label>
<input type="text" id="username" onChange={handleChangeUsername}/>
</div>
<div className="input-group">
<label htmlFor="timezone">timezone</label>
<input type="text" id="timezone" onChange={handleChangeTimezone}/>
</div>
<SubmitButtonComponent type="submit">
Submit
</SubmitButtonComponent>
</form>
if I ever try to pass a value
const handleEditProfile = async (e) => {
e.preventDefault();
[..]
onSubmit={(e)=>handleEditProfile(e.target.value)}>
or
onSubmit={handleEditProfile(e)>
then I get this error

Keep on getting 400 (Bad Request) on a POST request

So I'm trying to make a request to a database I have set up. The point is to send a POST to add to the table and for it to feed my back the full list.
I keep on getting "POST http://localhost:8000/api/folders 400 (Bad Request)" in the console. I know it's the POST as when I check the database on both DBeaver and POSTman the database remains the same.
I tried writing '"name"' as 'name' and that didn't change anything.
const postfolder = {
method: 'POST',
body: JSON.stringify({ "name" : f })
};
const getFolder = {
method: 'GET'
};
fetch(`${config.API_ENDPOINT}/folders`, postfolder)
.then(
fetch(`${config.API_ENDPOINT}/folders`, getFolder)
)
.then(res => {
if (!res.ok)
return res.json().then(e => Promise.reject(e))
})
.then(folders => {
this.setState({folders : folders});
})
.catch( error =>{
console.error({ error });
console.log("I fucked up the coding: 001");
});
EDIT:
For clarity here is the component that defines f. Though I did have a console.log (not seen in above) that checks the value and it's giving me the correct one.
import React, {Component} from 'react';
//import { NavLink, Link } from 'react-router-dom'
import './AddFolder.css';
export default class AddFolder extends Component{
handleSubmit = (e) => {
e.preventDefault();
console.log("handleSubmit ran");
var nameError = document.getElementById("folderNameError");
if (!e.target.name.value){
nameError.classList.remove("hidden");
return console.log("no name");
}
nameError.classList.add("hidden");
return this.props.addNewFolder(e.target.name.value);
// process form values here
}
render(){
return (
<form className="folderForm" onSubmit={(e) => this.handleSubmit(e)}>
<h3>New Folder</h3>
<label>Text </label>
<input type="text" className="elementName" name="name" id="folderName"/>
<div>
<button type="submit" className="registration__button">
Save
</button>
</div>
<div>
<button type="reset" className="registration__button">
Cancel
</button>
</div>
<div className="errorSpace">
<p className="hidden" id="folderNameError">A name is required</p>
</div>
</form>
)
}
}
Here's a quick picture of the database. It's just a name and an id.
I'm able to fetch to it using POSTMAN so I don't believe it's the issue.
So I found out that the issue was that I needed to add to my fetch request.
I had it as:
const postfolder = {
method: 'POST',
body: JSON.stringify({ "name" : f })
};
It should be:
const postfolder = {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify(newFolder)
};
I needed the content-type.

Curl works but React App throwing Cannot POST / error while using Axios and Express

I am trying to implement a simple form to send email. The error that I am getting is
Cannot POST /
I've used Create React App and the App.js looks like below:-
import React, { Component } from 'react';
//import logo from './logo.svg';
import './App.css';
import axios from 'axios';
import renderEmail from 'axios';
import MyEmail from 'axios';
class App extends Component {
state = {
data: null
};
componentDidMount() {
// Call our fetch function below once the component mounts
this.callBackendAPI()
.then(res => this.setState({ data: res.express }))
.catch(err => console.log(err));
}
// Fetches our GET route from the Express server
callBackendAPI = async () => {
const response = await fetch('/express_backend');
const body = await response.json();
if (response.status !== 200) {
throw Error(body.message)
}
return body;
};
handleSubmit(event){
const messageHtml = renderEmail(
<MyEmail name={this.state.name}> {this.state.feedback}</MyEmail>
);
axios({
method: "POST",
url:"http://localhost:3000/send",
data: {
name: this.state.name,
email: this.state.email,
messageHtml: messageHtml
}
}).then((response)=>{
if (response.data.msg === 'success'){
alert("Email sent, awesome!");
this.resetForm()
}else if(response.data.msg === 'fail'){
alert("Oops, something went wrong. Try again")
}
})
}
resetForm(){
this.setState({feedback: ''});
}
render() {
return (
<form id="contact-form" method="POST">
<div className="form-group">
<label htmlFor="name">Name</label>
<input type="text" className="form-control" id="name" />
</div>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" id="email" aria-describedby="emailHelp" />
</div>
<div className="form-group">
<label htmlFor="message">Message</label>
<textarea className="form-control" rows="5" id="message"></textarea>
</div>
<button type="submit" className="btn btn-primary" onClick={this.handleSubmit}>Submit</button>
</form>
);
}
}
export default App;
The server.js look like the below:-
const express = require('express');
const app = express();
const port = process.env.PORT || 5000;
var nodemailer = require('nodemailer');
const creds = require('./config');
// console.log that your server is up and running
app.listen(port, () => console.log(`Listening on port ${port}`));
// create a GET route
app.get('/express_backend', (req, res) => {
res.send({ express: 'YOUR EXPRESS BACKEND IS CONNECTED TO REACT' });
});
var transport = {
host: 'host', // e.g. smtp.gmail.com
//service: 'gmail',
port: 465,
secure: true,
auth: {
user: 'xxxxx',
pass: 'xxxxx'
},
tls: {
// do not fail on invalid certs
rejectUnauthorized: false
}
}
var transporter = nodemailer.createTransport(transport)
transporter.verify((error, success) => {
if (error) {
console.log(error);
} else {
console.log('All works fine, congratz!');
}
});
app.use(express.json());
app.post('/send', (req, res, next) => {
const name = req.body.name
const email = req.body.email
const message = req.body.messageHtml
var mail = {
from: name,
to: 'abc#gmail.com',
subject: 'Contact form',
html: message
}
transporter.sendMail(mail, (err, data) => {
if (err) {
res.json({
msg: 'fail'
})
} else {
res.json({
msg: 'success'
})
}
})
});
I have checked with curl and the localhost:3000/send is working properly and returns success. Please help! Thank you.
Have you tried enabling CORS in your server so as to enable React interact with your back end server?

Displaying rest api response data in react

Here response data contains{name ,details} fields. I have a upload button to upload single/multi files. After uploading files, I don't refresh the page. Now for ex, I upload single file and displayed the response. Again I upload 2 files. Now I should be able to display response of current upload as well as previous one. It should be in the following format:
1.Name1
Details1
2. Name2
Details2
3. Name3
Details 3
this.state.list = this.state.list.concat(details);
this.state.list_name = this.state.list_name.concat(name);
< form onSubmit={this.handleSubmit} >
<label>
Upload a file: <br /><br />
<input type="file" name="file" multiple onChange{this.onChangeHandler}/>
</label>
<br /><br />
<button type="submit">
Upload</button>
</form >
<ol>
// {this.state.list_name.map((k) =>
// <li>{k} :</li>)}
//{this.state.list.map((k) =>
// <li>{k}</li>
// )}
</ol>
handleSubmit = (event) => {
event.preventDefault();
const formData = new FormData();
for (var x = 0; x < this.state.selectedFile.length; x++) {
formData.append('inputFile', this.state.selectedFile[x])
fetch('url', {
method: 'POST',
body: formData
}).then(res => {
return res.json()
})
.then((res) => {
this.setState({
details: res.data.details,
name: res.data.name
})
console.log("res data", res)
//console.log("Data is", res.data.name) //displays name in the console
})
.catch(error => console.log('ERROR message'))
}
};
I have commented the code that I have tried. Thanks in advance.
you can do this
remove this
this.state.list = this.state.list.concat(details);
this.state.list_name = this.state.list_name.concat(name);
add this
fetch('url', {
method: 'POST',
body: formData
}).then(res => {
return res.json()
})
.then((res) => {
const list = this.state.list;
list.concat(res.data.details);
const list_name = this.state.list_name;
list_name.concat(name);
this.setState({
list,
list_name,
details: res.data.details,
name: res.data.name
})
console.log("res data", res)
//console.log("Data is", res.data.name) //displays name in the console
})
.catch(error => console.log('ERROR message'))
}

Resources