The issue is regarding the unit testing using JEST.
How to test the a function X which is returning a promise which is making an async HTTP request.
Function X
import httpHelper from './httpHelper';
function fetchMoxtraAccessToken(userEWAToken, successCallback, failureCallback) {
const httpObj = {
url: '/getAccessToken',
headers: { Authorization: userEWAToken },
};
return httpHelper(httpObj, successCallback, failureCallback);
}
How to unit test the function X on the basis of the response?
The easiest way is to mock httpHelper so it just returns a spy on which you can test that is was called with the correct parameter:
jest.mock('./httpHelper', () = > jest.fn()) //Path must be relative to test file
import httpHelper from './httpHelper'
describe(('fetchMoxtraAccessToken') => {
it(('makes correct http request') => {
const userEWAToken = 'someUserEWAToken'
const successCallback = jest.fn()
const failureCallback = jest.fn()
fetchMoxtraAccessToken(userEWAToken, successCallback, failureCallback)
expect(httpHelper).toHaveBeenCalledWith({
url: '/getAccessToken',
headers: {
Authorization: 'someUserEWAToken'
},
}, successCallback, failureCallback)
})
})
Related
The full error: PUT http://127.0.0.1:8000/api/event/107 500 (Internal Server Error).
I am trying to update an existing event within my DB. I have the fetch() setup so it uses the 'PUT' method in my /api/event/${eventid}.
const eventid = arg.event.id;
console.log(arg.event.id); // ID is logged here
const eventData = { // Event Data to be sent off is here
start: arg.event.start.toISOString(),
end: arg.event.end.toISOString(),
};
const csrfToken = document.head.querySelector("[name~=csrf-token][content]").content;
fetch(`/api/event/${eventid}`, {
method: 'PUT',
headers: {
"X-CSRF-Token": csrfToken,
},
body: encodeFormData(eventData),
})
.then(response => console.log(response))
.catch(error => console.log(error));
console.log("Complete");
This connects to my route as such:
Route::put('/event/{eventid}', [CalendarController::class, 'update']);
which also connects to my Controller:
public function update(Request $request, $eventid)
{
dd($request->id);
$booking = Booking::findOrFail($eventid);
$booking->start_date = $request->start;
$booking->end_date = $request->end;
$booking->save();
return response()->json($booking);
}
How can I solve the 500 error? There is no obvious reason to me why it would fail to connect. Thanks.
You can also do this
https://laravel.com/docs/8.x/routing#form-method-spoofing
const eventid = arg.event.id;
console.log(arg.event.id);
const eventData = {
start: arg.event.start.toISOString(),
end: arg.event.end.toISOString(),
_method:"PUT" //add method field
};
const csrfToken = document.head.querySelector("[name~=csrf-token][content]").content;
fetch(`/api/event/${eventid}`, {
method: 'POST', // POST method
headers: {
"X-CSRF-Token": csrfToken,
},
body: encodeFormData(eventData),
})
.then(response => console.log(response))
.catch(error => console.log(error));
console.log("Complete");
I'm writing a vue app. I read this sample code and wrote code like this:
const apiKey = 'mykey';
const discoveryDocs = ["https://www.googleapis.com/discovery/v1/apis/drive/v3/rest"]
const clientId = 'myclientid'
const scopes = 'https://www.googleapis.com/auth/drive.appdata'
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
apiKey,
discoveryDocs,
clientId,
scope: scopes
}).then(function () {
createFile()
});
}
function createFile() {
console.log('createFile')
var fileMetadata = {
'name': 'config.json',
'parents': ['appDataFolder']
};
var media = {
mimeType: 'application/json',
body: "body"
};
gapi.client.drive.files.create({
resource: fileMetadata,
media,
fields: 'id'
}, function (err, file) {
console.log('function in createFile')
if (err) {
console.error(err);
} else {
console.log('Folder Id:', file.id);
}
});
}
window.onload=handleClientLoad()
In the console, 'createFile' is logged but 'function in createFile' is not logged, so I think function(err, file)... does not work.
What is wrong?
I want the sample code to work.
I had the same issue. The function create() returns a promise, to execute the request, it seems to need a then(). See also this post.
The example code though does not work since you will get a 403 The user does not have sufficient permissions for this file error. This seems to happen since example code will create the file not in appDataFolder but in the root directory.
I managed to get it to work using the following code. Putting all request parameters flat into the object passed to create() seems to do the trick.
const s = new Readable();
s.push("beep"); // the string you want
s.push(null);
gapi.client.drive.files
.create({
name: "config.json",
parents: ["appDataFolder"],
mimeType: "application/json",
upload_type: "media",
fields: "id",
body: s,
})
.then(function (response) {
if (response.status === 200) {
var file = response.result;
console.log(file);
}
})
.catch(function (error) {
console.error(error);
});
I would like to use Cypress for API testing. My goal is to extract a part of the API response and pass it to another API request. Here's a sample code:
Cypress.Commands.add('createCustomer', () => {
return cy.request({
method: 'POST',
url: 'api/v1/Customers',
headers: {
'Content-Type': 'application/json'
},
body: {
// sample content
}
}).then((response) => {
return new Promise(resolve => {
expect(response).property('status').to.equal(201)
expect(response.body).property('id').to.not.be.oneOf([null, ""])
const jsonData = response.body;
const memberId = jsonData.id
resolve(memberId)
return memberId
})
})
})
With this code, I am getting [object%20Object] as the result.
Hoping for some feedback.
So you are adding the id generated by the POST to a subsequent GET request?
Try returning the id without using a Promise, I don't think you need one at that point since the response has already arrived.
}).then((response) => {
expect(response).property('status').to.equal(201)
expect(response.body).property('id').to.not.be.oneOf([null, ""])
const jsonData = response.body;
const memberId = jsonData.id;
return memberId;
})
Url for GET
cy.createCustomer().then(id => {
const url = `api/v1/Customers${id}`;
...
or
cy.createCustomer().then($id => {
const id = $id[0]; // Not quite sure of the format, you may need to "unwrap" it
const url = `api/v1/Customers${id}`;
...
If you want to pass response from API Request 1 to API Request 2, you can do something like this:
describe('Example to demonstrate API Chaining in Cypress', function () {
it('Chain two API requests and validate the response', () => {
//Part 1
cy.request({
method: 'GET',
url: 'https://www.metaweather.com/api/location/search/?query=sn',
}).then((response) => {
const location = response.body[0].title
return location
})
//Part 2
.then((location) => {
cy.request({
method: 'GET',
url: 'https://www.metaweather.com/api/location/search/?query=' + location
}).then((response) => {
expect(response.status).to.eq(200)
expect(response.body[0]).to.have.property('title', location)
})
})
})
})
Your code seems to be failing during the initial request, not during the subsequent actions. I am far from a Javascript expert, but you seem to have some unnecessary complexity in there. Try simplifying your command like this and see if you can at least get a successful request to go through:
Cypress.Commands.add('createCustomer', () => {
cy.request({
method: 'POST',
url: 'api/v1/Customers',
headers: {
'Content-Type': 'application/json'
},
body: {
// sample content
}
})
})
And if that works, keep going:
Cypress.Commands.add('createCustomer', () => {
cy.request({
method: 'POST',
url: 'api/v1/Customers',
headers: {
'Content-Type': 'application/json'
},
body: {
// sample content
}
}).then((response) => {
expect(response).property('status').to.equal(201)
expect(response.body).property('id').to.not.be.oneOf([null, ""])
const jsonData = response.body;
const memberId = jsonData.id
return memberId
})
})
I have some fixtures to stub a server that encode the messages with protobuf (I'm using protobufjs). I'd like to have the fixtures decoded to easily manipulate them and let Cypress encode the stub body before sending the response to the client, how can I do it?
[UPDATE] it's now available as a Cypress plugin
That's my solution:
cypress/plugins/protobufjs/index.js file (where the protobuf definitions are imported)
const path = require("path");
const protobufjs = require("protobufjs");
const definition = path.join(__dirname, "../../../public/escrow/ui.proto");
const proto = protobufjs.loadSync(definition);
module.exports = {
Status: proto.lookupType("escrow.Status"),
};
cypress/plugins/index.js file (where the encoding happens with a custom Cypress task)
const { StringDecoder } = require("string_decoder");
const Messages = require("./protobufjs");
module.exports = on => {
on("task", {
protobufEncode: ({ data, encoderName }) => {
const decoder = new StringDecoder("utf8");
const bufferValue = Messages[encoderName].encode(data).finish();
return decoder.end(Buffer.from(bufferValue));
}
});
};
in your test
cy.fixture("YOUR_FIXTURE.json").then(async json => {
cy.task("protobufEncode", { encoderName: "Status", data: json }).then(result => {
cy.route({
headers: {
"content-type": "application/octet-stream"
},
method: "GET",
response: result,
status: 200,
url: `**/YOUR_URL`
}).as("route_status_one_usb_key");
});
});
I am using 2 seperate libraries to make an http get in my reactjs application as follows
import { ajax } from 'rxjs/observable/dom/ajax';
import { Observable } from 'rxjs/Observable';
import * as actionType from '../types';
import types from '../types';
export default (action$, store) => {
return action$.ofType(types.getIssuers.requested).mergeMap(action => {
return ajax({
url: 'http://127.0.0.1:8181/api/v1/status',
responseType: 'json',
method: 'GET',
timeout: 2000
}).map(xhr => {
console.log("Issuer Epic")
const jsonBody = xhr.response;
return {
type: types.getIssuers.completed,
payload: jsonBody,
};
}).catch(error => {
return Observable.of({ type: actionType.LOAD_CUSTOMER_ERROR });
});
});
};
var request = require('request');
request('http://127.0.0.1:8181/api/v1/status', function (error, response, body) {
console.log('error:', error);
console.log('statusCode:', response && response.statusCode);
console.log('body:', body);
});
I can retrieve data without an issue if um using request library
I need to use rxjs/observable/dom/ajax as per the project requirement but it seems my HTTP GET request turned out to be an HTTP OPTION. Is there a fix for this ?