Testing attribute text to match part of href link in Cypress - cypress

I'm testing all the links on a page but I only want a partial match.
I can test the full href like this
cy.visit('/');
cy.get('.class').find('a').should("have.attr", "href", "/123/456");
but I want to test the string partially, for example /456. I tried .contains() but it doesn't work.

You could use include,
cy.get('.class').find('a')
.should('have.attr', 'href')
.and('include', '/456');
or you can switch the subject
cy.get('.class').find('a')
.invoke('attr', 'href')
.should('contain', '/456');
or a longer version using jquery
cy.get('.class').find('a')
.should('have.attr', 'href')
.then(href => {
expect(href.endsWith('/456')).to.be.true;
});

Related

Cypress get the ID of some element

I am trying to obtain the ID of some element in Cypress. Because it's ID randomly changes (yes it is strange but it is angular).
E.g. I have a <button id="dropdown-1" class="someclass"><span>Click here</button>
As I can't rely on that ID, because after I do some actions on the page it becomes to dropdown-2 etc., I want to know, what is the current ID name.
I tried something like:
cy.get('button > span').contains('Click here').find("id");
but seems that is not the correct way.
I also tried:
cy.get('button > span').contains('Click here')
.invoke('attr', 'id')
this works not as well.
You can use a combination of text and a selector which has the non-changing part of your id value. Something like:
cy.contains('button[id*="dropdown-"]', 'Click here').invoke('attr', 'id')
Now you can use use the id value in two ways.
Directly after extraction:
cy.contains('button[id*="dropdown-"]', 'Click here')
.invoke('attr', 'id')
.then((id) => {
cy.log(id) //prints id
})
Save it in alias .as and use it later:
cy.contains('button[id*="dropdown-"]', 'Click here')
.invoke('attr', 'id')
.as('idValue')
cy.get('#idValue').then((idValue) => {
cy.log(idvalue) //prints id
})

Call view in Laravel Controller with anchor tag

I need to call a view in a Laravel Controller, with parameters and with Anchor Tag.
I have this code in my controller:
return view('plans/editPlanView',
['plan' => $plan,
'patient' => $patient,
'aliments'=>$aliments, 'menu'=>$menu, 'tabName'=>$tabName]);
But i need to add an Anchor tag to land in a specific section of the page.
I can't use
return Redirect::to(URL::previous() . "#whatever");
proposed in other posts because i need to pass some parameters.
I think there are some base problem, trying with console this:
$('html, body').animate({
scrollTop: $('#whatever').offset().top
}, 1000);
scrolling to the desired section does not work.
it seems the page makes a small snap but always returns to the top.
Update
I have found the cause of the problem. At the bottom of the blade page I have the following code, without it the anchor tag works fine. Adding it the page makes a small scroll to return to the head. I need to use the datepicker, how can I fix the problem and get the anchor tag to work?
#push('scripts')
<script type="text/javascript">
$(document).ready(function () {
$('.date').datepicker({
firstDayOfWeek: 1,
weekDayFormat: 'narrow',
inputFormat: 'd/M/y',
outputFormat: 'd/M/y',
markup: 'bootstrap4',
theme: 'bootstrap',
modal: false
});
});
</script>
#endpush
You can create the method showPage() in your contoller for example TestController
public function showPage(Request $request)
{
$plan = $request->plan;
...
return view('plans/editPlanView', [
'plan' => $plan,
'patient' => $patient,
'aliments'=>$aliments, 'menu'=>$menu, 'tabName'=>$tabName
]);
}
Then create a route for rendering that view
Route::get('/someurl', 'TestController#showPage')->name('show-page');
And then in your methods you can use something like that:
$url = URL::route('show-page', ['#whatever']);
return Redirect::to($url)
I found a workaround, I added the disable attribute to the date input, in doing so, when the datepicker is initialized, the page does not scroll up. Then, as a last javascript statement I re-enabled the fields:
$('.date').prop("disabled", false);

How to insert dynamic value on url cypress

Hi there I am new to cypress and learning,
My data is dynamic and changes every second. Imagine a table with Column city and city incharge. The city incharge is dynamic and changes every minute.
This is clickable and holds a link. This particular part changes more frequently and I want to check if the href holds correct value.
<a href="/City/incharge/Mr.A" data-toggle="tooltip" title="" data-original-title="Mr.A">
</a>
I tried to store the value in a variable but then not sure how to add it to the url to see if it is correct.
For example I tried code in cypress like this,
it('Check click function on Transactionhash', () => {
cy.get('td').eq(1).then(($incharge) => {
var name = $incharge.text(); // Storing the dynamic value to a variable
cy.get('td').eq(1).click()
cy.url().should('eq','https://worldmap.com/city/'name')
});
This 'name' part on the above url should have the dynamic value. In our case Mr.A which might change in future to anything.
Can somebody please help?
Thanks.
Looking at your sample it should be something like this:
it('Check click function on Transactionhash', () => {
let name = ''
cy.get('td').eq(1)
.then(incharge => {
name = incharge.text()
cy.get('td')
.eq(1)
.click()
cy.url()
.should('eq',`https://worldmap.com/city/${name}`)
})
})
Note the usage of backticks (`) in the should() function

Kendo Grid Multiple Hyperlinks in single column

I am using following code to display data from server in a Kendo Grid.
Working fine.
I want to put two hyperlinks in last cell of each row, but can do with only one.
I want EDIT and DELETE link in same cell.
How can I achieve this?
CODE
#(Html.Kendo().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(u => u.USERNAME);
columns.Bound(u => u.PASSWORD);
columns.Bound(u => u.ROLE);
columns.Bound(u => u.STATUS);
columns.Template(c => Html.ActionLink("Edit", "Edit", new { id = c.ID }));
}
)
.Pageable()
)
There are a couple of ways to do this.
First you could use the inbuilt edit/delete options from within the grid config
like so:
columns.Command(command =>
{
command.Edit();
command.Destroy();
});
Then just wire up the edit config and destroy delete commands appropriately.
Alternatively you can template these out using one of two methods:
First inline template:
columns.Bound(c => c.ID).ClientTemplate("<a href='Edit/#=data.ID#'>Edit Link #=data.ID#</a>
<a href='Delete/#=data.ID#'>Delete Link #=data.ID#</a>")
So this is just bound to a column and the template is added as per your requirements using standard html and javascript if required. This is fine for simple things but can get very clunky fast if you have more complex templates which then leads to the second method creating a template and calling that like this:
columns.Bound(c => c.ID).ClientTemplate("#=getButtonTemplate(data,'buttonsTemplate')#")
then create your template like so:
<script id="buttonsTemplate" type="text/x-kendo-template">
<div class='btn-group'>
<a class="btn btn-primary" href='#Url.Action("{edit action}", "controller")/#=ID#'>Edit Link #=ID#</a>
<a class="btn btn-danger" href='#Url.Action("{delete action}", "controller")/#=ID#'>Delete Link #=ID#</a>
<div>
</script>
then the getButtonTemplate function:
function getButtonTemplate(data, templateName) {
var templateObj = $("#" + templateName).html();
var template = kendo.template(templateObj);
return template(data);
}
So let me explain what is going on here with this second method.
Instead of templating the html in the column we extract it out into two components for want of a better word.
We use the getButtonTemplate function to pass 2 params in the data item and the template's id. This function simply loads the passed data object into the template and the kendo magic renders the html and injects the values in as required. Check the kendo demo site for more info on this subject.
The template element can be a mix of html and javascript so if you needed to apply some logic in the template this can be done in here. Again refer to the kendo site for more info on this subject.
I personally prefer the second method of doing this client templating as it is easier to manage and make changes without rogue hash's or brackets breaking code.
If you need any more info let me know and I will update the answer for you.

Drupal 7 ajax_command_* creates unwanted div

I'm populating a select box using an AJAX callback in Drupal 7. I've tried both ajax_command_append() and ajax_command_html() to set the new <option...> statements, but both these wrap the HTML that I create inside a <div>. This causes the <select> to not display any of the options.
Is there a way to tell Drupal "Hey stupid, this is exactly the HTML I want, don't mess with it"?
I can code some jQuery to remove the div I guess, but it would be a lot better if I can prevent it from being added in the first place.
Yes you can!
Declare your own custom js callback. In below example, I used a span instead of the divs. But you can obviously remove the wrapper alltogether.
PHP:
function my_ajax_callback() {
$data = 'saved!';
// instead of using ajax_command_html, we provide our own
// js custom callback function
$output = array(
'#type' => 'ajax',
'#commands' => array(
array('command' => 'myjscallback', 'data' => $data),
),
);
return $output;
}
JS:
$(function() {
Drupal.ajax.prototype.commands.myjscallback = function (ajax, response, status) {
$('#save-btn-message').html('<span>' + response.data + '</span>');
};
});
The answer is yes.
Just use this instead:
$commands[] = ajax_command_invoke('#mywrapper', 'html', array($output));
So it seems the answer is "no" (or at least not without hacking core, and I'll have no dead kittens on my conscience).
misc/ajax.js contains the following:
var new_content_wrapped = $('<div></div>').html(response.data);
The comments therein go on to explain why they require the first HTML element to be a top-level one. If it is, the <div> wrapper is not used. In my case, I'm replacing <option> elements, so I get the <div>.
Now I could just replace the entire <select>, but that causes other issues in my case due to scripts that style things at page load. Rather than find those and re-fire them, it looks like it'll be easier to just ajax_command_invoke a script to run after my options are loaded to remove the div wrapper.
EDIT: As a workaround, I found I can do ajax_command_invoke($selector, 'html', array('<option...>')); and it bypasses the div addition code. Kinda sneaky, but it works...
you can use seen on this link http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#ajax
for more reference and example download this module http://drupal.org/project/examples
it has all the examples of custom code and "ajax_example" as well
It works for me!
$selector = '#my-select';
$method = 'append';
$opts = array('new option');
$commands[] = ajax_command_invoke($selector, $method, $opts);
return array('#type' => 'ajax', '#commands' => $commands);

Resources