I have problem relating to assertion during practicing.
I have response body like:
[
{
"id": 1,
"manufacturer": "Ford",
"model": "Model T",
"build": 1927
},
{
"id": 2,
"manufacturer": "Tesla",
"model": "Model 3",
"build": 2017
},
{
"id": 3,
"manufacturer": "Tesla",
"model": "Cybertruck",
"build": 2019
}
]
I wrote test
const response = pm.response.json()
let model;
for (let filter of response) {
if (filter.model === "Model 3") {
//console.log(filter)
model = filter;
}
}
console.log(model)
pm.test("car model is Model 3", function () {
pm.expect(response.model).to.eql("Model 3");
});
Unfortunately, my test fail AssertionError: expected undefined to deeply equal 'Model 3' I was trying to figure out but dunno why this is not passing because my navigation to that model is correct. Can you guide me what is wrong with my code please.
response.model is undefined since response is an array.
You probably forgot to use model.model instead of response.model
pm.test("car model is Model 3", function () {
pm.expect(model.model).to.eql("Model 3");
});
Related
I just started testing the api using the postman. I have come across one problem with the json path..
in json file I have code which looks like this
{
"users": [
{
"firstName": "UserOne",
"lastName": "One",
"subjectId": 1,
"id": 1
},
{
"firstName": "UserTwo",
"lastName": "Two",
"subjectId": 2,
"id": 2
},
{
"firstName": "UserThree",
"lastName": "Three",
"subjectId": 3,
"id": 3
}
],
"subjects": [
{
"id": 1,
"name": "SubOne"
},
{
"id": 2,
"name": "SubTwo"
},
{
"id": 3,
"name": "SubThree"
}
]
}
I start the json server with json-server --watch db.json
After that I send GET request using postman
Request URL http://localhost:3000/users
this is the body I get
[
{
"firstName": "UserOne",
"lastName": "One",
"subjectId": 1,
"id": 1
},
{
"firstName": "UserTwo",
"lastName": "Two",
"subjectId": 2,
"id": 2
},
{
"firstName": "UserThree",
"lastName": "Three",
"subjectId": 3,
"id": 3
}
]
I was trying to verify the firstName from the id 1 using the snippet code below
pm.test("Your test name", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.users[0].firstName).to.eql('UserOne');
});
But the output was
FAIL Your test name | TypeError: Cannot read property '0' of undefined
I need help here because the json path users[0].firstName should give me the first index..
There is no key users in your response, so when you try to access the non-existed key, you will get error Cannot read property 'xxx' of undefined. To fix that, you just need:
pm.test("Your test name", function () {
var jsonData = pm.response.json();
pm.expect(jsonData[0].firstName).to.eql('UserOne');
});
Expected Test Scenario: Need to validate the array response "Values" for the "Key: id".
I am using the test code:
pm.test("Your test name", function () {
var jsonData = pm.response.json();
pm.expect(jsonData.id).to.contains(16);
});
Getting the error:
AssertionError: object tested must be an array, a map, an object, a set, a string, or a weakset, but undefined given.
Response Body:
[
{
"id": 2,
"Name": "Hello",
"Country": "India"
},
{
"id": 4,
"Name": "thankyou",
"Country": "UK"
},
{
"id": 16,
"Name": "how are you",
"Country": "USA"
},
{
"id": 18,
"Name": "Good morning",
"Country": "Italy"
},
{
"id": 25510,
"Name": "Bonjour",
"Country": "France"
}
]
Anyone could help me in sorting out this please.
The response is not a JSON object but JSON array.
pm.response.json() will have you full json which is in the form :
[ {}, {} ]
so the JSON object with id 16 is the 3rd element in the array so first call jsonData[3] and then get id in it.
But still you will get error because what you are getting is a "integer" so cannot use contains with it . Use equal instead
pm.test("Your test name", function () {
var jsonData = pm.response.json();
pm.expect(jsonData[2].id).to.equal(16);
});
or if you want to use contains instead , then get response as text using pm.response.text():
pm.test("Your test name", function () {
var jsonData = pm.response.text();
pm.expect(jsonData).to.contains(16);
});
I am trying to send horizontally scrollable carousel message on Facebook workplace platform using the generic template as described in the messenger platform documentation(Ref: https://developers.facebook.com/docs/messenger-platform/reference/template/generic)
The template that I am using looking something like this:
[
{
"text": "Hi!!!!"
},
{
"attachment": {
"type": "template",
"payload": {
"template_type": "generic",
"elements": [
{
"title": "Some Title 1",
"image_url": "some image url",
"buttons": [
{
"title": "button_title1",
"type": "postback",
"payload": "Title 1"
}
]
},
{
"title": "Some Title 2",
"image_url": "some image url",
"buttons": [
{
"title": "button_title2",
"type": "postback",
"payload": "Title 2"
}
]
},{
"title": "Some Title 3",
"image_url": "some image url",
"buttons": [
{
"title": "button_title3",
"type": "postback",
"payload": "Title 3"
}
]
},
]
}
}
}
]
Everything worked as I expected but, from the past 2 weeks or so, the order of carousel elements(cards in my case) isn't what I am expecting(i.e., Title1, Title2, Title3). The elements in the carousel are shown in a different order every time I use it. I just want to know if anyone else has the same issue or it has something to do with my code?
The code that I have used to send the message in the end is:
return new Promise((resolve, reject) => {
//(async ref:https://www.npmjs.com/package/async)
async.eachSeries(
//facebookMessages is the message template that I am using(posted above)
facebookMessages,
(msg, callback) => {
//sendFBSenderAction sends the message to FB using api(https://graph.facebook.com/v2.6/me/messages?access_token=<PAGE_ACCESS_TOKEN>)
this.sendFBSenderAction(sender, 'typing_on')
.then(() => this.sleep(this.messagesDelay))
.then(() => {
facebookMessages.attachment ? this.sendFbAttachment(msg) : this.sendFBMessage(sender, msg);
facebookMessages.attachment = false;
})
.then(() => callback())
.catch(callback);
},
err => {
if (err) {
console.error(err);
reject(err);
} else {
console.log('Messages sent');
resolve();
}
}
);
});
Looks like there’s already a current bug report for this - https://developers.facebook.com/support/bugs/260229951577494/
Subscribe to that, to be updated when the status of that bug report changes.
When I query to include a nested model – e.g. GET /api/Widgets/1?filter={include: {"foos": "bars"}} – I get duplicate foos in my results. I thought this was due to a LEFT JOIN or something like that, as I'm using MySQL, but when I run LoopBack in the loopback:connector:mysql debug mode, I can see that the query for the initial widget runs once, but that the query for foo runs twice, and the query for bar runs twice. Why is this behavior occurring, and what can I alter (my models, my code or my expectations)?
Models:
{
"name": "Widget",
...
"relations": {
"foos": {
"type": "hasMany",
"model": "Foo",
"foreignKey": "widgetId"
}
}
}
{
"name": "Foo",
...
"relations": {
"bars": {
"type": "hasMany",
"model": "Bar",
"foreignKey": "fooId"
},
"widget": {
"type": "belongsTo",
"model": "Widget",
"foreignKey": ""
}
}
}
{
"name": "Bar"
...
"relations": {
"foo": {
"type": "belongsTo",
"model": "Foo",
"foreignKey": ""
}
}
}
Results:
{
id: 1
foos: [
{
id: 2,
bars: [
{
id: 3
}
]
},
{
id: 2,
bars: [
{
id: 3
}
]
}
]
}
Expecting:
{
id: 1
foos: [
{
id: 2,
bars: [
{
id: 3
}
]
}
]
}
This is paraphrased SQL that I see being run for this request:
SELECT `...` FROM `Widget` WHERE `id`=1 ORDER BY `id` LIMIT 1
SELECT `...` FROM `Foo` WHERE `widget_id` IN (1) ORDER BY `id`
SELECT `...` FROM `Foo` WHERE `widget_id` IN (1) ORDER BY `id`
SELECT `...` FROM `Bar` WHERE `foo_id` IN (2) ORDER BY `id`
SELECT `...` FROM `Bar` WHERE `foo_id` IN (2) ORDER BY `id`
I'm using Loopback 3.x.
Update: While a request of GET /api/Widgets/1?filter={include: {"foos": "bars"}} exhibits this behavior, a server-side execution of Widgets.findById(id, {include: {"foos": "bars"}}) works perfectly. So, at the moment I'll create a remote method that does this and perhaps file a bug report with LoopBack.
I was using this mixin that limits the limit of a query to max out at a defined value. When include is present in a query, the mixin also sets a limit on the scope of the include like so:
"include": {"foo":"bar","scope":{"limit":1}}
Seems the mixin was assuming all includes that are objects would be written in the form of {"relation":"foo", "scope":{"include:"bars"}}, so includes were getting added twice.
For what it's worth, I wrote this simple mixin to limit the maximum number of results unless specified and stopped using the one linked above:
common/models/model.json:
"mixins": {
"ResultsetLimit": {
"limit": 100
}
}
common/mixins/resultset-limit.js:
const _ = require('lodash');
module.exports = (Model, options) => {
/**
* Modify incoming query to apply appropriate limit filters.
*/
Model.beforeRemote('**', (ctx, unused, next) => {
// Get the limit from the request, defaulting to the max limit.
const request_limit = _.toNumber(_.get(ctx, 'args.filter.limit', options.limit));
// Set the limit.
_.set(ctx, 'args.filter.limit', request_limit);
next();
});
};
have you tried removing the following lines?
Because by default, if foreignKey is NOT set, it will set it as <relationName>Id. But since you set it to blank, loopback is not looking for any column to reference to. hence it is getting all the records on your related model.
{
"name": "Widget",
...
"relations": {
"foos": {
"type": "hasMany",
"model": "Foo",
"foreignKey": "widgetId"
}
}
}
{
"name": "Foo",
...
"relations": {
"bars": {
"type": "hasMany",
"model": "Bar",
"foreignKey": "fooId"
},
"widget": {
"type": "belongsTo",
"model": "Widget",
"foreignKey": "" // remove this
}
}
}
{
"name": "Bar"
...
"relations": {
"foo": {
"type": "belongsTo",
"model": "Foo",
"foreignKey": "" //remove this
}
}
}
UPDATE:
This is how I call 2nd (or 3rd) level relations:
/api/Widgets/1?filter={include: [{"relation":"foo", "scope":{"include:"bars"}}]}
My fixture data contains multiple array.Out of this multiple array cart_items contains some product data.
I am trying to calculate total no of products available in cart data (based on length of cart_items items) but i am not able to calculate no of items are present in cart_items.
In router i have selected application fixture as model for current route,as follow :
Astcart.IndexRoute = Ember.Route.extend({
model: function() {
return Astcart.Application.find();
}
});
Computed property code :
Astcart.IndexController = Ember.ArrayController.extend({
tot_cart_prd: function() {
return this.get("model.cart_items").get('length');
}.property("#each.isLoaded")
});
And my fixture data is :
Astcart.Application.adapter = Ember.FixtureAdapter.create();
Astcart.Application.FIXTURES = [
{
"logo_url": "img/logo.jpg",
"logged_in": {
"logged": true,
"username": "sachin",
"account_id": "4214"
},
"category_list": [
{
"id": "1",
"name": "Mobiles & Accessories"
},
{
"id": "2",
"name": "Computers & Software"
},
{
"id": "3",
"name": "Fashion"
},
{
"id": "4",
"name": "Electronics"
},
{
"id": "5",
"name": "Watches & Jewelry"
},
{
"id": "6",
"name": "Health & Beauty"
},
{
"id": "7",
"name": "Games"
},
{
"id": "8",
"name": "Books & Entertainment"
},
{
"id": "9",
"name": "Gaming"
},
{
"id": "10",
"name": "Shoes & Bags"
}
],
"cart_items": [
{
"id": "1",
"name": "Samsung Galaxy Tab 2",
"qty": "1",
"price": "1245.12",
"subtotal": "7842.23"
},
{
"id": "2",
"name": "Samsung Galaxy Tab 2",
"qty": "1",
"price": "1245.12",
"subtotal": "7842.23"
},
{
"id": "3",
"name": "Samsung Galaxy Tab 2",
"qty": "1",
"price": "1245.12",
"subtotal": "7842.23"
}
]
}
];
I have posted my code here(JSFiddle).
Can any one tell me why this.get("model.cart_items") is returning null?
Because your IndexController receive an array of Astcart.Application, from the route. You need to iterate in each application and get the length of each category list .
Your computed property need to be the following:
Astcart.IndexController = Ember.ArrayController.extend({
tot_cart_prd: function() {
var result = this.get('model').map(function(application) {
return application.get('category_list.length');
});
return result;
}.property('model.#each.category_list.length')
});
Here's an updated fiddle http://jsfiddle.net/marciojunior/PZZym/
I just looked at this and your core issue has something to do with the relationship setup between Application and Cart_items. The reason that this.get("model.cart_items").get('length') is failing is that this.get("model.cart_items") returns null. If you can get your relationship working you should be on the right track. I don't know anything about EmberModel, so I can't be of much help there.