Error trying to get attribute from element in Cypress - cypress

I have this HTML element:
<input id="" type="text" name="last_name" value="Userc7bff2d0-7faf-11e8-9884-8fe4c5df7f77-Updated" class="medium" maxlength="2000" autocomplete="off" tabindex="" data-reactid=".0.2.0.1.0.2.1.0.1.0.0.1:0.1.0.1.2:$/=10">
I want to get it's value property to assert that it has been updated by my test.
I have tried using its():
cy
.get(selector)
.its("value")
.should("contain", "-Updated");
But get the error:
CypressError: Timed out retrying: cy.its() errored because the property: 'value' does not exist on your subject.
I have also tried invoke:
cy
.get(selector)
.invoke("value")
.should("contain", "-Updated");
But get a similar error:
CypressError: Timed out retrying: cy.invoke() errored because the property: 'value' does not exist on your subject.
In both cases, the Cypress console output of the get() command shows the element with its value property successfully:
Yielded: input id="" type="text" name="first_name" value="Fake-Updated"
class="medium" maxlength="2000" autocomplete="off" tabindex="" data-
reactid=".0.2.0.1.0.2.1.0.1.0.0.1:0.1.0.0.2:$/=10"
I'm kind of stumped on this one. Please let me know if you want more info or have an idea what's going on.

invoke() calls a jquery function on the element. To get the value of an input, use the function val():
cy.get('input').invoke('val').should('contain', 'mytext')
This is not the same as getting the value attribute which will not update with user input, it only presets the value when the element renders. To get an attribute, you can use the jquery function attr():
cy.get('input').invoke('attr', 'placeholder').should('contain', 'username')

you can use this
cy.get('a') // yields the element
.should('have.attr', 'href') // yields the "href" attribute
.and('equal', '/home') // checks the "href" value
or
cy.get('a').should('have.attr', 'href', '/home')
for more details check this: https://docs.cypress.io/api/commands/should#Method-and-Value

If above answers doesn't work try this,
cy.get('input[placeholder*="Name"]')
Find the input with a placeholder attribute containing the word "Name".

Now there is a plugin for your need.
https://github.com/Lakitna/cypress-commands/blob/develop/docs/attribute.md
With this, you'll be able to do :
cy.get('input').attribute('placeholder').should('contain', 'username');

Aprt from above suggestions, you can also get the value using prop()
The benefit of using prop() over attr() is that:
The prop() will always give you the current value but the attr can sometimes give you the default value no matter how many times you updated it.
cy
.get(selector)
.invoke("prop","value")
.should("contain", "-Updated");

Related

Get Input Data Value in Controller in Laravel

I want to get the value of this input.
<input type="text" name="txtEmployeeNo" value='{{ $employee->employee_no }}'>
Its value is 53210. How can I get that in my controller?
I currently have this on my controller.
$employeeNum = $request->input('txtEmployeeNo');
$employeeSched = Schedule::where(['employee_no'=>$employeeNum])->get();
return view('admin.employeemaintenance.createSchedule',compact(,'employeeSched'));
The problem is when I open and see if it is fetched nothing is showing. I cannot get the input.
Try this, It should must work.
$employeeNum = (isset($request['txtEmployeeNo'])) ? $request['txtEmployeeNo'] : 0;
$employeeSched = Schedule::where(['employee_no'=>$employeeNum])->get();
return view('admin.employeemaintenance.createSchedule',$employeeSched);
In your controller insert this line after opening your function:
dd($request->all);
It will show you everything that has been posted through your form with values. If you get your 'txtEmployeeNo' without value, it means something went wrong when you insterted it in your input.
Check with dev tools if that specific input has any value.
If your input has the value you mentioned and your $request->all() still shows an empty value for your "txtEmployeeNo", then the error is in the HTML/Blade file.
Make sure you create the form correctly
Make sure your input's name equals with the request you are trying to receive in your controller.
If you get null as the value of the $request, that could mean, in your Blade file, the input also has it's value as null.
Try to manually insert a value like <input type="text" name="txtEmployeeNo" value="2"> and see if you get that in your controller. If you do, then the query in your input is wrong.
That's all I could think of without provided Blade and Controller code.
Try this:
$employeeNum = $request->input('txtEmployeeNo');
$employeeSched = Schedule::where('employee_no', $employeeNum)->get();
return view('admin.employeemaintenance.createSchedule',compact('employeeSched'));
well, here is an edit to this answer with the steps needed:
in your routes:
Route::post('yourRouteName','yourController#nameOfFunctionInController')->name('TheNameOfTheRoute');
In your controller:
public function nameOfFunction(Request $request) {
$employeeNum = $request->input('txtEmployeeNo');
$employeeSched = Schedule::where('employee_no', $employeeNum)->get();
return view('admin.employeemaintenance.createSchedule',compact('employeeSched'));
}
And that's it basically.

Cypress picks up the wrong element?

I am trying to find and click this element using Cypress:
<input class="form-control btn btn-primary" type="button" value="Log out">
I have tried several variations, but the closest is this:
cy.get("input[type='button']").filter('.btn-primary').should('have.value','Log out').click()
So when I run this, I get the following response:
expected [ <input.form-control.btn.btn-primary>, 1 more... ] to have value Log out, but the value was Edit.
Sure, there is a button there called Edit, but it is not the one I want. I have specified what I want with the should('have.value','Log out') clause.
So - why does it insist on trying to use the wrong element & failing?
Update: I finally got this working.
This is the solution I went with in the end:
cy.get("input[type='button']").filter('.btn-primary').eq(1)
.should('have.value','Log out').then(($btn) => {
$btn.click()
})
can you try
cy.get('input').find("[value='Log out']").click()
or
cy.get("[value='Log out']").click()
Obviously you need your developers to add ids, but I know your situation.
You could also try if there is only one btn-primary
cy.get('.btn-primary').click()
This was the solution that worked for me:
cy.get("input[type='button']").filter('.btn-primary').eq(1)
.should('have.value','Log out').then(($btn) => {
$btn.click()
})
How about to set an unique testID for that button and get it as simple as it can be.
Something like:
data-test-id= "log-out-button" //put that in your button code
and then in Cypress:
cy.get('[data-test-id="log-out-button"]')
.click()
even though you can set a function to get those testID's more effectively:
Command.Cypress.add('getTestID', (testID) => {
cy.get(`[data-test-id="${testId}"]`)
})
and now everything you do for getting that button (or every element with testID is: cy.getTestID('log-out-button')

Angular 2 form valid by default

Having issue with form validation .
i want to submit the form only when form is valid.
but with the empty inputs and clicking on submit button is submitting the form although the inputs are empty.
<form name="equipmentForm" #f="ngForm" (ngSubmit)="f.form.valid && addEquipment()" validate>
Inputs be like this.
<input name="equimentId" class="text-input form-control" type="text" [(ngModel)]="model.equipmentNumber" pattern="^[0-9][0-9]{1,19}$" title="Equipment ID. can be upto 20 digits only.">
I cant post the whole code although.
this
f.form.valid is true from form initialization
wanted to acheive something like this
<div *ngIf="!model.equipmentModel && f.submitted" class="text-danger">
Please enter Equipment Model
</div>
So on submit i want to show this message instead of default browser's.
but this f.form.valid is goddamn true from default.
You should add required attribute to your input tags to, then as #Cobus Kruger mentioned, form will not be submitted untill it is filled.
However you can also give a try to pristine, dirty options, which allow you to check if the user did any changes to the form so in this case your condition may look like this:
<form name="equipmentForm" #f="ngForm" (ngSubmit)="f.form.valid && f.form.dirty ? addEquipment() : ''" validate>
and the input:
<input name="equimentId" class="text-input form-control" type="text" [(ngModel)]="model.equipmentNumber" pattern="^[0-9][0-9]{1,19}$" title="Equipment ID. can be upto 20 digits only." required />
In this case it will check if any changes were applied to the input, and submit the form if both conditions are met.
If you specify the required attribute on the input, then the form will not be submitted unless a value is filled in. But that only covers values that were not supplied and you may want to check for invalid values as well.
The usual way is to disable the submit button unless the form is valid. Like this:
<button type="submit" [disabled]="!f.form.valid">Submit</button>
The Angular documentation about form validation also shows this. Look near the bottom of the "Simple template driven forms" section
In function which you call on submit you can pass form as parameter and then check. In html you will need to pass form instance:
<form name="equipmentForm" #f="ngForm" (ngSubmit)="addEquipment(f)" validate>
In typescript:
addEquipment(form){
if(form.invalid){
return;
}
//If it is valid it will continue to here...
}

How can i put HTML5 required field using form_input() function in Codeigniter framework

I am new in codeigniter.But now i am developing a project using codeigniter.
My Html code like this:
<input type="text" class="get_started_frm_reg" name="first_name" required />
Now i want to convert it through function form_input() function.I wrote my code like that
$first_name=array(
"name"=>"first_name",
"class"=>"get_started_frm_reg",
"type"=>"text"
);
But i don't understand how can i put required field.Please help me.
$first_name=array("name"=>"first_name",
"class"=>"get_started_frm_reg",
"type"=>"text",
"required"=>"required");
This is working
I would recommend the following:
form_input('first_name', $value, 'class="get_started_frm_reg" required');
// if you don't want to pass a variable for value, pass 'null'
form_input('first_name', null, 'class="get_started_frm_reg" required');
The above will output exactly how you were asking in your question.
I like using this method better then passing an array to form_input because you have better control over boolean input values, like required. Also, you don't need to pass text="type" since it is the default on form_input.
The best is to use it like this:
<?=form_input(['name'=>'first_name', 'class'=>'get_started_frm_reg'],'','required');?>
Produces:
<input type="text" class="get_started_frm_reg" name="first_name" required />

How to serialize a form with dynamically added inputs using jQuery?

I've read through a lot of questions addressing similar question but I can't get a grip on it, yet.
I have a simple HTML form just like
<form id="edit-items" name="edit-items" onsubmit="saveItems();">
<input type="submit" value="Save">
<input class="item" id="ei81" type="hidden" name="i[81]" value="1">
<input class="item" id="ei124" type="hidden" name="i[124]" value="1">
</form>
The two existing hidden inputs could be set upon document loading due to a prior save.
Now I have images (kind of a menu). If they are clicked a corresponding hidden input is appended to the form:
<img id="i37" class="clickable-item" src="items/i37.gif" title="item name" onclick="addItem(37,1)" />
The addItem function:
function addItem(id,n) {
var zitem = $("#e"+id);
if ( 0 in zitem ) {
if ( zitem.val() > 0 ) {
var newcnt = parseInt(zitem.val()) + n;
if ( newcnt <= 0 ) {
zitem.remove();
}
else {
zitem.val(newcnt);
}
}
}
else if(n == 1) {
var iform = $("#edit-items");
iform.append("<input class=\"item\" id=\"e"+id+"\" type=\"hidden\" name=\"i["+id+"]\" value=\"1\">");
}
}
This part all works correct, after clicking the image, my form looks like
<form id="edit-items" name="edit-items" onsubmit="saveItems();">
<input type="submit" value="Save">
<input class="item" id="ei81" type="hidden" name="i[81]" value="1">
<input class="item" id="ei124" type="hidden" name="i[124]" value="1">
<input class="item" id="ei37" type="hidden" name="i[37]" value="1">
</form>
which is exactly what I want. But then when hitting the submit button only the first two elements are submitted (the ones which have not been added dynamically).
Now, I read a lot about .bind and .live handlers but I am missing some point obviously. I tried to delete the onclick attribute on the images and to bind the .live to them since they are causing the new inputs:
$(".clickable-item").live("click", function() {
addItem($(this).attr("id"),1);
});
However, the ID is not transferred which is needed, though (hence no correct input is added). I learned that .live doesn't bind the handler to any elements but to the event.
Is it even possible to pass the element which has been clicked to the live handler?
Should the images even be watched by .live or should it be bound to something else?
The last thing I learned form another question here is that the inputs should be watched by .live, since they are dynamically added. But what kind of event I would attach? The inputs themselves are not clicked.
I would really appreciate any help as I am cracking my head and starting to get lost on that one.
Thanks in advance,
Paul
Regarding live() [docs]: this refers to the clicked element, so you can pass it to addItem with addItem(this, 1). This part of your code should work.
If you don't add or remove images dynamically then there is no reason to use live. You can just use click() [docs] (and yes, don't use onclick in the HTML).
But I see another problem:
The image id is i37. $(this).attr("id") will return this value.
In your addItem function you then take this value and perform string concatenation. The result will be $("#ii37") (note the two is).
The input element you create will have the id ii37 and not i37.
If you correct this to match it with the other elements like in your example (i.e. i37) , you will have problems because you have several elements with the same id (the input element and the image). If the image comes before the input field in the hierarchy, then $("#i37") will always select the image and you cannot call .val() on an image.
As I don't know what is the overall purpose of the code and what you want to do, I cannot give any suggestion how to improve this. Maybe it is enough to just change the prefix of the image and input field ids.
I learned that .live doesn't bind the handler to any elements but to the event.
That is not correct. .live() binds the event handler to the document root. Events, if not cancelled, bubble up the DOM tree, so they reach the root eventually. There, the event.target [docs] property is examined to determine the element that was clicked.

Resources