I need to check if some values in submitted data have expected values. To do this i tried to access and sent data by XMLHttpRequest in Cypress during the request run.
describe('test submitted data', () => {
it('some data is changed', () => {
submitBtn().click({force: true});
//in this case Cypress doesnt get into this debugger point
cy.server({
onAnyRequesty: (props) => {
debugger
}
});
//in this one Cypress go into and stops at the point but
//the data variable doesnt contrain submitedData
cy.route('PUT', `${APP_CONTEXT}/api/model/${modelId}`, (data) => {
debugger;
});
});
});
Data is sent by the way below:
$.ajax({
url: url,
method: "PUT",
data: "{"inputData":"123"}",
contentType: "application/json",
success: () => {},
error: () => {}
});
What am i doing wrong? Thanks
One more thing: and how to make Cypress check if the data condition is met? for example:
it('some data is changed', () => {
submitBtn().click({force: true});
cy.route('PUT', `${APP_CONTEXT}/api/model/${modelId}`, (data) => {
const parsedData = JSON.parse(data);
// the test is passed if the value is equal
expect(parsedData.inputData).to.eq('123');
});
UPDATE
i tried proposed answer from #richard-matsen and different callBack keys but neither were working:
onResponse
onAnyResponse
onRequest
onAnyRequest
But callback function in neither of them didnt run
it("Signature removed from the field and empty value submitted", () => {
cy.server();
submitBtn().click();
//here i check the put url as an url submitting to
cy.log(`${BASE_URL}/api/data/${formId}/${modelId}`);
cy.route({
method: "PUT",
url: `${BASE_URL}/api/data/${formId}/${modelId}`,
onAnyRequest: (data) => {
const signValue = JSON.parse(data)[`${modelId}|sign_2||`];
debugger;
cy.log(signValue);
expect(signValue).to.eq(null)
}
})
})
UPDATE UPDATE
#richard-matsen ,thanks, you were right, I did an error in method options, but I decided to simplify the route options but still the debugger cannot get in neither handler:
it("Submitted data", () => {
cy.server({ whitelist: (xhr) => console.log('custome log: server', xhr) });
submitBtn().click({force: true});
cy.route({
url: /.+/,
onResponse: (data) => {
debugger;
cy.log('onResponse signature value - ' + data);
},
onAnyResponse: (data) => {
debugger;
cy.log('onAnyResponse signature value - ' + data);
},
onRequest: (data) => {
debugger;
cy.log('onRequest signature value - ' + data);
},
onAnyRequest: (data) => {
debugger;
cy.log('onAnyRequest signature value - ' + data);
}
})
})
Also tried to click submission btn right after cy.route, but that wasn't working as well.
I appreciate your help!
The patterns for using cy.route() are
cy.route(url)
cy.route(url, response)
cy.route(method, url)
cy.route(method, url, response)
cy.route(callbackFn)
cy.route(options)
Looks like your command is interpreted as #4, but response is the value used to stub. Never seen it with a function, so is best guess.
To be sure, use the pattern with options and put function in onResponse
cy.route({
method: 'PUT',
url: `${APP_CONTEXT}/api/model/${modelId}`,
onResponse: (data) => {
expect(parsedData.inputData).to.eq('123');
}
})
Also onAnyRequesty: (props) => change to onAnyRequest: (props) =>.
In your latest code,
onAnyRequest: (data) => {,
data is already parsed so JSON.parse(data) causes an error.
In my test, I get a weird error about cross-origin when trying to re-parse within onResponse() (Expecting a message like 'Unexpected token o in JSON at position 1').
In any case, put the debugger up one line to avoid other code problems.
If cy.route() is not matching the url, you can see all calls with (temporary)
cy.server({ whitelist: (xhr) => console.log('server', xhr) }).
Maybe APP_CONTEXT !== BASE_URL?
Submit can be a native event which won't be captured by Cypress.
I think you can test if this is so, see Submit a POST form in Cypress and navigate to the resulting page.
If you do the following instead of submitBtn().click({force: true}) and the cy.route() does pick it up, then you have a native event.
cy.visit({
url: `${BASE_URL}/api/data/${formId}/${modelId}`,
method: "PUT",
form: true,
body: {
inputData :"123"
}
});
Related
What I am trying to achieve is sending a bunch of post requests to a print service, and if any of them fail I want to display a warning message to the user. My current set up has a warning message for each time it fails.
items.forEach(function (item) {
var data = {
date: self.getDateTime(),
barcode: item.barcode,
description: item.description
};
var url = 'http://localhost/print_service'
$.ajax({
method: "POST",
url: url,
data: JSON.stringify(data),
}).fail(function () {
self.display_warning(
'Failed to connect to printer',
);
});
});
I am not able to make use of async / await in this project.
My thought was to just set some flag like printFailed = true, and after the loop just display a message if it is true. However, the fail is of course asyncronous, so the flag is now set when I make that check.
How can I tackle this effectively? Typically I would throw the error and / or flag into a .then(), but I can't do this as it would then still be caught in the loop.
Try to use Promise.all:
const requests = items.map(function(item) {
return $.ajax({
method: "POST",
url: 'http://localhost/print_service',
data: JSON.stringify({
date: self.getDateTime(),
barcode: item.barcode,
description: item.description
}),
});
});
Promise.all(requests).catch(function() {
self.display_warning('Failed to connect to printer', );
});
I'm developing a website with express and ejs. I got into a trouble where i need to call an api via ajax. The problem is on a button onclick i'm passing two values to ajax data. but it gives error ,i tried a lot of ways and i'm messed up. i'm a newbie , find my code below.
const parsedData = JSON.parse(localStorage.getItem('myData'));
const container = document.getElementById('s1');
parsedData.data.rows.forEach((result, idx) => {
var a = result.master_id;
var b = result.session_name;
console.log(a,b,"a","b")
var userData = {"pid":a,"session" :b};
console.log(userData,"userData");
sessionStorage.setItem("user", JSON.stringify(userData));
console.log(userData,"data for api");
const card = document.createElement('div');
card.classList = 'card';
const content = `
<div class="row">
<div class="card-body" onclick="graphApi()">
</div>
</div>
`;
container.innerHTML += content;
});
function graphApi(){
var apiValue =JSON.parse( sessionStorage.getItem("user"));
console.log(apiValue, "value from card");
$.ajax({
type: "POST",
data: apiValue,
dataType:"json",
url: "http://localhost:5000/graphFromcsv",
success: function(data) {
console.log(data,"graph api");
}
error: function(err){
alert("graph api failed to load");
console.log(err);
},
});
i'm always getting this pid in api value undefined and 400 badrequest . but if i use raw data like,
{
"pid":"WE6",
"session":"W.csv"
}
instead of apiValue my ajax is success and i'm gettig the data. i'm using this data to plot a multiple line graph. Any help is appreciated.
You need to correct data key and their value(value must be string in case of json data) and also add contentType key like
$.ajax({
type: "POST",
data: sessionStorage.getItem("user") || '{}',
dataType: "json",
contentType: "application/json",
url: "http://localhost:5000/graphFromcsv",
success: function (data) {
console.log(data, "graph api");
},
error: function (err) {
alert("graph api failed to load");
console.log(err);
},
});
Note: In backend(ExpressJS), make sure you are using correct body-parser middleware like app.use(express.json());
Let assume your apiValue contain {"pid":"WE6", "session":"W.csv" } then body: { apiValue } will be equal to:
body: {
apiValue: {
"pid":"WE6",
"session":"W.csv"
}
}
But if you use the link to the object like body: apiValue (without brackets) js will build it like:
body: {
"pid":"WE6",
"session":"W.csv"
}
I'm trying to sketch as in the image below the mistakes made by mis-inserting data into the form.
However, it only works when the data is entered correctly. It should show "Invalid CPF", for example.
JavaScript code:
$("#formCadastro").on("submit", function (event) {
event.preventDefault();
var dados = $(this).serialize();
$.ajax({
url: getRoot() + 'controllers/controllerCadastro',
type: "POST",
dataType: "json",
data: dados,
success: function (xhr) {
$(".retornoCad").empty();
$(".retornoCad").append("Dados inseridos com sucesso!");
},
error: function (xhr) {
$(".retornoCad").empty();
getCaptcha();
$.each(xhr.response, function(key,value){
$(".retornoCad").append(value + '<br>');
});
}
});
});
And the .php file for validation is:
public function validateFinalCad($arrVar)
{
if (count($this->getErro()) > 0) {
$arrResponse = [
// print_r($this->getErro())
"retorno" => "erro",
"erros" => print_r($this->getErro())
];
} else {
$arrResponse = [
// print_r($this->getErro())
"retorno" => "success",
"erros" => null
];
/*$this->cadastro->insertCad($arrVar);*/
}
return json_encode($arrResponse);
}
The error callback will only run if the entire HTTP request fails (i.e. it returns a status code which is not 200 (or related such as 201 etc)). It won't go to error just because you returned some JSON which contains messages which you consider to indicate validation errors. It's not a HTTP error.
Either
a) make the PHP return a 400 Bad Request response when there are validation errors, or
b) write code in the "success" to check the contents of the JSON and act accordingly.
e.g. this would do the job for option (b) :
success: function (xhr) {
$(".retornoCad").empty();
if (xhr.retorno == 'erro') {
getCaptcha();
$.each(xhr.erros, function (key, value) {
$(".retornoCad").append(value + '<br>');
});
} else {
$('.retornoCad').append('Dados inseridos com sucesso!');
}
}
Also, $.each(xhr.erros isn't going to do much, because in your PHP, erros is either null or a string (because you used print_r, which is supposed to only be a debugging tool). "erros" => $this->getErro() would be better (assuming getErro() returns an array of strings).
i.e.
$arrResponse = [
"retorno" => "erro",
"erros" => $this->getErro()
];
I have a function that gets the form values and send them Flask backend to retrieve info from SQLite database. I'm using jQuery $.ajax() with POST to allow for better error handling.
Because the ajax is async I'm passing a callback to logTable(callback) as suggested here. I need the logTable() to run after I input the form data and click the submit button. I'm using $("#some-id").click() to achieve this.
const logsTable = (callback) => {
const startDate = $("#start-date").val();
const endDate = $("#end-date").val();
const container = $("#programs").val();
const server = window.location.host;
const url = `http://${server}/api/log-info`;
let logs = "";
let dataToSend = {
start_date: startDate,
end_date: endDate,
program: container,
};
$.ajax({
type: "POST",
url: url,
data: dataToSend,
success: (data) => {
callback(data);
},
error: (jqXHR, textStatus, errorThrown) => {
alert(errorThrown);
},
});
};
$("#submit-button").click(() => {
return logsTable((data) => {
$("#logs-div").html(data);
alert("Success");
});
});
I receive the alert with Success, the data briefly appears on the page and disappears. If run the code below directly it, it runs on page reload and posts an empty list to a page because no data was sent to the backend.
logsTable((data) => {
$("#logs-div").html(data);
alert("Success");
});
I need to somehow the function call above to a Submit button. How can I do that?
I try to make dropdown option dependent using ajax . i want to see the data in console whether the data is success or else. I expect the data was shown in console log but error given
http://localhost/fic/public/sla/sla/getbranch/180 404 not found
Here is my code for view ajax
if(country_id) {
//console.log(country_id);
$.ajax ({
url: 'sla/getbranch/'+country_id,
//url: "{{ route('sla.getbranch') }}"+country_id,
type: 'GET',
datatype: 'json',
success: function(data){
console.log(data);
}
})
My controller
public function index()
{
$custList = $this->hdcustomermaster->getAllCustomerActiveSts();
return view('sla.slm.SLAList', compact('custList'));
}
public function getbranch($id)
{
$data=HDCustomerBranch::where('cb_customer_ID',$id)->pluck('cu_customer_ID','cu_customer_Name');
return json_encode($data);
}
my web.php
Route::group(['prefix' => 'sla'], function () {
Route::get('/','SlaController#index');
Route::resource('sla', 'SlaController');
Route::get('sla/getbranch','SlaController#getbranch')->name('sla.getbranch');
});
Replace your route like this
Route::group(['prefix' => 'sla'], function () {
Route::get('/','SlaController#index');
Route::resource('sla', 'SlaController');
Route::get('sla/getbranch/{id}','SlaController#getbranch')->name('sla.getbranch');
});
Here the problem is you are passing 180 as an param in that route. But you dont declare that param in your route.
Also you can add a '?' if it is an optional param, like this
Route::get('sla/getbranch/{?id}','SlaController#getbranch')->name('sla.getbranch');