cy.get div that hasn't got a display: none on it - css-selectors

I'm working on some poor code, that someone else has written. I'm trying to write some tests for the functionality, before we're changing it, so we can ensure it all works, after the feature-changes.
I have 8 siblings divs like this:
<div class="container">
<!-- Child-1 -->
<div class="child-group child-1" style=""> <!-- Notice empty style-tag -->
<div class="buttons">
<button class="go-to-child-group-1">Child-group-1</button>
<button class="go-to-child-group-2">Child-group-2</button>
<button class="go-to-child-group-3">Child-group-3</button>
... <!-- Leaving out all the buttons for readability -->
<button class="go-to-child-group-8">Child-group-8</button>
</div>
<div class="content">Content1 content1 content1</div>
</div>
<!-- Child-2 -->
<div class="child-group child-2" style="display: none"> <!-- Notice display none -->
<div class="buttons">
<button class="go-to-child-group-1">Child-group-1</button>
<button class="go-to-child-group-2">Child-group-2</button>
<button class="go-to-child-group-3">Child-group-3</button>
... <!-- Leaving out all the buttons for readability -->
<button class="go-to-child-group-8">Child-group-8</button>
</div>
<div class="content">Content2 content2 content2</div>
</div>
<!-- Child-3 -->
<div class="child-group child-3" style="display: none"> <!-- Notice display none -->
<div class="buttons">
<button class="go-to-child-group-1">Child-group-1</button>
<button class="go-to-child-group-2">Child-group-2</button>
<button class="go-to-child-group-3">Child-group-3</button>
... <!-- Leaving out all the buttons for readability -->
<button class="go-to-child-group-8">Child-group-8</button>
</div>
<div class="content">Content3 content3 content3</div>
</div>
<!--
Etc. etc. etc.
for group Child-4, Child-5, Child-6, Child-7 and Child-8
-->
</div>
When you click one of the buttons, it sets display: none on the active group - and removes display: none from the child-group that needs to become visible.
I'm trying to write a test, that first activates a certain child-group (by clicking the the button to make it visible) and afterwards checks the content is correct.
But when I do this:
cy.get( ".child-group .buttons .go-to-child-group-2" ).click();
Then my test fails with this error:
cy.click() can only be called on a single element. Your subject contained 8 elements. Pass { multiple: true } if you want to serially click each element.
It's obviously crap, that all the buttons are loaded on each element. But we can't change that until further down the line.
How do I select only the .child-group that doesn't have display: none set on it?
Solution attempt 1: Select by style
I found this post on how to select by style. But since I'm trying to select the one without the style, that makes this more difficult.
I tried this:
cy.get( ".child-group[style*='display: block'] .buttons .go-to-child-group-2" ).click();
But that doesn't work. And when I inspect the element without the display: none, then I can find no display-style on it. And I could also read that display didn't have any default value.
Solution attempt 2: Make cy.get(...) disregard all non-visible elements.
I found a bit about Interacting with Elements, but it didn't tell me how I could pass that option the my cy.get-function.
I also checked the documentation for cy.get, but couldn't find anything either.
Solution attempt 3: Simply click all the buttons (poor)
I could do what it says and click all the buttons, by calling the click-function like this:
cy.get( ".child-group .buttons .go-to-child-group-2" ).click( {multiple: true, force: true});
This works, but I was hoping for a better solution.

I think you're looking for the :not() pseudo selector
cy.get('.child-group .buttons .go-to-child-group-2:not([style="display: none"])')
I guess it's also worth trying this, but not sure if the empty string will throw it
cy.get('.child-group .buttons .go-to-child-group-2[style=""]')

Alternatively, you can use the :visible selector.
cy.get('.child-group .buttons .go-to-child-group-2')
.filter(':visible') // filter only visible elements
Here is a simple example

Related

How to add space between create button and a success message that will show at the bottom after creating?

In my form, I have the following JSX written with React and after I create with the button, the success message will touch the button at the bottom, leaving no space. Is there anyway to add that space between? Thanks again.
<button className="btn btn-primary">Create a hat</button>
</div >
</form >
<div className={successClass} id="success-message">
You have created a new hat!
</div>
I tried googling methods to add properties into the button and message but nothing seems to split them apart.
Try adding padding-top to the success message div.
<button className="btn btn-primary">Create a hat</button>
</div>
</form>
<div className={successClass} id="success-message"
style={{paddingTop :"2rem"}}
>
You have created a new hat!
</div>
`
</form>
<div className={successClass} id="success-message">
The best way to position elements is by use of CSS, avoid things like {' '}
Second, make your page structure clear for example
<div class="form-wrapper" style="padding: 10px; margin-bottom:4px;">
<form>
<!-- put your create button here -->
</form>
</div>
<div class="success-msg-wrapper" style="padding: 10px;">
<!-- put your message div here -->
</div>
Finally, make use of class-based styling instead of inline css for better maintainability of the code.

Lightning-combobox getting cut off

I am building a lightning web component that uses a combobox. It seems to be having its dropdown portion cut short by the bounds of its container.
I've tried adding height, z-index, overflow, and margin modifiers to the style sheet for the input element and its container, and the only thing that's had a visible effect is adding margin to the combobox's container, which just makes more space for the dropdown to show its contents but doesn't solve the problem.
Here is an excerpt of the html file:
<div class="slds-col slds-grid">
<!-- Complete Task -->
<div class="slds-grid slds-col slds-size_2-of-4 slds-p-right_small slds-truncate">
<div class="slds-col">
<div class="slds-border_bottom" style="background-color: #ecd4b566">Log a Call</div>
<div class="slds-grid_vertical slds-p-top_small">
<div class="slds-col">
<lightning-combobox
class="spencer_combobox"
variant="label-hidden"
placeholder="-- Call Result --"
options={callResults}
value={selectedResult}
required
onchange={handleResultSelection}>
</lightning-combobox>
</div>
<div class="slds-col">
<lightning-textarea maxlength=255 placeholder="Write comments here" onchange={handleComment} value={commentValue}></lightning-textarea>
</div>
<div class="slds-col">
<lightning-button class="slds-col" variant="Brand" label="Complete Task" onclick={handleCompleteTaskClick} disabled={buttonDisabled}></lightning-button>
</div>
</div>
</div>
</div>
I expected the dropdown to be visible on top of the other elements, but it ends up hidden or cut off.
Here is a screenshot; the dropdown menu isn't being cut off by the next element below it, it's actually getting cut off by its own bounds.
Figured it out.
I put slds-truncate in the class of the container, and that comes with overflow:hidden, so I was able to just remove the truncate or edit the style sheet to fix the problem.

protractor expect not working for non-angular accordion widget

After clicking on the accordion element, the accordion panel opens, but the expect() in the following code passes even though the desired panel has been expanded (aria-expanded="true"). I am trying to verify the correct panel has been opened. I am new to protractor - any help will be appreciated.
var el = element(by.css('#brainstormingLink'));
el.click().then(function(){
browser.sleep(1000).then(function(){
expect(element(by.css('#BrainstormingAccordion[aria-expanded="false"])).isPresent());
});
});
The HTML is as follows:
<h3 id="brainstormingLink" class="menuSectionLink ui-accordion-header ui-helper-reset ui-state-default ui-accordion-header-active ui-state-active ui-corner-top" sectionnum="1" role="tab" aria-controls="BrainstormingAccordion" aria-selected="true" tabindex="0">Brainstorm</h3>
<div id="BrainstormingAccordion" class="accordion-inner scrollable ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content-active" aria-labelledby="brainstormingLink" role="tabpanel" aria-expanded="true" aria-hidden="false" style="display: block; height: 282px; overflow: auto;">
Follow these steps to brainstorm ideas:<br><br>
<ol>
<li>Use the add idea button <div class="toolbarButtonIcon inlineIcon"><div id="icon-plus"> </div></div> to enter one idea, fact, or opinion about your topic that you think might be useful.</li>
<li>Continue using the add idea button <div class="toolbarButtonIcon inlineIcon"><div id="icon-plus"> </div></div> to add as many ideas as you can.<br><br>
<div class="buttoncenter"><button class="btn btn-custom" type="button" name="brainstorming" title="brainstorming"> about brainstorming</button></div>
</li>
</ol>
</div>
Your test always passes because you didn't complete the assertion in the expect statement. .isPresent() returns a boolean so you need to finish it with whatever you are expecting the result to be i.e .toBe(false) or .toBeTruthy() etc.
Just note that isPresent is really asking if that element is present in the page, if you want to know if it's currently visible to a user then use .isDisplayed(). Also, since that element has an ID, I think you're better off locating it that way like you did with the first element, the HTML attribute isn't necessary unless you had trouble locating it. I always use ID when it's available because they're unique.
List of available assertions here: http://jasmine.github.io/2.0/introduction.html

How to disable content based on checkbox in AngularJS/Bootstrap3

I am creating a form where the user can configure a recurring event, so there are a large number of controls. At the top is a checkbox to enable/disable the schedule.
How can I disable, but not hide, the entire section based on the checkbox? If it is checked, the user should be able to make modifications to the schedule. If it is not checked, no changes should be allowed.
I'm fairly certain I can use the ng-disabled directive on each control, but I'd like to set some attribute/class on the entire container, rather than on each individual control.
I am using Bootstrap 3, so if there is a class that would provide this functionality, that would be an acceptable solution as well.
Here is the relevant section of the HTML:
<input type="checkbox" ng-model="status" title="Enable/Disable Schedule" /> <b>Schedule the task to run:</b>
<div class="row"> <!-- need a way to disable this row based on the checkbox -->
<span>Every <input type="number" ng-model="interval" />
<select ng-model="frequency"
ng-options="freq as freq.name for freq in frequencies"></select>
</span>
<div>
On these days:
</div>
<div class="btn-group" data-toggle="buttons-checkbox">
<button type="button"
class="btn"
ng-model="day.value"
ng-repeat="day in days">{{day.name}}</button>
</div>
</div>
I have tried:
<div class="row" ng-disabled="!status">
It didn't work, and based on the docs, it doesn't look like it is even supposed to, as its intended use is for disabling form controls. I also tried without the !, just to validate that it wouldn't work either.
OK, I found a technique that works for my purposes...
<div class="row" ng-class="{disabled: !status}"> <!-- added ng-class here -->
and
.disabled {
z-index: 1000;
background-color: lightgrey;
opacity: 0.6;
pointer-events: none;
}
This prevents clicks on the page and gives a nice visual indication of the section being "disabled".
It does not prevent me from tabbing through the controls, but it works OK for my purposes.

Using a Conditional Statement in AngularUI's Collapse Directive

Can I place a conditional statement into the collapse directive for AngularUI?
I have the following setup, which has 3 radio-style buttons:
<div class="controls controls-row">
<div class="btn-group" data-toggle="buttons-radio">
<button type="button" class="btn" ng-model="radioPurpose" btn-radio="'meeting'">Meeting</button>
<button type="button" class="btn" ng-model="radioPurpose" btn-radio="'tour'">Tour</button>
<button type="button" class="btn" ng-model="radioPurpose" btn-radio="'other'">Other...</button>
</div>
</div>
<div class="controls controls-row">
<textarea class="span6" placeholder="Why are you here?" ng-model="textPurpose" collapse="{{ radioPurpose == 'other' }}"></textarea>
</div>
I would like textarea to show/hide according to the value of the radioPurpose buttons. I know the statement is evaluating to true at the appropriate time, but the directive always shows the textarea.
Copied answer from comment:
I haven't used AngularUI, but I'm guessing collapse expects an expression. Remove the curly braces: collapse="radioPurpose == 'other'"
Collapse is actually not the best way of doing a simple show/hide. A collapsed item has its height set to 0, rather than being set to display: none; it might not always have the effect you're expecting. I would suggest instead using ng-show or ng-hide.
http://docs.angularjs.org/api/ng.directive:ngShow
I saw that you solved it, and so did I and can share my JSFiddle; Toggle Collapse with Radiobuttons.
However, I see what S McCrohan mean, since I got a problem in my app. The collapse for the table did not work fully in my app first, since it collapsed but left the top row visible. It seems to require that you separate the divs, i.e. a div with collapse and a div with span# class, like following...:
<!-- START CHART AREA -->
<div collapse="chartCollapsed">
<div class="span12 well well-small">
<div id="chart_div" style="width: 600px; height: 400px;"></div>
</div>
</div>
<!-- END CHART AREA -->
<!-- START TABLE AREA -->
<div collapse="tableCollapsed">
<div class="span12">
<!-- TABLE OMITTED -->
</div>
</div>
<!-- END TABLE AREA -->

Resources