Firebase Request simplification and error fixing - json

I have a bunch of forms that input data into my firebase database using a express API and cloud functions.
I have one main issue - I'm getting a error on trying to test my API when inputting the form data.
The secondary issue is more, is there a cleaner way to take the inputted form data to the firebase than how I am currently doing it.
This is the code to create a new workflow (which is the data outputed from the forms)
(this is the required code from the route file)
const {getAllWorkflows,
postOneWorkflow} = require('./handlers/workflow');
// Workflow Routes
app.get('/Workflows', getAllWorkflows);
app.post('/Workflow', postOneWorkflow);
And this is the request code from a handler file
exports.postOneWorkflow = (req, res) => {
const newWorkflow = {
completed: req.body.completed,
currentStep: req.body.currentStep,
createdAt: new Date().toISOString(),
Reason: req.body.Reason,
breach: req.body.breach,
cauInd: req.body.cauInd,
cauOth: req.body.cauOth,
cauWea: req.body.cauWea,
claimEoT: req.body.claimEoT,
dateAware: req.body.dateAware,
dateEoTClaim: req.body.dateEoTClaim,
daysClaimed: req.body.daysClaimed,
dec: req.body.dec,
delayRespon: req.body.delayRespon,
descB: req.body.descB,
descCau: req.body.descCau,
descExt: req.body.descExt,
event: req.body.event,
eviCause: req.body.eviCause,
eviExtent: req.body.eviExtent,
ifGranDay: req.body.ifGranDay,
notice: req.body.notice,
proMitPro: req.body.proMitPro,
proResPro: req.body.proResPro,
recWri: req.body.recWri,
stepsMit: req.body.stepsMit,
stepsPre: req.body.stepsPre
};
db.collection("Workflow")
.add(newWorkflow)
.then(doc => {
const resWorkflow = newWorkflow;
resWorkflow.WorkflowId = doc.id;
res.json(resWorkflow);
})
.catch(err => {
res.status(500).json({ error: "something went wrong" });
console.error(err);
});
};
I'm currently receiving an error of
SyntaxError: Unexpected token c in JSON at position 10
when inputting json using postman to the workflow post route,
{
completed: "False",
currentStep: 1,
claimEoT: "True",
event: "True",
notice: "True",
recWri: "True",
dateEotClaim: "",
dateAware: "",
eviCause: "",
descCau : "",
eviExtent : "True",
descExt : "",
daysClaimed : 5,
delayRespon : "True",
proResPro : 1,
stepsPre : "True",
proPrePro : 1,
stepsMit: "True",
proMitPro : 10 ,
breach : "True",
descB : "describe",
cauInd : "True",
cauWea : "True",
cauOth : "True",
dec : "True",
ifGranDay : 5,
Reason : "I AM THE SENATE"
}
Not 100% sure why as it seems like my formatting is fine?
With creating the query - I wonder if there is a more efficient way of doing this other than writing an ungodly amount of code for the queries.
The point is I need to be able to query the different collections and edit them, but I feel like a query that just took in what it was told, and sent it through to this database, without having to specify the specific "completed", or "Reason",would be ideal.

Your postman JSON is invalid. The keys are also supposed to be enclosed in quotes.
{
"completed": "False",
"currentStep": 1,
...
}
You can just create the newWorkflow object from req.body!
const newWorkflow = req.body;
newWorkflow.createdAt = new Date().toISOString();

Related

422 error trying to save json data to the database

I'm trying to save data to my MySql db from a Node method. This includes a field called attachments.
console.log(JSON.stringify(post.acf.attachments[0])); returns:
{
"ID": 4776,
"id": 4776,
"title": "bla",
"filename": "bla.pdf",
"filesize": 1242207,
"url": "https://example.com/wp-content/uploads/bla.pdf",
"link": "https://example.com/bla/",
"alt": "",
"author": "1",
"description": "",
"caption": "",
"name": "bla",
"status": "inherit",
"uploaded_to": 0,
"date": "2020-10-23 18:05:13",
"modified": "2020-10-23 18:05:13",
"menu_order": 0,
"mime_type": "application/pdf",
"type": "application",
"subtype": "pdf",
"icon": "https://example.com/wp-includes/images/media/document.png"
}
This is indeed the data I want to save to the db:
await existing_post.save({
...
attachments: post.acf.attachments[0],
)};
However, the attachments field produces a 422 server error (if I comment out this field, the other fields save without a problem to the db). I'm not getting what is causing this error. Any ideas?
I've also tried
await existing_post.save({
...
attachments: post.acf.attachments,
)};
but then it seems to just save "[object Object]" to the database.
The field in the database is defined as text. I've also tried it by defining the field as json, but that made no difference.
exports.up = function (knex, Promise) {
return knex.schema.table("posts", function (table) {
table.longtext("attachments");
});
};
The 422 error code is about the server unable to process the data you are sending to it. In your case, your table field is longtext when post.acf.attachments seems like an object. That's why it saves [object Object] to your db (It is the return value of the toString() method).
Try using
await existing_post.save({
...
attachments: JSON.stringify(post.acf.attachments),
)};
MySQL and knex both support the JSON format, I'd suggest you change the field to json. (See knex docs and mysql 8 docs). You'll stiil need to stringify your objects tho.
EDIT: I just saw that Knex supports jsonInsert (and plenty other neat stuff) as a query builder that should be useful for you.
Mysql also support a large range of cool stuffs for handling jsons
In addition, when you fetch the results in the database, you'll need to parse the JSON result to get an actual JSON object:
const acf = await knex('posts').select('acf').first();
const attachment = JSON.parse(acf.attachment;
Knex also provide jsonExtract that should fill your needs (See also the mysql json_extract

Cypress intercept API JSON response and extract URL

My web app sends an API POST request to create an application and returns JSON response. I want to access one particular JSON object from that response.
My JSON starts like this
[
{
"status_code": 201,
"body": {
"created": "2021-01-28T00:00:00Z",
"modified": "2021-01-28T00:00:00Z",
"id": "a2d86d17-9b3c-4c4d-ac49-5b9d8f6d6f8f",
"applicant": {
"id": "07f1e1d3-0521-401b-813e-3f777f2673c6",
"status": "Pending",
"first_name": "",
"last_name": "",
"URL": "some onboarding url"
And I wanna take that URL in the JSON response and visit it later in my cypress automation script.
Notice that the JSON repsonse starts with a square bracket not a curly bracket, which means, the whole response is an object, I assume?
My cypress script looks like this
cy.contains('button', 'CONTINUE').click()
cy.EmailGen('candidate').then(email => {
cy.get('#emails\\[0\\]').type(`${email}`)
cy.wrap(email).as('candidateEmail')
})
//writing intercept here, before the Send application button, which triggers the POST req.
cy.intercept('/hr/v1/applications/invite').as('getURL')
cy.get('button').contains('SEND APPLICATION').click({ force: true })
//waiting on the alias of intercept and using interception to print objects from response
cy.wait('#getURL').then((interception)=> {
cy.log(interception.response.body.applicant.URL)
})
cy.Logout()
The script executes with no errors. Just that nothing is logged in the cy.log statement. Below is the screen.
I also tried using another method as given below.
cy.intercept('/hr/v1/applications/invite',(req) => {
req.reply((res=> {
expect(res.status_code).to.equal('201')
expect(res.body.applicant.status).to.equal('Pending')
}))
})
In this case, I get a assert error embedded with the request and response along with some other stuff which I am unable to understand.
The complete error goes something like this...
"expected The following error originated from your test code, not from Cypress.\n\n > A response callback passed to req.reply() threw an error while intercepting a response:\n\nexpected undefined to equal '201'\n\nRoute: {\n "matchUrlAgainstPath": true,\n "url": "/hr/v1/applications/invite"\n}\n\nIntercepted request:{} Intercepted response: {} When Cypress detects uncaught errors originating from your test code it will automatically fail the current test. to include window.zE is not a function"
Its a bit weird to read this..
My application sometimes throws this exception, which I have handled using following code.
cy.on('uncaught:exception', (err, runnable) => {
expect(err.message).to.include('window.zE is not a function')
done()
return false
})
I really hope I have explained everything here. Please, help a noob.
Regards
As Richard Matsen suggested in the comments,
I used console.log(interception.response) and checked the console output in the browser controlled by Cypress.
I Noticed that the response json structure was something different than what I got in the network tab of developers tools, while using the web app.
The response was something like below...
{headers: {…}, url: "https://example.com/hr/v1/applications/invite/batch/", method: null, httpVersion: "1.1", statusCode: 200, …}
body: Array(1)
0:
body:
applicant: {id: "c6b2d686-d4f3-483e-abc8-e4641c365845", status: "Pending", first_name: "", last_name: "", email: "qa2+candidate879#example.com", …}
applicant_status: "NONE"
applicant_status_label: "None"
created: "2021-01-29T00:00:00Z"
get_applicant_status_display: "None"
id: "ad2939f5-c8ab-490a-a9e1-b0474de69e2c"
URL: "some url"
This made me modify the json traverse to
interception.response.body[0].body.applicant.URL
If others have a neat way to handle this, please let me know!

Zapier Catch (Raw) Hook JSON parsing issue

I would like to configure sync between two different CRMs (Clevertap and Intercom) using Zapier and Webhooks. In general Clevertap sends the following JSON to webhook:
{
"targetId": 1548328164,
"profiles": [
{
"event_properties": {
"MSG-sms": true,
"MSG-push": true,
"businessRole": "EMPLOYEE",
"Mobile Number": "123123123123",
"Name": "Artem Hovtvianisa",
"Title": "Mr",
"Last Name": "Hovtvianisa",
"Gender": "M",
"Customer type": "Business Account Holder",
"MSG-email": true,
"First Name": "Artem",
"Last seen IP": "111.177.74.50",
"tz": "GMT+0200",
"International customer": "yes",
"isBusiness": true,
"Email": "xxxyyy#gmail.com",
"Identity": 15675
},
"objectId": "e32e4de3c1e84b2d9bab3707c92cd092",
"all_identities": [
"15675",
"xxxyyy#gmail.com"
],
"email": "xxxyyy#gmail.com",
"identity": "15675"
}
]
}
Zapier provides two types of catch webhook: regular and Raw.
Catch Raw Hook
When I use this type, JSON raw data will be handled OK and on the next step (Zapier JS code app) I am able to pass proper JSON data like in example above.
However when I use simple JS code to parse JSON object and get profiles[0] array value I get the following error "TypeError: Cannot read property '0' of undefined"
JS Code from Code step:
var result = JSON.parse(JSON.stringify(inputData));
console.log(result.profiles[0]);
return result;
Catch Hook
In case I use regular Catch Hook, hook parse data in some odd way, like this:
JSON.parse cannot recognize this structure.
Please advise how can I handle Webhook Zapier step in a proper way in order to get profiles[0] array item values?
Thanks in advance!
David here, from the Zapier Platform team. You're on the right track!
Catch Raw Hook is the way to go here. Your issue is that the data is coming in as a string and you're re-stringifying it before parsing it, which gets you back to where you came from. A simpler version:
JSON.stringify("asdf") // => "\"asdf\"", quotes in the string
JSON.parse("\"asdf\"") // => "asdf", the original string
"asdf".profiles // => undefined
undefined[0] // => error, cannot read property "0" of undefined
Instead, just parse it and you're good to go!
// all your variables are already in "inputData", so yours,
// also named inputData, must be referenced explicitly.
const result = JSON.parse(inputData.inputData);
return {result: result, firstProfile: result.profiles[0]};

How can I use AJAX with web methods to send JSON objects to a jQuery DataTable using asp.net?

So I have the jQuery datatable using AJAX to call for the JSON in this format.
$(document).ready(function () {
$('#test').DataTable({
ajax:{
url:"players.json",
dataSrc:""
},
columns: [
{data: "id"},
{ data: "player" },
{ data: "points" },
{ data: "steals" },
{ data: "blocks" },
{ data: "assists" },
{ data: "MPG" },
{ data: "shot %" },
{ data: "3 %" }
]
});
});
My aspx.cs file has a method to create the JSON file which works.
[System.Web.Services.WebMethod]
public static void loadTable()
{
NBAPlayerRepository players = new NBAPlayerRepository();
DataTable dt = players.GetAll();
var json = dt.ToJson();
System.IO.File.WriteAllText(#"C:\Users\wheres\Downloads\nbaStats\nbaStats\nbaStats\players.json", json);
}
And the JSON looks like this:
[{"id" : "67926aa7-46b7-4418-96db-fc7e5216aac4","playername" : "Wilson Heres","points" : "34534","steals" : "34","blocks" : "34","assists" : "343","mpg" : "343","shootingpercentage" : "33.3429985046387","threepointpercentage" : "33.3429985046387"}
,{"id" : "6dc42e0b-8750-463d-a9ef-5a025a27154b","playername" : "Wilson Heres","points" : "34534","steals" : "34","blocks" : "34","assists" : "343","mpg" : "343","shootingpercentage" : "33.3429985046387","threepointpercentage" : "343.334014892578"}
,{"id" : "f727130c-5b94-4730-a653-cfb603c73b8a","playername" : "Wilson Heres","points" : "34534","steals" : "34","blocks" : "34","assists" : "343","mpg" : "343","shootingpercentage" : "33.3429985046387","threepointpercentage" : "343.334014892578"}
]
But now I am getting this error "jquery.dataTables.min.js:48 Uncaught TypeError: Cannot read property 'length' of undefined"
Edit: This all works now. Just had to add dataSrc:""
Cleaned-up version of your DataTables initialization
$(document).ready(function () {
$('#test').DataTable({
ajax: {
url: "players.aspx/loadTable"
},
columns: [
{ data: "id" },
{ data: "player" },
{ data: "points" },
{ data: "steals" },
{ data: "blocks" },
{ data: "assists" },
{ data: "MPG" },
{ data: "Shot %" },
{ data: "3 %" },
]
});
});
This may seem like a lot of stuff was removed from your code, so let me make some explanations/assumptions about what was changed.
Assumptions
First, an assumption: DataTables will always try to use a GET request, not a POST when first getting the data from the table, so make sure that your data processing code expects that.
I also am assuming that you have no strong desire to have your Ajax separate from your initialization and that was just how you decided to do it as a first attempt. If that is the case, let me know and I'll update the code to match that.
Explanation
Your formatting is incorrect in some areas and against DataTables standard in others, so this version should do most of what you were trying to do in a much simpler form. A lot of your Ajax options are unnecessary because they are already the default (JSON for the data type, for example), which is why they have been removed.
One nice thing about DataTables is that you can have the Ajax options in the initialization, which is what I have done here. You do lose the success and failure callbacks but I think that for debugging purposes they aren't really necessary and having any extra code increases the amount of stuff to debug (I don't even use those callbacks in most of my final code).
Most of the other changes were mainly incorrect nomenclature (e.g. data instead of title in the column definitions.
Disclaimer
While I would recommend these changes in general just to improve your code, I would make sure to take a look at the format of the JSON that is being sent to and from the server. If you don't know how to do that I'd recommend downloading Fiddler to 'listen in' on the JSON data being sent.
If your JSON is wrong, no amount of changes to the page are going to make the table appear.
Finally, make sure you have no JS errors on the page. Use your browser's developer console (F12) to check that.
If you do find any JS errors, post them in your question. I'd also recommend posting the JSON data being sent to the question as well so that we can ensure the format is correct.

Google Apps Script and Big Query - tabledate.insertAll

Have been struggling with this..... Google Apps Script and the Big Query API are working well however when I try to use BigQuery.Tabledata.insertAll I keep getting an error saying 'no such field'.
When I try to run the same thing through the Google API explorer it works fine. The documentation says the command is :
BigQuery.TableData.insertAll(TableDataInsertAllRequest resource, String projectId, String datasetId, String tableId)
I have constructed the TableDataInsertAllRequest resource as per the documentation https://developers.google.com/bigquery/docs/reference/v2/tabledata/insertAll and it looks like this :
{
"kind": "bigquery#tableDataInsertAllRequest",
"rows":
[
{
"json":
{
"domain": "test",
"kind": "another test"
}
}
]
}
This matches my table schema.
When I run the command the error returned is :
{
"insertErrors": [
{
"index": 0,
"errors": [
{
"message": "no such field",
"reason": "invalid"
}
]
}
],
"kind": "bigquery#tableDataInsertAllResponse"
}
As I say the same TableDataInsertAllRequest resource works fine in the API explorer (clicking Try It on the documentation page above) it just does not work through Apps Script.
Any help gratefully received.
I've run into this too, and had somewhat better luck with this variation.
var rowObjects = [];
// Generally you'd do this next bit in a loop
var rowData = {};
rowData.domain = 'test';
rowData.kind = 'another test';
rowObjects.push(rowData);
// And at this point you'd have an array rowObjects with a bunch of objects
var response = BigQuery.Tabledata.insertAll({'rows': rowObjects}, projectId, datasetId, tableId);
Some things to note:
I don't indicate a kind -- it is implied by the call to insertAll()
I use dot notation (is that the right term?) rather than strings to stuff attributes into my "row objects"
I'm not sure which of these is the Secret Sauce. Anyways, in the end, the structure of the call looks about like this:
BigQuery.Tabledata.insertAll({'rows' : [
{
'domain' : 'test',
'kind' : 'another test'
}
]
},
projectId,
datasetId,
tableId);