Cypress request body interception and compare with a fixture / cont variable? - request

How can I intercept the entire requestbody and compare this with an fixture?
I tried:
it('Check if Frontend requestbody is the correct', () => {
cy.intercept('GET', '**/api/assessmenttestreference').as('ItemMove')
cy.wait('#ItemMove').its('request.body')
.to.equal({fixture:'MovedItemStructure.json'})
});
Is there a working or an alternative solution for this goal?

Use a routeHandler function, which gives you access to all properties of the request.
cy.fixture('MovedItemStructure.json').then(fixture => {
cy.intercept('GET', '**/api/assessmenttestreference', (req) => {
expect(req.body).to.deep.eq(fixture)
})
.as('ItemMove')
})
If you want to compare the response body, you can nest another callback
cy.fixture('MovedItemStructure.json').then(fixture => {
cy.intercept('GET', '**/api/assessmenttestreference', (req) => {
req.continue((res) => {
expect(res.body).to.deep.eq(fixture)
})
})
.as('ItemMove')
})

To check it against a fixture you will have to use deep.equal.
const movedItemStructure = require('/pathToFixtures/MovedItemStructure.json')
it('Check if Frontend requestbody is the correct', () => {
cy.intercept('GET', '**/api/assessmenttestreference').as('ItemMove')
// action to trigger request
cy.wait('#ItemMove').its('request.body')
.should('deep.equal', movedItemStructure)
});

Thanks to TesterDick. I have combined his answers to the following
cy.fixture('MovedItemStructure.json').then(fixture => {
cy.intercept('PUT', '**/api/assessmenttest/*', (req) => {
expect(req.body).to.deep.eq(fixture)
req.reply({ fixture: 'MovedItemStructure.json' })
}).as('ItemMove')
})

Related

Why isn't my Promise in a Post response in MockAdapter being evaluated?

When I mock a get using MockAdapter and reply with a Promise, the promise is evaluated fine and I'm able to select the response data.
When I try the same thing with a Post, it doesn't work. The .then method isn't evaluated and I don't get the response data.
test:
var axios = require("axios");
var MockAdapter = require("axios-mock-adapter");
let mock;
beforeAll(() => {
mock = new MockAdapter(axios);
});
afterEach(() => {
mock.reset();
});
test("", async () => {
const response = { data: { assignee: '' }};
mock.onPost(`${APP_ROOT}/${ASSIGN}`).reply(function (config) {
return new Promise(function(resolve, reject) {
setTimeout(function () {
resolve([200, response]);
}, 1000);
});
})
})
useEffect in page:
useEffect(() => {
assign(id)
.then(responseData => {
})
.catch(error => {
})
}
I've got a very similar test using mock.onGet returning a Promise and everything works fine. Is there a reason why this shouldn't work for a Post?
I've tried various url's on the Post. For the onGet, I leave it blank but haven't seen any onPost examples with this - is onPost() with no url legal?
In case it matters, I've also set up a localStorage mock.

using axios with promise API

I am using a promise based hook in a React app to fetch async data from an API.
I am also using a Axios, a promise based http client to call the API.
Is it an anti-pattern to use a promise based client inside another promise? The below code does not seem to work.
const getData = () => {
return new Promise((resolve, reject) => {
const url = "/getData";
axios.get(url)
.then(function(response) {
resolve(response);
})
.catch(function(error) {
reject(error);
});
});
const useAsync = (asyncFunction) => {
const [value, setValue] = useState(null);
const execute = useCallback(() => {
setPending(true);
setValue(null);
setError(null);
return asyncFunction()
.then(response => setValue(response))
.catch(error => setError(error))
.finally(() => setPending(false));
}, [asyncFunction]);
useEffect(() => {
execute();
}, [execute]);
return { execute, pending, value, error };
};
};
const RidesList = () => {
const {
pending,
value,
error,
} = useAsync(getData);
Oh man. I think you have a fundamental misunderstanding about how Promises work.
First, axios already returns a Promise by default. So your whole first function of getData can be reduced to:
const getData = () => {
const url = "/getData"
return axios.get(url)
}
But the meat of your code seems to indicate you want a querable Promise - so you can check the status of it for whatever reason. Here's an example of how you would do it, adapted from this snippet:
function statusPromiseMaker(promise) {
if (promise.isResolved) return promise
let status = {
pending: true,
rejected: false,
fulfilled: false
}
let result = promise.then(
resolvedValue => {
status.fulfilled = true
return resolvedValue
},
rejectedError => {
status.rejected = true
throw rejectedError
}
)
.finally(() => {
status.pending = false
})
result.status = () => status
return result
}
In this way, you can then do something like let thing = statusPromiseMaker(getData()) and if you look up thing.status.pending you'll get true or false etc...
I didn't actually run what's above, I may have forgotten a bracket or two, but hopefully this helps.
I have to admit - I haven't seen anything like this ever used in the wild. I am interested in knowing what you're actually trying to accomplish by this.
Axios itself returns a promise but if you want to make a custom class having your custom logic after each API call then you can use interceptors I was having the same requirement and this is how I am returning promises after applying my custom logic on each API call.
Interceptors will get executed separately after and before each request you made so we can simply use them if we want to modify our request or response.
here is my working solution have a look at it.
callApi = (method, endpoint, params) => {
this.apiHandler.interceptors.request.use((config) => {
config.method = method
config.url = config.baseURL + endpoint
config.params = params
return config
})
return new Promise((resolve, reject) => {
this.apiHandler.interceptors.response.use((config) => {
if (config.status == 200) {
resolve(config.data)
} else {
reject(config.status)
}
// return config
}, error => reject(error))
this.apiHandler()
})
}
Below is the code to call this function
helper.callApi("get", "wo/getAllWorkOrders").then(d => {
console.log(d)
})

How to use async function and export it correctly with React Native?

My question is about correctly implementing an async function to fetch data. I've a function called _getData() and I'm calling it on the componentDidMount() of a screen. But when server response is slow, switching to this screen is getting slower. So I would like to use async function for fetching data. But I'm not sure if I'm doing it correctly. Is that a correct approach? I can't be sure if it works async or not.
Here is my Api._getData() code:
const _getData = async () => {
return await axios.get("http://blabla.com/someservice", { params: someParamDataHere });
};
export const Api = {
_getData
};
and on SomeScreen.js, I also have loadData() function which calls the function above and does state updates.
loadData() {
Api._getData()
.then((response) => {
this.setState({ myData: response.data });
})
.catch((error) => {
console.log(error.response);
});
}
in componentDidMount() function of the same screen I'm calling this loadData()  function directly.
Now, is it enough to declare Api._getData() as async and using await in it, or should I change some trigger functions too?
Thank you very much for your help.
instead of async await use promises
export const getRequest = (url) => {
return new Promise((resolve, reject) => {
api
.get(url)
.then((response) => {
handleReponse(response)
.then((errorFreeResponse) => {
resolve(errorFreeResponse);
})
.catch((error) => {
reject(error);
});
})
.catch((error) => {
reject(handleError(error));
});
});
};
You are doing correct while retrieving in load Data . What you can do more is try more syntactical sugar of es6 by using async await in loadData , hence
loadData = async() =>{
try{
let response = await Api._getData();
this.setState({ myData: response.data });
} catch(err){
console.log(error.response);
}
}
Hope it helps. feel free for doubts

How to write test cases to cover all the nested 'then' callbacks in a promise chain

I'm having difficulty covering the entire promise chain in my unit test coverage. I did find articles that gave me the nearest solution but the challenge is at the last 'then' I need to call three function that does not return a promise.
Below is the example/Sample I tried
async = jest.fn(() => {
return Promise.resolve('value');
});
async1 = jest.fn(() => {
return Promise.resolve('value1');
});
async2 = jest.fn(() => {
return Promise.resolve('Final Value');
});
it('test my scenario', (done) => {
someChainPromisesMethod()
.then(data => {
expect(async1).toBeCalledWith('value');
expect(async2).toBeCalledWith('value1');
expect(data).toEqual('Final Value');
done();
});
});
Below is the function which returns another function with nested 'then' functions. I need help with the test cases to cover them all.
function consolidatedReport(param1, param2){
const somedata = param1.data;
const someOtherData = param2.data;
if(true){
doThisthing();
}
return promiseChainBegin(somedata, someOtherData)
.then(response => response && functionOne(somedata, someOtherData)
.then(response => response && functionTwo(somedata, someOtherData)
.then(response => response && functionThree(somedata, someOtherData)
.then(response => response && functionFour(somedata, someOtherData)
.then(response => {
if(response) {
notApromiseFuncOne(somedata)(someOtherData);
notApromiseFuncTwo(somedata)(someOtherData);
notApromiseFuncThree(somedata)(someOtherData);
} else{
notApromiseFailCase(someOtherData);
}
});
}
I'm having difficulty covering the nested then functions.
You'd mock each of functionOne, etc resolved values:
import functionOne from '../path/to/functionOne';
import functionTwo from '../path/to/functionTwo';
import functionThree from '../path/to/functionThree';
jest.mock('../path/to/functionOne');
jest.mock('../path/to/functionTwo');
jest.mock('../path/to/functionThree');
it('test my scenario', () => {
functionOne.mockResolvedValue('value 1');
functionTwo.mockResolvedValue('value 2');
functionTwo.mockResolvedValue('value 3');
return someChainPromisesMethod()
.then(data => {
expect(functionOne).toBeCalledWith('value returned by promise');
expect(functionTwo).toBeCalledWith('value 1');
expect(functionThree).toBeCalledWith('value 2');
expect(data).toEqual('Final Value');
});
});
This is not exactly your code, but the idea goes like that. You mock the resolved value for each of your functions.

How to pass query parameters to a url inside a lambda function (netlify environment)

When the user submit a search form I want to add the query parameter to the api url that is inside a lambda function.
I set up the netlify environment inside a react app and initialize a lambda function.Now I only get the response using hard-coded queries.
How can I pass parameters to the event.queryStringParameters?
exports.handler = function(event, context, callback) {
const API_PARAMS = qs.stringify(event.queryStringParameters);
const { API_TOKEN, API_URL } = process.env;
const URL = `${API_URL}search?part=snippet&maxResults=5&key=${API_TOKEN}&q=animals`;
// Let's log some stuff we already have.
console.log("Injecting token to", API_URL);
console.log("logging event.....", event);
console.log("Constructed URL is ...", URL);
console.log('params are...', API_PARAMS);
const pass = body => {
callback(null, {
statusCode: 200,
body: JSON.stringify(body)
});
};
const get = () => {
axios
.get(URL)
.then(response => {
console.log(response.data);
pass(response.data);
})
.catch(err => pass(err));
};
if (event.httpMethod == "GET") {
get();
}
};
App.js
componentDidMount() {
fetch('.netlify/functions/youtube')
.then(response => response.json())
.then(data => console.log(data));
}
this took me a minute to figure out but it's in the query string:
let thing = 123;
fetch(`/.netlify/functions/${filename}?item=${thing}`)
.then(response => response.json())
.then(json => console.log(json))
if it's a post, you will need to parse it from the query but a regular get call you can pull it out of the event.queryStringParameters

Resources