I am trying to make a basic GET call to an API using JSON API specifications with deeply nested relationship data. I'm experiencing an issue with axios or vue manipulating my data...
Paying attention to pickup and delivery relationships, the raw data looks like the following:
{
"data": {
"type": "parent",
"id": "34",
"attributes": {
// ...
},
"relationships": {
"r1": {
"data": [
{
"type": "nextparent",
"id": "62",
"attributes": {
// ..
},
"relationships": {
"pickup": {
"data": [
{
"type": "package",
"id": 521,
"attributes": {
// ...
}
},
// ...
]
},
"delivery": {
"data": []
}
}
},
// ...
]
}
}
}
}
... where pickup has an array of objects and delivery has an empty array. However, when I try to retrieve the response in the callback, delivery is an exact copy of pickup.
var promise = window.axios({
url: window.baseApi + '/my-object/34',
method: 'get'
})
promise.then(function (response) {
console.log(response)
})
Whenever you run console.log(response) in the callback, Vue's observers are applied to the response object, which makes me wonder if this is a Vue issue considering that only the relationships of the first r1 object experience this.
Screenshot of log from callback (incorrect):
Additionally, I checked the response from the axios transformResponse function and the raw json was correct (without observers). This is only happening in the callback.
Screenshot of log from transformResponse (correct):
Will update with fiddle, as soon as I can.
EDIT:
The axios function is being called in a vuex action. Here is the code:
fetchData ({commit, dispatch}) {
var promise = window.axios({
url: window.baseApi + '/my-object/34',
method: 'get'
})
promise
.then(function (response) {
console.log(response)
commit('toggleProgress', {key: 'fetchingData'})
commit('setActive', response.data.data)
dispatch('otherModule/setActiveShipments', response.data.data, {root: true})
dispatch('history/clear')
})
.catch(function () {
//
})
return promise
},
Related
I need to mutate a graphql call in Cypress to where I can change certain key:value pairs within a fixture depending on the test.
I know I can call a graphql fixture with a format similar to this:
cy.intercept('POST', '/graphql', (req) => {
if (req.body.operationName === 'operationName') {
req.reply({ fixture: 'mockData.json'});
}
}
but pretend mockData has the following shape:
data: {
"user": {
"user": {
"userId": 123,
"inviteId": "123",
"status": "NEEDS_MORE",
"firstName": "Testy",
"lastName": "McTesterson",
"email": "test#testqa.com",
"phone": "3129876767",
"user": null,
"invite": {
"id": "12345",
"sentAt": null,
"sendDate": null,
"status": "NOT_SENT",
"__typename": "Invite"
},
},
}
}
How would I intercept the graphql call with all the info in mockData.json but change "status": "NEEDS_MORE" to "status": "CLAIMED" in my test without changing the rest of the fixture? The idea would be that in each it block of a spec, I re-use the same fixture but change the status, and have different assertions.
My attempts so far either only send the status without the rest of the data or only send the fixture without mutating anything. There is cypress documentation on how to do this in rest, but not in graphql. We're using typescript.
You can read the fixture first, make the modification before the reply
cy.fixture('mockData.json').then(data => {
data.user.user.status = 'CLAIMED'
cy.intercept('POST', '/graphql', (req) => {
// according to one reference, this is needed
const g = JSON.parse(req.body)
if (g.operationName === 'operationName') {
req.reply({
body: {data} // same reference shows reply stubbing in this format
})
}
}
})
Ref: Smart GraphQL Stubbing in Cypress
Consider using a dynamic import to read the fixture.
cy.intercept('POST', '**/graphql', async (req) => {
const data = await import('../fixtures/mockData.json')
data.user.user.status = 'CLAIMED'
if (req.body.operationName === 'operationName') {
req.reply({
body: {data}
})
}
})
Since you have typescript set up, add resolveJsonModule to tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress", "node"],
"resolveJsonModule": true
},
"include": ["**/*.ts"]
}
#Paolo's answer is good. An alternative to avoid using cy.fixture().then()
const mockedData = require('path/to/fixture/mockData.json')
// later in your test block
mockedData.user.user.status = 'CLAIMED'
cy.intercept('POST', '/graphql', (req) => {
if (req.body.operationName === 'operationName') {
req.reply((res) => (res.body.data = mockedData))
}
})
I'm doing a project where I'm fetching an api data from my backend laravel with axios get and using its property to concatenate a channel within the mounted section of my component.
I'm fetching api/user through axios get which contains
{
"id": 1,
"name": "admin",
"email": "admin#company.com",
"email_verified_at": null,
"created_at": "2019-08-17 10:06:14",
"updated_at": "2019-11-27 02:03:30",
"phone_number": "+12345678911",
"phone_number_verified": 0,
"company_id": 1,
"verification_code": "",
"signature": "",
"signature_image": null,
}
Here's how I'm getting the user data from my laravel backend through axios:
mounted() {
this.$http
.get('/api/user')
.then(response => ( this.user = response.data ))
.catch(error => console.log(error))
},
Which is then declared as an empty array in my data() section as such:
data() {
return {
user: [],
};
},
I can access the properties for example, id, in my template through {{ user.id }} and when I try to access it within the mounted() section, it gives me an object but when I try console.log(this.user.id) within the mounted, it throws undefined instead. The reason I need to access this.user.id within the mounted section is because I'm using it to concatenate the channel I'm using through Laravel Echo given as such:
mounted() {
this.$http
.get('/api/user')
.then(response => ( this.user = response.data ))
.catch(error => console.log(error))
this.$echo
.channel(`new-notification.${this.user.id}`)
.listen('NewNotification', (data) => {
// eslint-disable-next-line no-alert
this.notifications.unshift(data);
});
},
I'm fairly new to Vue and I don't know what I'm doing wrong in this. It would be of great help if someone can point out what I'm doing wrong or if there's a better method of doing it.
The issue is the console will run before the response of api call. You can make the call async and try.
mounted() {
this.fetchApi();
},
methods:{
fetchApi: async function(){
let response = await this.$http
.get('/api/user');
this.user = response.data;
this.$echo
.channel(`new-notification.${response.data.id}`)
.listen('NewNotification', (data) => {
// eslint-disable-next-line no-alert
this.notifications.unshift(data);
});
}
}
How to split data in JSON if have array after array? This is my JSON format
{
"status": "true",
"error": "",
"data": [
{
"id": 1,
"sections": [
{
"section_id": 1,
"position": []
}
]
}
]
}
So, I'm using AXIOS . This code AXIOS
const url = '/api/v1/form/'
axios
.get(url)
.then(response => {
this.listing = response.data.data;
})
How to call section using this response.data.data.sections ? I'm try but error undefined. Please help me thanks
response.data.data[0].sections
data is an array according to your json so you cannot directly call sections you will have to iterate or select an instance within the array.
the following code should print all section ids //untested code
const url = '/api/v1/form/'
axios
.get(url)
.then(response => {
response.data.data.foreach((listing)=>{
console.log(listing.sections.section_id)
})
})
If you always will have only one entry under data or you want to access only the 1st entry of data you can use response.data.data[0].sections this is a bad way to access it though because if data is empty it will throw you an error . If the case is that you only have one entry under data you should just change your json to be
{
"status": "true",
"error": "",
"data":
{
"id": 1,
"sections": [
{
"section_id": 1,
"position": []
}
]
}
}
and you can then access it directly response.data.data.sections but as long as its an array you will have to treat it as such.
Iterate through sections and positions [as per comments]:
const url = '/api/v1/form/'
axios
.get(url)
.then(response => {
response.data.data.foreach((listing)=>{ //#this will get you each listing(parent object that contains sections array)
listing.sections.foreach((section)=>{//# this will get you each section(parent object that contains position array)
section.position.foreach((el)=>{//# this will get you each elment in the position array as `el`
console.log(el)
})
})
})
})
Try this:
const url = '/api/v1/form/'
axios
.get(url)
.then(response => {
this.listing = response.data;
console.log(this.listing.data) // <-------
})
I am looking to write what I am calling structural expectations with Jest and I am not sure how this could be accomplished.
To start I have a graphql server and a database with a number of todo items. I currently have the following test that just returns true if the content within the database is the same as the response that I have written. I want to check instead that the response looks like an object with data that could be anything.
Here is the code that I have:
describe('To Do:', () => {
it('add todo items', async () => {
const response = await axios.post('http://localhost:5000/graphql', {
query: `
query {
getTodoItems {
message
id
dateCreated
dateDue
}
}
`
});
const { data } = response;
expect(data).toMatchObject({
data: {
getTodoItems: [
{
message: "message",
id: "5bd9aec8406e0a2170e04494",
dateCreated: "1540992712052",
dateDue: "1111111111"
},
{
message: "message",
id: "5bd9aeec60a9b2579882a308",
dateCreated: "1540992748028",
dateDue: "1111111111"
},
{
message: "new message",
id: "5bd9af15922b27236c91837c",
dateCreated: "1540992789836",
dateDue: "1111111111"
}
]
}
})
});
});
Now I want to write something like this, where there can be any number of returned items and they follow similar structuring:
describe('To Do:', () => {
it('add todo items', async () => {
const response = await axios.post('http://localhost:5000/graphql', {
query: `
query {
getTodoItems {
message
id
dateCreated
dateDue
}
}
`
});
const { data } = response;
expect(data).toMatchObject({
data: {
getTodoItems: [
{
message: expect.any(String),
id: expect.any(String),
dateCreated: expect.any(String),
dateDue: expect.any(String)
} // There needs to be unlimited additional items here
]
}
})
});
});
I have been looking throught the docs and I even tried nesting the expectations but I can't seem to get the desired response. Let me know what yo think or if I can clarify in any way.
I figured out the best way for me to do it. I would love to hear better answers. I wrote a function within the scope of the test as a jest.fn and then I called it. In that function, I made custom checks to parse the data that was received in the response. From there I added an expect function with the 'toHaveReturnedWith' method to see what the response of my custom function was and finishing out the test.
const addTodoResponse = jest.fn(() => {
// Custom parsing and check here
// Returns true or false
});
addTodoResponse();
expect(addTodoResponse).toHaveReturnedWith(true);
Are there better ways to do this out there?
I'm trying to get values using axios and on my browser returns [[PromisseValue]] undefined. Follow my code. Please, help-me... thanks
This is my data to get
<script>
export default {
props: ['endpoint'],
data () {
return {
response: {
table: '',
displayable: [],
records: []
}
}
},
methods: {
getRecords () {
return axios.get(`${this.endpoint}`).then((response) => {
console.log(response.data.data.table)
})
}
},
mounted () {
this.getRecords()
}
}
It will return promise because AXIOS is a promise function that you are trying to return.
axios.get(`${this.endpoint}`).then((response) => {
this.response.table = response.data.data.table
})
after axios call you need save it into your state or data the response then use it wherever you want.