intercept a call when a button is clicked - cypress

I have the following steps
Click button
when the button is clicked, a save request is being sent
the website navigate to other page
Now I need to intercept the request sent to the backend to get information not displayed on the other page (date of appointment including timestamp and zone for instance)
I have the following code
let date = ''
cy.intercept('POST', '**/appointments/v1', (req) => {
// make an assertion on the payload contents
expect(req.body).not.to.be.null
console.log(req.body['date'])
date = req.body['date']
}).as('appointment')
cy.get('[data-cy="appointment-confirm"]').should('exist').find('button')
.click({force: true})
cy.wait('#appointment')
the request is being intercepted on the abovementioned code, but the navigation to the next page is will not take place, as I I have not clicked the button at all. The data of the request are also not saved to the backend.
I looks like the intercepted request is being stopped
I have also used
let date = ''
cy.intercept('POST', '**/appointments/v1', (req) => {
// make an assertion on the payload contents
expect(req.body).not.to.be.null
console.log(req.body['date'])
date = req.body['date']
}).as('appointment')
cy.get('[data-cy="appointment-confirm"]').should('exist').find('ion-button')
.click({force: true}).then(()=>{
cy.wait('#appointment')
})
I have also treid
cy.intercept('POST', '**/appointments/v1', (request) => {
expect(request.body).not.to.be.null
console.log(request.body['date'])
date = request.body['date']
request.continue()
}).as('appointment')
but have the same issue
I have figured out, that the intercepted request is now returning 400 Bad request

IMO, actually your code almost correct and I suggest you to try something like this
cy.intercept({ method: 'POST', url: '**/roles' }).as('responseRole')
// after intercept you can click the button
cy.get('button').click()
// and wait for cypress to get the result as alias
cy.wait('#responseRole').then(({ request, response }) => {
console.log(request.body)
console.log(response.body)
})

I tried multiple scenarios and I almost had the same issue. I changed the sequence and it worked. Such that:
Click Button
Intercept
Wait
This happens because requestTimeout of cy.wait() needs the API to fire before intercept.
For reference see here: https://docs.cypress.io/api/commands/wait#Timeouts
Your code should look like this:
let date = '';
cy.get('[data-cy="appointment-confirm"]').should('exist').find('button')
.click({force: true});
cy.intercept('POST', '**/appointments/v1', (req) => {
// make an assertion on the payload contents
expect(req.body).not.to.be.null
console.log(req.body['date'])
date = req.body['date']
}).as('appointment');
cy.wait('#appointment');

Related

GravityView Ajax Link

I have a table created with GravityView and I want to implement the single entry link with Ajax so that the page does not refresh and the URL does not change.
Is such a thing possible?
enter image description here
You can load the single entry page with jQuery .load method.
You would need to pass the URL of the page, in this case I am trying to get the content on another page whose URL is in the anchor link of the table, in your case its link field.
So i give the .load method URL + the id of the accordion in which the content i need to display exists, and a call back function.
Here how I did it.
jQuery( document ).ready(function($) {
// select the div where you want to display content
var $loadedContent = $('#fl-accordion-5c450fd66133e-panel-0');
// register an event, get the click event of the link
$(document).on('click','.gv-field-3-date_created a', function(event) {
//stop the link form opening
event.preventDefault();
//get URL from the href attribute of the anchor link
var $url = $(this).attr("href");
// send the request and get the response, In my case I am trying to show the content inside a accordian, so i have taken its ID and added that with URL
$loadedContent.load($url+' #fl-accordion-5c450fd66133e-panel-0', completeFunction);
return false;
});
function completeFunction(responseText, textStatus, request) {
if(textStatus == 'error') {
// show a relevant message
$loadedContent.text('An error occurred during your request: ' + request.status + ' ' + request.statusText);
}
}
});
Just add your classes, and it will get the Job Done.
Thanks for using GravityView! Zack here, founder.
We’re going to be adding this functionality later this year. If you wait a few months, it’ll be ready!

how to cancel one of the pending http request from many angular 8

I have an implementation for a file upload api using drag and drop multiple files. I am making a call within the for loop as below
uploadFile(file:any[]) {
file.forEach((file, index)=>{
const formData = new FormData();
formData.append('report_file', file);
this.fileService.uploadFile(this.configurations.uploadUrl, formData)
.subscribe(fileResp=>{
console.log('file', fileResp);
}, error=>{
console.log('error while uploading files', error);
});
});
}
This works while uploading. However, I have a requirement to be able to cancel one of the pending file if needed. so, how do I cancel a particular http request if user is opting to cancel that upload? for the bulk cancel I can do unsubscribe to my observable but in this case I need to make others still be uploading.
Here's an idea:
const files$ = from(files);
files$.pipe(
mergeMap(
file => this.fileService.uploadFile(/* ... */).pipe(
takeUntil(fromEvent(getButtonThatCorrespondsToFile(crtFile), 'click').pipe(take(1)))
)
)
)
function getButtonThatCorrespondsToFile (): HTMLButtonElement { }
mergeMap - will allow you to start making a request for each file at the same time
takeUntil - attached to the request's observable of each file; makes sure that when a button that corresponds to a certain file is clicked, it will cancel the current request
Now I guess a small problem is how you get a button that corresponds to a file, but I think that wouldn't be too difficult. You could use, for example, #ViewChildren to get all the buttons, and by using the index in the mergeMap's projection function(2nd argument; mergeMap((val, idx) => ...)), you could identify a certain file.

React/Redux form submission

In my application, I am using actions to do all of my ajax calls. When the results come back, it dispatches them to the reducer, which then puts it in the store. My component is bound to the property and will then be able to get it from the store.
However, I am having an issue trying to figure out the best way to do form submissions. From a listing page, a user can click on a link from any row to open a modal. This modal has a form in it. When the form is filled out, it will then pass the data along to an action, which will submit it. The only response from a valid submission is a HTTP 200.
Without using callbacks, how would the modal know that the ajax call is complete, so it can close itself? As of now, I have a flag in the store called form.processing. This is default to false, and the action will set it to true when it begins and false when its done. The component watches this and then knows when it goes from true to false and knows everything is done. However, I feel like there should be a better way.
Or should I be using callback in forms, even though we don't follow that process for any other ajax call?
Here are following pseudo code can help you:
constructor () {
this.state = {
disaplyModalPopup: false;
}
}
handleSubmit = () => {
this.setState({disaplyModalPopup: true})
let payLoad = { 'Key':this.state.something }
this.props.hitAPI(payLoad).then((res) => {
if (res.data.success) {
this.setState({
'disaplyModalPopup': false
})
}else{
this.setState({
'disaplyModalPopup': true,
'errorMessage': 'something wend wrong'
})
}
})
}
rendor (){
let errorMessage = {this.state.errorMessage}
let disaplyModalPopup = {this.state.disaplyModalPopup}
return (
{disaplyModalPopup ? <modal> </modal> : ''}
{ errorMessage? 'errorMessage': ''}
)
}
Here I have handled your modalPopup with disaplyModalPopup state.
And After get in the response saved in reducer, it is changes as {disaplyModalPopup: false}
And modalPopUp HTML will disappear.
But in case your API get in failed while making response.
So that case: i have handle as error message in as text
errorMessage where you can show your error message. So that Modal is closed side by side.

AngularJs POST json data stored in $scope through ajax

I'm getting mad: I'm working with angular js and I don't know how to post data correctly.
I've filled some html input fields, whose values are stored in (ex.) $scope.prodotto, and I must send the json structure of $scope.product to a webservice I've written.
Unfortunately using the inspector, I' can't see anything.
I mean: I've written this:
$scope.salva = function() {
console.log($scope.prodotto);
$http.post('./service/prodotti/create', $scope.prodotto).error(function(data, status, headers, config){
console.log($scope.prodotto);
});
};
Salva is binded to a button. through ng-click argument. When I click the button, "salva" is triggered.
I see that $scope.prodotto is populated with the right values (thanks to console.log), but...the server receives nothing, and the browser doesn't send anything (inspecting the req with chrome's inspector, shows an empty array)
So what am I doing wrong?
Thanks in advance!
I've found the solution.
Unfortunately the variable "$scope.prodotto" has been initialised as an array:
$scope.prodotto = [];
The solution is simple. Initialize it as an object:
$scope.prodotto = {};
That's it.
You are only checking the ajax call if there is an error with your original post. you need to use the success callback like this:
$scope.salva = function() {
console.log($scope.prodotto);
$http.post('./service/prodotti/create', $scope.prodotto)
.success(function(data, status, headers, config){
console.log($scope.prodotto);
});
.error(function(data, status, headers, config){
console.log($scope.prodotto);
});
};

Handle ajax response with node.js

I am trying to scrape information from a specified website. This site uses authentication first, thus a i use zombie.js:
var Browser = require("zombie");
var browser = new Browser();
browser.visit("https://*****login.aspx", function(){
browser.fill('#user', '*****');
browser.fill('#pwd', '*****');
var button = browser.querySelector('#btnSubmit');
browser.fire('click', button, function(){
//scraping main.aspx
});
});
It's working, i can scrape the main.aspx: there is a <table>, containig information about new messages(from, date, subject,), the problems comes here: the subject field is clickable, and clicking on it makes a new window appear with the actual message. However it is an ajaxgrid, and when i perform a click:
var field = browser.querySelector('#VeryLongIdOfTheField');
browser.fire('click', field, function(){
console.log(browser.querySelector('#VeryLongIdOfTheFieldContainingTheMessage').innerHTML);
});
it returns an error message, saying that undefined has no innerHTML. I suppose its because this action handled with some ajax magic. I am new in this js/nodejs/jquery/.. world, some help needed to enlight me.
Since the data is populated using async ajax, I'm guessing there's a lag between your click and the actual DOM population inside the node. How about waiting for a bit before checking the content inside the node.
browser.fire('click', field, function(){
setTimeout(function(){
console.log(browser.querySelector('#VeryLongIdOfTheFieldContainingTheMessage').innerHTML);
}, 3000)
});
If the time taken is not very predictable, you could also run it inside a loop until you find the content or exit after a reasonable number of retries.

Resources