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
})
Related
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;
});
On my page I have multiple tables with this structure:
<div class="box"><h4>Service 1</h4></div>
<div class="container"><ag-grid-table>items in the table</ag-grid-table><div>
<div class="box"><h4>Service 2</h4>
<div class="container"><ag-grid-table>items in the table</ag-grid-table><div>
</div>
<div class="scope-header"><h5>Service 3</h5></div>
<div class="scope-grid"><ag-grid-table>items in the table</ag-grid-table><div>
As you can see, all sections have different structure, and there are even more on the page.
What I want to achieve is to assert that the Service 3 table contains the correct item.
I was thinking about using cy.get('div.scope-header').contains('Service 3') and then using next() or sibling() but the ag-grid-table is neither directly next or sibling.
The only idea I have is to check ag-grid-table:nth(n), this should work, but is there a solution that selects the table according the header title text?
I mean select the table e.g. belonging to Service 3 only.
If you want to continue from cy.get('div.scope-header')
cy.contains('div.scope-header', 'Service 3') // this returns div.scope-header
// not <h5>Service 3</h5> which
// cy.get().contains() would do
.next() // next() moves you to <div class="scope-grid">
.find('ag-grid-table') // table is within that
You can do something like this with .sibling()
cy.contains('div.scope-header', 'Service 3')
.sibling('div.scope-grid') // move to specified sibling
.find('ag-grid-table') // within that element
.should(...)
From what I understood from your question, You can do something like this:
cy.contains('div.scope-header', 'Service 3')
.next() //goes to .scope-grid
.within(() => {
// scopes search within .scope-grid
cy.contains('ag-grid-table', 'some text').should('be.visible')
//OR
cy.get('ag-grid-table').find('item selector').should('be.visible')
//OR
cy.get('ag-grid-table')
.find('item selector')
.should('have.text', 'some text')
})
Something like this, you can do use Traversal commands.
Adding selectors to next() and sibling() is more robust when page layout changes.
cy.contains('h5', 'Service 3')
.parent('div.scope-header')
.next('div.scope-grid')
.children('ag-grid-table')
.find('div.ag-row').eq(2)
...
I have a datatable that fetches orders and is working and displaying properly. I show the orders to the users that initiated them. Then they can only search on their owns orders. Now I need to display a message to a user, if an order was found but it was initiated by another user, instead of displaying an empty result in the datatable. This will happen after typing in the search box and not when loading the datatable in the beggining. The problem is that the query already filters the results by user id so I cannot change it during manual search.
I can display code if needed but the function is quite big and I don't really need code but the logic/way of doing that.
Do you have any suggestions on how I could accomplish this?
Well, maybe not the best way to do it but that's how I solved it:
In the controller, I check for the search field, and run a query on the relationship but only on the orders that have different seller than the logged in user:
$otherSeller = "";
if(!empty($request->search['value']))
{
$ordersOtherSeller = Order::where('status_id', "!=", 3)->where('seller_id', '!=', $loggedUser->id)->whereHas('user', function ($q) use ($request){
$q->searchFullName($request->search['value']);
})->first();
if($ordersOtherSeller != NULL && $ordersOtherSeller->count() > 0)
$otherSeller = $ordersOtherSeller->user->full_name . ' ' . $ordersOtherSeller->seller->full_name;
}
And I set a custom variable with the table's json:
...
->with('otherSeller', $otherSeller)
->make(true);
Then on the datatable jquery drawCallBack, I check for a populated string that guarantees that the result is not returned by a query from the current user:
fnDrawCallback: function( oSettings ) {
var api = this.api();
if(api.ajax.json().otherSeller != "")
{
$('#alert-info span').text(api.ajax.json().otherSeller);
$('#alert-info').show();
}
else
$('#alert-info').hide();
},
And last is the toggling of the materialert element with updated text:
<div id="alert-info" class="materialert info" style="display: none;">
<i class="material-icons">info</i> <span></span>
<button type="button" class="close-alert">×</button>
</div>
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
A null value is returned, when a multiple select box is empty - this causes an error while using the sync command for a pivot table. How do I make the select box return a blank array '' instead of null?
{!! Form::select('tag_list[]', $tags, '', array('class' => 'select2 form-control', 'multiple')) !!}
The only way I have been able to solve the problem is by checking for null before syncing i.e.
private function syncTags(Company $company, $tags)
{
if (is_null($tags)) {
$tags = [];
}
$company->tags()->sync($tags);
}
If nothing is selected then Laravel indeed returns null. Manual null check is one way to resovle the case, much like you have already done.
Another option is to choose "something" by default if user has not selected it but this is a ugly hack. I have done it with hidden input which has same name. One will override other and if nothing is selected then hidden input value will be used instead.
So far this is the best solution (still a little ugly!)
$tags = $request->input('tag_list', []);
$company->tags()->sync($tags);