Cypress request : empty array in body - javascript

I'm finding myself in some troubles while testing my API with Cypress. (I'm using version 2.1.0)
I am sending a request to my endpoint, and want to verify how it is reacting when I am sending an empty array as a parameter. The problem is that somehow, Cypress must be parsing the body I am giving him, and removing the empty array.
My code is the following :
cy.request({
method: 'PUT',
url,
form: true,
body: {
name: 'Name',
subjects: []
}
})
.then((response) => {
expect(response.body).to.have.property('subjects');
const { subjects } = response.body;
expect(subjects.length).to.eq(0);
});
// API receives only the parameter name, and no subjects
When I am sending an empty array of subjects, the endpoint will delete all the associated subjects, and return the object with an empty array of subjects. It is working as it should, and my software in use is working as it should.
When Cypress is sending this request, the endpoint does not receive the parameter subjects. Which is for me a very different thing : I should not touch the subjects in this case.
Is there a way to avoid this "rewriting" by Cypress and send the body as I write it ?

The test works when setting form: false.
it.only('PUTs a request', () => {
const url = 'http://localhost:3000/mythings/2'
cy.request({
method: 'PUT',
url: url,
form: false,
body: {
name: 'Name',
subjects: []
}
})
.then((response) => {
expect(response.body).to.have.property('subjects');
const {
subjects
} = response.body;
expect(subjects.length).to.eq(0);
});
})
I set up a local rest server with json-server to check out the behavior.
If I try to PUT a non-empty array with form: true
cy.request({
method: 'PUT',
url: url,
form: true,
body: {
name: 'Name',
subjects: ['x']
}
})
looking at db.json after the test has run, I see the item index migrating into the key,
"mythings": [
{
"name": "Name",
"subjects[0]": "x",
"id": 2
}
],
so perhaps form means simple properties only.
Changing to form: false gives a proper array
{
"mythings": [
{
"name": "Name",
"subjects": ['x'],
"id": 2
}
],
}
which can then be emptied out by posting an empty array.

Related

Why is my JSON invalid when making post request? (Postgres, Knex)

I've been playing around with this for a while, and I have to say I'm rather stumped.
I have a table called "physical_sites", and created the column "history" as a "json" type in this table.
My API request function is as follows:
const response = await fetch(BASE_URL + "physical_sites", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ data: jobSite }),
});
With my incoming data as:
{
"physical_site_name": "Here",
"physical_site_loc": "test",
"created_by": "ME",
"status": "Active",
"history": [{
"action_date": "2022-07-21T01:22:44.056Z",
"action_taken": "Create Job Site",
"action_by": "me",
"action_by_id": 24,
"action_comment": "Initial Upload",
"action_key": "1jt9JPRLy7RHJUwmz3kqoy98u"
}]
}
I will continually be adding items to the 'array' in history, so there will be multiple objects here. I checked this in an online JSON validator, and it seems correct.
Lastly, my "create" function in the controller is as follows:
async function create(req, res) {
const result = req.body.data;
console.log(result);
const data = await knex("physical_sites")
.insert(result)
.returning("*")
.then((results) => results[0]); //insert body data into assets
res.status(201).json({ data });
}
Fairly simple.
However, I keep getting this error:
message: 'insert into "physical_sites" ("created_by", "history", "physical_site_loc", "physical_site_name", "status") values ($1, $2, $3, $4, $5) returning
* - invalid input syntax for type json'
Not exactly sure what is going on, can someone help me understand what I'm missing?
Thanks.
Most likely one of you column for this table has a JSON type. I believe that it is the history column.
You could parse the history property to String before sending the request.
// ...
body: JSON.stringify({
data: {
...jobSite,
history: JSON.parse(jobSite.history)
}
}),
// ...

How to post the JSON data in a embed in discord.js

I wrote a code and i got the data in a json format. Now i want it to convert that data into a discord embed so that when i enter a command . EX:- .data the json data to be sent from the URL.
Here is the input
request({
url: "https://data.vatsim.net/v3/vatsim-data.json",
json: true
}, (err, response, body) => {
console.log(body)
})
The json data looks like this :
{
cid: 1435807,
name: ' ',
callsign: 'ZAP85LJ',
flight_plan: [Object],
last_updated: '2021-10-24T10:45:52.516736Z'
},
{
cid: 1439854,
name: ' ',
callsign: 'DLH1ML',
flight_plan: [Object],
last_updated: '2021-10-24T10:46:13.4226778Z'
}
You can use EmbedFields, you can use up to 25 fields on an embed. On this example I used .forEach so that for each element on the array I can create a field with its value:
request({
url: "https://data.vatsim.net/v3/vatsim-data.json",
json: true
}, (err, response, body) => {
const embed = new Discord.MessageEmbed()
const pilots = body.pilots.slice(0, 15)
body.pilots.forEach(pilot => {
embed.addField(p.name,
`CID : ${p.cid}
Server : ${p.server}
etc...`)
})
message.channel.send(embed)
}
If you really want to show every single one of your elements on the array you can use discord-buttons to make the embed edit its message and change pages but for now this is the simplest and easiest solution for you.

Send object as get parameter with Axios

The API expects the following GET request:
/resource?labels[team1]=corona&labels[team2]=virus
My issue is to generate this URL using the Axios params option.
I tried the following params structures and they both generate the wrong url:
{
labels: {
team1: 'corona',
team2: 'virus'
}
}
{
labels: [
team1: 'corona',
team2: 'virus'
]
}
I at least thought it would work with the string indexed array but that generates no get params at all.
So, can anyone tell me how to generate the desired URL?
The solution was to use the paramsSerializer with the same setup as in the axios readme. And I used the first params object from my post above..
paramsSerializer: (params) => {
return qs.stringify(params, { arrayFormat: 'brackets' });
}

How to structure a JSON call

I have an endpoint which I call with Axios and the response looks like (for example):
items: [
{
url: "https://api.example1...",
expirationDate: "2019-11-15T00:00:00+01:00"
},
{
url: "https://api.example2...",
expirationDate: "2019-12-20T00:00:00+01:00"
},
{
url: "https://api.example3...",
expirationDate: "2020-01-17T00:00:00+01:00"
},
...and so on.
If I go to one of the url:s in the browser the structure of the JSON is:
fooBar: {
url: "https://api.foo...",
id: "123",
type: "INDEX",
source: "Foobar",
quotes: {
url: "https://api.bar..."
}
},
I need to get the quotes of the two first url:s in items:[] dynamically because they will disappear when the 'expirationDate' is older than today's date.
How can this be achieved? Thanks in advance!
If I understand the requirements correctly you need to:
get the list of items
get item details for first two items (to extract links to quotes)
get quotes for first two items
You can use promise chaining to execute these operations maintaining the order:
const getQuotes = (item) => axios.get(item.url)
.then(resp => axios.get(resp.data.fooBar.quotes.url));
axios.get('/items') // here should be the url that you use to get items array
.then(resp => resp.data.slice(0, 2).map(getQuotes))
.then(quotes => Promise.all(quotes))
.then(quotes => {
console.log(quotes);
});
Please find my proposal below. I gave two examples. You can get the whole quotes object, or just the URL inside the quotes object.
This is just a console log, but you can easily ie. append this data to a div in the html or pass this URL to some other function.
$(function() {
const address = 'https://api.example1...';
function loadQuotes() {
$.ajax({
url: address,
dataType: 'json',
}).done(function(response) {
response.forEach(el => {
console.log(`el.quotes`);
// or if you want to be more specific console.log(`el.quotes.url`);
});
});
}
loadQuotes();
});
If these are nested objects, just append fooBar.
For example change the .done part to:
.done(function(response) {
let qqq = response.quotes
quotes.forEach(el => {
console.log(`el.quotes`);
// or if you want to be more specific console.log(`el.quotes.url`);
});

When using Joi with Hapi, how does one setup a require on one key but allow any and all other keys?

I'm trying to write a Joi validation for a JSON object coming into a Hapi handler. So far the code looks like this:
server.route({
method: 'POST',
path: '/converge',
handler: function (request, reply) {
consociator.consociate(request.payload)
.then (function (result) {
reply (200, result);
});
},
config: {
validate: {
payload: {
value: Joi.object().required().keys({ knownid: Joi.object() })
}
}
}
});
You can see the Joi object validation so far in the config: validate: code section above. The JSON coming in looks like this.
"key": '06e5140d-fa4e-4758-8d9d-e707bd19880d-testA',
"value": {
"ids_lot_args": {
"this_id": "stuff",
"otherThign": "more data"
},
"peripheral_data": 'Sample peripheral data of any sort'
}
In this JSON above the key and value at the root of the object are required, and the section called ids_lot_args is required. The section that starts with peripheral_data could be there or not, or could be any other JSON payload. It doesn't matter, only key and value at the root level and ids_lot_args inside the value are required.
So far, I'm stumbling through trying to get the Joi validation to work.
Any ideas on how this should be setup? The code repo for Joi is located at https://github.com/hapijs/joi if one wants to check it out. I've been trying the allow all functions on objects to no avail so far.
You just need to call the unknown() function on the value object:
var schema = Joi.object({
key: Joi.string().required(),
value: Joi.object({
ids_lot_args: Joi.object().required()
}).unknown().required()
});
You can use the "allowUnknown" parameter:
validate : {
options : {
allowUnknown: true
},
headers : {
...
},
params : {
...
},
payload : {
...
}
}
}
Try using Joi.any()
server.route({
method: 'POST',
path: '/converge',
handler: function (request, reply) {
consociator.consociate(request.payload)
.then (function (result) {
reply (200, result);
});
},
config: {
validate: {
payload: {
key: Joi.string().required(),
value: Joi.object({
ids_lot_args: Joi.object().required(),
peripheral_data: Joi.any()
})
}
}
}});

Categories