In Cypress, I'm trying to count how many elements (in this case how many buttons in li) contain text. When using "contains", the number of returned items is always equal to one because "contains" only gives the first item in the document containing the search text.
cy.get('li')
.contains('button', 'Submit')
.its('length')
.then(elLength => {
// I want to test here the number of all buttons in li elements containig word 'Submit'
}
Of course, this doesn't work that way, because elLength is always 1 (or 0 if no items found).
Is there any other method in Cypress that can return all elements with text, and I can count them?
Cypress get() uses the same selectors as jQuery. You can therefor use :contains to get all elements containing a text.
As Cypress contains() only includes visible DOM elements, you have to add :visible to get the same kind of behaviour.
To make sure only one visible button contains "Submit":
cy.get('button:visible:contains("Submit")').should('have.length', 1);
To make sure only one visible button inside a "li" element contains the text "Submit":
cy.get('li button:visible:contains("Submit")').should('have.length', 1);
To count the "li" elements that contain one or more visible "Submit" buttons:
cy.get('li:has(button:visible:contains("Submit"))').should('have.length', 1);
If you know the right amount of buttons that need to have that label, you could try:
cy.get('li').then($el => {
cy.wrap($el).find(".button").then($els => {
expect($els.filter(index => $els.eq(index).is(':contains(Submit)'))).to.have.length(your_amount);
})
Related
i want to do visual testing with cypress-image-diff. So far, so good. I can take and compare screenshots of the complete page, but never of the element itself, as they are in an iFrame. With help of cypress-iframe I can check e.g. name, stype etc of the element. But screenshots are always taken from another area. Pls help
verifyLogoShown() {
cy.log("Verify if diconium logo is visible");
cy.frameLoaded(this.IFRAME)
// after the frame has loaded, we can use "cy.iframe()"
// to retrieve it
cy.iframe().find(this.TEST_OBJECT).should('have.text', 'Styled Button - primary') // works. I can test all kinds of CSS or other values from the button TEST_OBJECT
cy.wait(1000);
cy.getIframeBody(this.IFRAME).find(this.TEST_OBJECT).should('have.text', "Styled Button - primary")
cy.getIframeBody(this.IFRAME).type("a")
cy.compareSnapshot('button (replaceable)');
//doesn't take screenshot of that part I expect (e.g. iFrame box or button itself, instead of the menu part on the left)
}
My commands.js
Cypress.Commands.add('getIframeDocument', (iFrameSelector) => {
return cy
.get(iFrameSelector)
.its('0.contentDocument');
})
Cypress.Commands.add('getIframeBodyOtherWay', (iFrameSelector) => {
return cy
.getIframeDocument(iFrameSelector).should('exist').its('body').should('not.be.undefined')
.then(cy.wrap);
})
Cypress.Commands.add("getIframeBody", (framename) => {
// get the iframe > document > body
// and retry until the body element is not empty
return cy
.get(framename)
.its('0.contentDocument.body').should('not.be.empty')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
// https://on.cypress.io/wrap
.then(cy.wrap);
});
I can query for elements for example that have a title property like;
$$('*[title]')
Lets say I want to find all elements with border / or border-radius applied, I tried some queries but they did not work.
$$('*[border-width]')
// returns nothing
$$('*[border-width="1px"]')
// returns nothings
this are applied on class level but I tried a few with inline styling, still does not work.
So how can you find elements with lets say, some specific border, padding, etc applied?
Working Demo: https://dojo.telerik.com/IlOVEsAS/7
function getElementByCSSProps(props){
var elements = $("*").filter(function(e){
var borderWidth = parseInt($(this).css(props));
return borderWidth > 0;
});
return elements;
}
The above function will return elements based on the passed parameter.
For e.g
getElementByCSSProps("border-width"); - This line will return all elements with border.
getElementByCSSProps("border-radius"); - This line will return all elements with border-radius.
I want to style a grid row after clicking on it. I get the grid row / item in the itemClickListener, but I need to avoid using grid.select(item). I have achieved the desired output which would highlight the row I clicked on with the grid select method, but this causes problems for my app since I do not want that row to be selected, but I want it to be just highlighted, e.g. apply a CSS style to said row. This is my code so far:
grid.addItemClickListener(e -> {
grid.deselectAll();
grid.select(e.getItem());
});
as well as:
grid.setStyleGenerator(row -> grid.getSelectedItems().contains(row)
? getRowSelectedStyle(row)
: null);
I cannot seem to find anything on the forums which could apply a style name for the clicked row.
You probably need to add a property to your item Bean, se "clicked".
Then you could do
grid.addItemClickListener(e -> {
e.getItem().setClicked(true);
grid.getDataProvider().refreshItem(e.getItem());
});
And
grid.setStyleGenerator(row -> row.isClicked()
? getRowSelectedStyle(row)
: null);
I am conceiving a horizontal bar containing items.
They must all be of same width, having the same spacing between them.
They can expand as much as they want vertically (
stackblitz here
Problem:
How to automatically set the width of the row elements? Here I simply put a value that looks good: width:200px.
I want them to have a width dependent on the number of element per row.
What I tried:
Using elementRef in Horizontile (component holding the individual tiles, displaying with *ngFor) to get the width of this element:
currentWidth:number;
constructor(private el:ElementRef) {}
ngAfterViewInit(): void {
this.currentWidth=this.el.nativeElement.offsetWidth;}
it returns 5. (??) Using .width returns nothing. Also this is not recommended, I'd like another solution, less coupling.
I noticed I can make use of width:inherit; in the css of the individual tile component, which allows me to set the style from the horizontal list component.
<app-tile [style.width.px]="0.9*currentWidth/nDisplayedTiles" [tile]="item"></app-tile>
As the currentWidth value is zero, of course it doesn't work;
I tried setting it in % but the inherits css tag keeps the %, which is not the intended effect.
Why is the app-tile styling not cared about if inherits is not set?
I tried using ViewEncapsulation but it had no effect either.
This looks like a trivial matter though: did I just miss something?
You can use the offsetParent (link) width and create a method to return the value on each of the cells and call it in your [style.width.px], something like the following will work.
The HTMLElement.offsetParent read-only property returns a reference to the element which is the closest (nearest in the containment hierarchy) positioned ancestor element.
stackblitz
ngAfterViewInit(): void {
//added this as the compiler was throwing ExpressionChangedAfterItHasBeenCheckedError
setTimeout(() => {
this.currentWidth=this.el.nativeElement.offsetParent.clientWidth;
});
}
getWidth(): number{
let width:number = 0;
//you may need to change this value to better display the cells
let multiplier = 0.7;
width = (this.currentWidth * multiplier) / this.ndisplayTiles;
width = Math.round(width);
return width;
}
<app-tile [class]="'layout-tile'" [tile]="item" [style.width.px]="getWidth()">
</app-tile>
I am trying to get my text to wrap around and display in multiple lines in Office UI Fabric's DetailsRow. At the moment some of my rows that have long text go off the screen, and I would like them to wrap around so the user does not have to scroll to read the entire row.
This is my GroupedList
<GroupedList
items={this._items}
onRenderCell={this._onRenderCell}
groups={this._groups}
selectionMode={SelectionMode.none}
compact={true}
/>
This is my render method for each cell.
_onRenderCell = (nestingDepth, item, itemIndex) => {
return (
<DetailsRow
columns={this._columns}
groupNestingDepth={nestingDepth}
item={item}
itemIndex={itemIndex}
selection={this._selection}
selectionMode={SelectionMode.none}
onClick={() => this.insertComment(item.key, item.link)}
/>
);
};
Any ideas on how to make the text wrap? I am a beginner when it comes to styling.
If you have specific columns whose text are known to require more than "1 line" of text, you can use the isMultiLine property on the column. This is the example that sets isMultiLine to true for a column to wrap the text, which in turn enlarges the height of the corresponding row: "DetailsList - Variable Row Heights".