I am using nock to mock my asynchronous thunk action creators. Everything works as expected for GET requests, but I haven't been able to make a POST request work. I have read everything I can find online but nothing fixed my problem. I can see the response body in the failed test run. The issue is that there is no nock match for the url. Can anyone spot the problem?
Test file:
describe('#saveReminder', () => {
it(`creates ${constants.actions.REQUEST_SAVE_REMINDER}
and ${constants.actions.RECEIVE_SAVE_REMINDER}`, () => {
data = { payload: 'payload' };
nock(constants.paths.API_AUTHORITY)
.post('api/prospect/add-reminder', {
prospect: 1,
reminder_datetime: '2017-12-22T18:42:00.000Z',
description: 'description',
})
.reply(200, { data } )
const expectedActions = [
{ type: constants.actions.REQUEST_SAVE_REMINDER },
{ type: constants.actions.RECEIVE_SAVE_REMINDER, data }
]
return store.dispatch(actions.saveReminder({
id: 1,
description: 'description',
date: moment(),
time: moment(),
})).then(() => {
expect(store.getActions()).toEqual(expectedActions)
})
})
})
Async action:
export function saveReminder({ id, description, date, time }) {
return (dispatch) => {
requestSaveReminder();
return fetch(`${constants.paths.API_AUTHORITY}api/prospect/add-reminder`, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'X-Csrf-Token': Cookie.get('X-Csrf-Token'),
},
credentials: 'same-origin',
method: 'POST',
body: JSON.stringify(
{
prospect: id,
reminder_datetime: moment(`${date.format('MM/DD/YYYY')} ${time.format('HH:mm')}`, 'MM/DD/YYYY HH:mm'),
description,
}
),
}).then(response => {
response.json();
})
.then(json => dispatch(receiveSaveReminder(json.data)))
.catch(ex => dispatch(requestSaveReminderFailure(ex)));
};
}
Test Failure:
Object {
- "type": "REQUEST_SAVE_REMINDER",
+ "data": [FetchError: request to http://localhost:8080/api/prospect/add-reminder failed, reason: Nock: No match for request {
+ "method": "POST",
+ "url": "http://localhost:8080/api/prospect/add-reminder",
+ "headers": {
+ "accept": [
+ "application/json"
+ ],
+ "content-type": [
+ "application/json"
+ ],
+ "accept-encoding": [
+ "gzip,deflate"
+ ],
+ "user-agent": [
+ "node-fetch/1.0 (+https://github.com/bitinn/node-fetch)"
+ ],
+ "connection": [
+ "close"
+ ],
+ "content-length": [
+ 89
+ ]
+ },
+ "body": "{\"prospect\":1,\"reminder_datetime\":\"2017-12-22T18:56:00.000Z\",\"description\":\"description\"}"
+ }],
+ "type": "REQUEST_SAVE_REMINDER_FAILURE",
},
- Object {
- "data": Object {
- "payload": "payload",
- },
- "type": "RECEIVE_SAVE_REMINDER",
- },
The urls appear to match. Why does it say Nock: No match for request? Thanks!
Because you are not only matching URLs, you are also validating expected payload with Nock. If you replace your nock post() call with .post('api/prospect/add-reminder', () => true) I would think the timestamp difference wont affect you.
Related
I'm trying to integrate algolia search with sanity CMS using the sanity-algolia library (ref https://www.sanity.io/plugins/sanity-algolia)
But when i try to get the plain text from Portable Text rich text content using the pt::text function.
i get expected '}' following object body , and i dont really know where im missing a bracket.
(another note: since im hosting sanity by using sanity start, I am using nextjs (my frontend) to run the function instead using the /api routes in nextJS) So sanity has a webhook to this route.
details about the error:
details: {
description: "expected '}' following object body",
end: 174,
query: '* [(_id in $created || _id in $updated) && _type in $types] {\n' +
' _id,\n' +
' _type,\n' +
' _rev,\n' +
' _type == "post" => {\n' +
' title,\n' +
' "path": slug.current,\n' +
' "body": pt::text(body)\n' +
' }\n' +
'}',
start: 107,
type: 'queryParseError'
}
this is the serverless function im running:
export default async function handler(req, res) {
if (req.headers["content-type"] !== "application/json") {
res.status(400);
res.json({ message: "Bad request" });
return;
}
const algoliaIndex = algolia.initIndex("dev_kim_miles");
const sanityAlgolia = indexer(
{
post: {
index: algoliaIndex,
projection: `{
title,
"path": slug.current,
"body": pt::text(body)
}`,
},
},
(document) => {
console.log(document);
return document;
},
(document) => {
if (document.hasOwnProperty("isHidden")) {
return !document.isHidden;
}
return true;
}
);
return sanityAlgolia
.webhookSync(sanityClient, req.body)
.then(() => res.status(200).send("ok"));
}
and my post schema from sanity:
export default {
name: 'post',
title: 'Post',
type: 'document',
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
},
{
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'title',
maxLength: 96,
},
},
{
name: 'author',
title: 'Author',
type: 'reference',
to: {type: 'author'},
},
{
name: 'mainImage',
title: 'Main image',
type: 'image',
options: {
hotspot: true,
},
},
{
name: 'categories',
title: 'Categories',
type: 'array',
of: [{type: 'reference', to: {type: 'category'}}],
},
{
name: 'publishedAt',
title: 'Published at',
type: 'datetime',
},
{
name: 'body',
title: 'Body',
type: 'blockContent',
},
{
name: 'extra',
title: 'extra',
type: 'blockContent',
},
],
preview: {
select: {
title: 'title',
author: 'author.name',
media: 'mainImage',
},
prepare(selection) {
const {author} = selection
return Object.assign({}, selection, {
subtitle: author && `by ${author}`,
})
},
},
}
sanity api v1 doesnt work with functions, I was using
const sanityClient = client({
dataset: "production",
useCdn: true,
projectId: "project_id",
});
which defaults to v1, but in order to use function i added a apiVersion parameter, which made it use later api version:
const sanityClient = client({
dataset: "production",
useCdn: true,
projectId: "9dz8b3g1",
apiVersion: "2021-03-25",
});
As explained in the NextJs documentation: https://nextjs.org/docs/api-reference/next.config.js/headers , it is possible to configure the HTTP headers of a page using the code below, however my code is not working.
Next Example:
module.exports = {
async headers() {
return [
{
source: '/about',
headers: [
{
key: 'x-custom-header',
value: 'my custom header value',
},
{
key: 'x-another-custom-header',
value: 'my other custom header value',
},
],
},
]
},
}
My Code:
module.exports = {
async headers() {
return [
{
source: '/about',
headers: [
{
key: 'cache-control',
value: 'max-age=31536000',
},
],
},
]
},
}
describe('Getting asset for player', () => {
before(() => {
return provider.addInteraction({
given: 'GET call',
uponReceiving: 'Get asset for player',
withRequest: {
method: 'GET',
path: term({
matcher: '/api/assets/[0-9]+',
generate: '/api/assets/10006'
}),
},
willRespondWith: {
status: 200,
headers: { 'Content-Type': 'application/json' },
body: assetByPlayer
}
});
});
it('Get the asset by player', () => {
return request.get(`http://localhost:${PORT}/api/assets/10006`)
.set({ 'Accept': 'application/json' }).then((response) => {
return expect(Promise.resolve(response.statusCode)).to.eventually.equals(200);
}).catch(err => {
console.log("Error in asset with player listing", err);
});
});
});
I get the json file as : https://pastebin.com/TqRbTmNS
When i use the json file in other code base by pact stub server , it
gets the request from UI as
===> Received Request ( method: GET, path: /api/assets/10006, query:
None, headers: Some({"actasuserid": "5", "content-type": "application/vnd.nativ.mio.v1+json", "host": "masteraccount.local.nativ.tv:30044", "accept": "application/json", "authorization": "Basic bWFzdGVydXNlcjptYXN0ZXJ1c2Vy", "connection": "close", "content-length": "2"}), body: Present(2 bytes) )
but does not sends any response
But if i just remove the matching rules part
"matchingRules": {
"$.path": {
"match": "regex",
"regex": "\/api\/assets\/[0-9]+"
}
}
it starts to work again
===> Received Request ( method: GET, path: /api/assets/10006, query: None, headers: Some({"authorization": "Basic bWFzdGVydXNlcjptYXN0ZXJ1c2Vy", "accept": "application/json", "content-length": "2", "connection": "close", "host": "masteraccount.local.nativ.tv:30044", "content-type": "application/vnd.nativ.mio.v1+json", "actasuserid": "5"}), body: Present(2 bytes) )
<=== Sending Response ( status: 200, headers: Some({"Content-Type": "application/json"}), body: Present(4500 bytes) )
and I can see the data to be present
Could you let me what is wrong here ?
I am attempting to use the nativescript HTTP.request to send a curl for firebase push notifications. I have tested the curl and it works however I am getting a bad request error when i try to send it via http.request.
Here is the curl code (my key has been substituted for a variable for privacy reasons)
curl -X POST --header "Authorization: key=MyKey" --Header "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d "{\"notification\":{\"title\": \"My title\", \"text\": \"My text\", \"sound\": \"default\"}, \"data\":{\"foo\":\"bar\"}, \"priority\": \"High\", \"to\":\"d1LHpypPxA0:APA91bHG4HlZQnb7F_BkZAZYHv1MM00FhNbsONMhsLRB-U4p3As3C0Pp_8ALqQFusOOkgdSHZUlOfHbtt6qXU8pzCnjC-ozfMU3vTqjY0iy90XDvGHkDt0qw1w2wnr73PjFqViHEGONH\"}"
here is my http.request
http.request({
url: 'https://fcm.googleapis.com/fcm/send',
method: "POST",
headers: { 'Authorization': 'key=MyKey','Content-Type': 'application/json'} ,
content: {
"notification": {
"title": "testingtesting",
"text": "some text",
"sound": "default",
"priority": "High"
}
},
data: { "foo": "bar" },
to: "d1LHpypPxA0:APA91bHG4HlZQnb7F_BkZAZYHv1MM00FhNbsONMhsLRB-U4p3As3C0Pp_8ALqQFusOOkgdSHZUlOfHbtt6qXU8pzCnjC-ozfMU3vTqjY0iy90XDvGHkDt0qw1w2wnr73PjFqViHEGONH"
}).then((response) => {
//HttpResult = response.content.toJSON();
console.log('----------------------------------------------------');
console.log(response.content);
}, (e) => {
console.log("Error occurred " + e);
});
any help would be greatly appreciated!
I figured it out, this is the code that worked. I had some issues with formatting, I hope this helps someone in the future!
var HttpResult;
http.request({
url: 'https://fcm.googleapis.com/fcm/send',
method: "POST",
headers: { 'Authorization': 'key=MyKey', 'Content-Type': 'application/json' },
content: JSON.stringify({
"notification": {
"title": "testingtesting",
"text": "some text",
"sound": "default",
"priority": "High"
},
'data': { "foo": "bar" },
'to': "d1LHpypPxA0:APA91bHG4HlZQnb7F_BkZAZYHv1MM00FhNbsONMhsLRB-U4p3As3C0Pp_8ALqQFusOOkgdSHZUlOfHbtt6qXU8pzCnjC-ozfMU3vTqjY0iy90XDvGHkDt0qw1w2wnr73PjFqViHEGONH"
})
}).then((response) => {
//HttpResult = response.content.toJSON();
console.log('----------------------------------------------------');
console.log(JSON.stringify(response));
}, (e) => {
console.log("Error occurred " + JSON.stringify(e));
});
I have a JSON store which read data from webservice.
The JSON from the webservice is valid (I've tried reading the data directly from file and it was working).
Here is the JSON Data:
{
"type": "FeatureCollection",
"name": "Points",
"keyField": "GPSUserName",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
35.19999,
31.780965
]
},
"properties": {
"GPSId": "<img src=images/battery3.png />",
"DateTime": "12/07/2013 09:05:00",
"GPSUserName": "13",
"GPSUserColor": "#00FF57",
"GPSUserIcon": "marker_red2.png",
"GPSLabelPosX": "6",
"GPSLabelPosY": "7"
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
35.201142,
31.780699
]
},
"properties": {
"GPSId": "<img src=images/battery4.png />",
"DateTime": "12/07/2013 09:05:00",
"GPSUserName": "14",
"GPSUserColor": "#00FF57",
"GPSUserIcon": "marker_red2.png",
"GPSLabelPosX": "6",
"GPSLabelPosY": "7"
}
}
]
}
When using the following store , everything is working fine :
initComponent: function () {
this.store = new Ext.data.JsonStore({
storeId: 'usersStore',
autoLoad: true,
autoSync: false,
proxy: {
type: 'ajax',
url: 'data/users.json',
reader: {
type: 'json',
root: 'features'
}
},
fields: [
{ name: 'name', mapping: 'properties.GPSUserName'},
{ name: 'date', mapping: 'properties.DateTime' },
{ name: 'battery', mapping: 'properties.GPSId' }
]
});
this.columns = [
{ header: 'name', dataIndex: 'name', flex: 1 },
{ header: 'date', dataIndex: 'date', flex: 3 },
{ header: 'battery', dataIndex: 'battery', flex: 1 }
];
this.callParent(arguments);
}
but when I change to use a webservice (which returns the file content) nothing works:
initComponent: function () {
this.store = new Ext.data.JsonStore({
storeId: 'usersStore',
autoLoad: true,
autoSync: false,
proxy: new Ext.data.HttpProxy({
url: 'service.asmx/GetJson',
headers: { 'Content-Type': 'application/json; charset=utf-8;' },
reader: { root: 'd', record: 'features' }
}),
fields: [
{ name: 'name', mapping: 'properties.GPSUserName'},
{ name: 'date', mapping: 'properties.DateTime' },
{ name: 'battery', mapping: 'properties.GPSId' }
]
});
this.callParent(arguments);
}
and this is the webservice :
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true, XmlSerializeString = false)]
public string GetJson()
{
string res = File.ReadAllText("data\users.json");
return res;
/*HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/json";
HttpContext.Current.Response.Charset = "utf-8";
HttpContext.Current.Response.Write(res);*/
}
In firebug I see the following returns from the call :
So ... what am I missing here ?
What you are missing is the buggy implementation of ExtJS JsonStore in ExtJS 4.2. If you look at the source code of this class, you will see that it is ignoring your proxy configuration:
Ext.define('Ext.data.JsonStore', {
extend: 'Ext.data.Store',
alias: 'store.json',
requires: [
'Ext.data.proxy.Ajax',
'Ext.data.reader.Json',
'Ext.data.writer.Json'
],
constructor: function(config) {
config = Ext.apply({
proxy: {
type : 'ajax',
reader: 'json',
writer: 'json'
}
}, config);
this.callParent([config]);
}
});
Just use the Ext.data.Store class and everything should be find. Lost a lot of time on this before figuring this out.