I'm trying to perform a Cucumber test that can click on the ng-select component (dropdown menu) and, after that, clicks on one of the options of the menu.
I've tried to use "element (by.partialLinkText('Solid Community')).click()", where "Solid Community" is the text that must be clicked. I also tried with "by.LinkedText" but it didn't work.
I can not use "by.id" or similar because the options of the menu don't have an id (the whole dropdown menu has one).
Here are some relevant parts of the code:
login.component.html:
...
<div style="margin-top: 10px;">
<ng-select class="login-select"
id="login-select-menu"
bindLabel="name"
bindValue="loginUrl"
placeholder="Select ID Provider"
dropdownPosition="bottom"
[items]="identityProviders"
[(ngModel)]="selectedProviderUrl"
style="width: 360px; height: 48px; margin-left: auto; margin-right: auto;">
<!-- DROPDOWN TEMPLATE -->
<ng-template ng-option-tmp let-item="item">
<div style="height:40px; padding-top:10px; position: relative;">
<img [src]="item.image" style="float: left; height: 32px; width: 32px; margin-top:-5px;" />
<span style="float: left; margin-left: 10px;">{{ item.name }}</span>
<div style="clear: both;"></div>
</div>
</ng-template>
</ng-select>
<input type="text"
class="wide-text"
*ngIf="selectedProviderUrl===null"
placeholder="Enter WebID"
style="margin-top:10px; padding: 12px 10px; width: 340px; height: 16px; display: block; margin-left: auto; margin-right: auto;"
[(ngModel)]="customProviderUrl" />
<button class="wide-button" (click)="onLogin()" *ngIf="selectedProviderUrl !== undefined || customProviderUrl !== undefined" [disabled]="selectedProviderUrl===null && !customProviderUrl" style="margin-top:10px;">Go</button>
</div>
...
loginSelectMenu.feature:
#loginSelectMenu-feature
Feature: Click on login select menu
Display anything
#loginSelectMenu-scenario
Scenario: Login Page
Given I am on the login page
When I click on the login select menu
Then It should happen anything
app.steps.ts (the error is in "When"):
When(/^I click on the login select menu$/, async () => {
await page.clickOnLoginSelectMenu();
await page.clickOnSolidCommunity();
});
app.po.ts:
clickOnLoginSelectMenu() {
return element(by.id('login-select-menu')).click();
}
clickOnSolidCommunity() {
this.sleep(3000);
return element(by.partialLinkText('Solid Community')).click();
}
When identifying elements it's important to look at the rendered HTML in the DOM instead of the angular HTML template. There are a number of transformations that occur when the templates are rendered.
Also partialLinkText will search for <a> tags which contain the provided string. It does not appear you are using any a tags within your code.
If your element is of another type you should be able to use the cssContainingText locator like so
element(by.cssContainingText('div','Solid Community')).click();
Related
I've had a look at related answers but none are what I am looking for... I think. Apologies if I am duplicating a question.
This HTML is used many times on a page, within a product box and is displayed on a product category page.
<div class"all-buttons-container">
<div class="button1-container">
<a class="button1">text</a>
</div>
<div class="button2-container">
<a class="button2 **hidden**">text</a>
</div>
</div>
In this (much simplified) HTML I have a container which houses 2 siblings.
- Each sibling contains an anchor.
The button containers are always visible.
Sometimes, the .button2 anchor also has the bootstrap class of hidden so the anchor is no longer displayed. This is done in each of the product boxes depending on the need to have the second button for that product. I am not in control of this.
When the .button2 anchor has the hidden class I need to add some margin-top to button1-container to vertically center it
I was going to use pure style (flexbox) but it wasn't achieving what I needed.
I would like to run a little jQuery or pure JS every time the page finishes loading which adds some the top margin, if required, on each instance of this HTML. I don't like having to do this but will need to if I cannot find another simple way of controlling it.
Any thoughts... solutions... perfect solutions etc?
Thanks in advance!
cheers
wayjo
I suppose I've fully understood your question.
You can achieve this without JS, in a cleaner any.
Why not make a custom class of button2-hidden and attach it to all-buttons-container?
<div class"all-buttons-container button2-hidden">
<div class="button1-container">
<a class="button1">text</a>
</div>
<div class="button2-container">
<a class="button2">text</a>
</div>
</div>
Then you have this CSS:
.button2-hidden .button2-container{
display: none; // or visibility -- whatever you want
}
.button2-hidden .button1-container{
margin-top: 1rem;
}
If you can add a div to contain the buttons, than you can use the snippet below:
.all-buttons-container{
display: flex; /* important part */
align-items: center; /* important part */
padding: 10px;
background-color: grey;
width: 200px;
border: 2px solid #fff;
height: 150px;
}
.hidden {
display: none!important;
}
.all-buttons-container > div a{
display: inline-block;
background-color: blue;
padding: 7px;
margin: 7px;
color: #fff;
}
<div class="all-buttons-container">
<div class="very-important-div">
<div class="button1-container">
<a class="button1">button1</a>
</div>
<div class="button2-container">
<a class="button2">button2</a>
</div>
</div>
</div>
<div class="all-buttons-container">
<div class="very-important-div">
<div class="button1-container">
<a class="button1">button1</a>
</div>
<div class="button2-container">
<a class="button2 hidden">button2</a>
</div>
</div>
</div>
<div class="all-buttons-container">
<div class="very-important-div">
<div class="button1-container">
<a class="button1 hidden">button1</a>
</div>
<div class="button2-container">
<a class="button2">button2</a>
</div>
</div>
</div>
I am having a bit of trouble when loading dynamic divs on Angular. I have made a button which adds new divs on each click on a specific area. But the problem happens once I have added them, as they are shown incorrectly:
The editor and the calendar (Both are made by PrimeNG) are not shown after I add such div, as it shows on the picture above. But after I click twice on the text box (marked as red in the picture below), the components load up.
Here is the HTML code I am using to show that.
<div class="ui-g-9" style="border: 2px solid #c8c8c8; border-radius: 5px;">
<section class="card" style="display: flex; overflow-x: auto; overflow-y: unset;">
<div *ngFor="let disparaEmail of disparaEmails" class="ui-g-4" style="margin-right: 10px; border: 1px solid #c8c8c8; border-radius: 5px; min-width: 466.828px;">
<p class="titulo-campo font1 fw700">Assunto:</p>
<textarea pInputTextarea [rows]="2" [(ngModel)]="disparaEmail.assuntoEmail" style="width: 100%; resize:unset; font-size: 18px;"></textarea>
<p class="titulo-campo font1 fw700">Tipo de Aviso:</p>
<p-editor [style]="{'height':'300px'}" [(ngModel)]="disparaEmail.msgEmail"></p-editor>
<p class="titulo-campo font1 fw700">Data:</p>
<p-calendar [(ngModel)]="disparaEmail.dataEmail" dateFormat="dd/mm/yy" showButtonBar="true" [locale]="br" [monthNavigator]="true"
[yearNavigator]="true" yearRange="2018:2050"></p-calendar>
</div>
</section>
</div>
<div style="display: inline-grid;">
<i class="fa fa-plus botoes-chamada" (click)="addAviso()" style="color: #819049; padding:30px; margin-bottom: 10px;" pTooltip="Adicionar um tipo de aviso."></i>
<i class="fa fa-minus botoes-chamada" (click)="deletaAviso()" style="color: #905149; padding:10px;" pTooltip="Remover o Ășltimo tipo de aviso inserido."></i>
</div>
Here is the TS part:
addAviso(){
this.disparaEmails.push(new EmailDispara());
}
deletaAviso(){
if (this.disparaEmails.length > 1){
this.disparaEmails.splice(this.disparaEmails.length - 1, 1);
}
}
Thanks for the help in advance!
This is probably the common problem of not properly detecting changes. Add ChangeDetectorRef injection into your component:
constructor (..., changeDetector: ChangeDetectorRef)
and invoke detectChanges after adding/removing:
addAviso(){
this.disparaEmails.push(new EmailDispara());
this.changeDetector.detectChanges(); // <- this line here
}
I'm testing a reactjs app and the type() and pressKeys() commands are not working correctly. type('string') isn't entering text into the input field and pressKeys('string') is only entering 's'. I'm not sure if this is an issue with leadfoot and react in general, or the particular react app I'm testing. Here is some sample code from the page:
<div class="Select Select--multi is-searchable" data-reactid=".0.1.0.0.1.0.0.1:$languages">
<input type="hidden" data-reactid=".0.1.0.0.1.0.0.1:$languages.0" value="">
<div class="Select-control" data-reactid=".0.1.0.0.1.0.0.1:$languages.1">
<div class="Select-placeholder" data-reactid=".0.1.0.0.1.0.0.1:$languages.1.0:$placeholder">Languages</div>
<div class="Select-input " data-reactid=".0.1.0.0.1.0.0.1:$languages.1.1" style="display:inline-block;">
<input data-reactid=".0.1.0.0.1.0.0.1:$languages.1.1.0" style="width:5px;box-sizing:content-box;" tabindex="0" value="">
<div data-reactid=".0.1.0.0.1.0.0.1:$languages.1.1.1" style="position: absolute; visibility: hidden; height: 0px; width: 0px; overflow: scroll; white-space: nowrap; font-size: 14.4px; font-family: "Proxima Nova","Helvetica Neue",Helvetica,Arial,sans-serif; font-weight: 400; font-style: normal; letter-spacing: normal;"></div>
</div>
<span class="Select-arrow-zone" data-reactid=".0.1.0.0.1.0.0.1:$languages.1.4">
</div>
</div>
I can't select the first input element since it's hidden and I've tried selecting all of the available divs and the second input element. I currently have to do the following to enter text:
.pressKeys('t')
.pressKeys('e')
.pressKeys('x')
.pressKeys('t')
Any suggestions? I'm currently using a function that converts the data string to a char array and then enters each char one at a time.
This is on my plugin page on Git and I have two interactive demo in the web page. In one of the demo page, I have a small dialog that opens when you click on a div.
The weird issue is that this dialog is getting opened when I click on the top title that says attrchange beta . This happens only if the first click is on the title attrchange beta, clicking any other element in page fixes this issue.
The plugin page http://meetselva.github.io/attrchange/ [Fixed, use the below URL to see the problem]
http://meetselva.github.io/attrchange/index_so_issue.html
Below is the code,
<!-- The title -->
<h1 id="project_title">attrchange <span class="beta" style="text-decoration: line-through;" title="Almost there...">beta</span></h1>
<!-- Main dialog that has link to the sub-dialog -->
<div id="attributeChanger">
<h4 class="title">Attribute Changer</h4>
<p>Listed below are the attributes of the div:</p>
<div class="attrList"></div>
<div class="addAttribute text-right">add new attribute</div>
</div>
<!-- Sub-dialog -->
<div id="addOrmodifyAttr" title="Add/Modify Attribute">
<h4 class="title">Add/Modify Attribute</h4>
<p><b>Attr Name</b> <input type="text" class="float-right attrName"></p>
<p><b>Attr Value</b> <input type="text" class="float-right attrValue"/></p>
<div class="clear"> </div>
<button type="button" class="float-right close">Close</button>
<button type="button" class="float-right update">Update</button>
<div class="clear"></div>
</div>
JS:
var $attributeChanger = $('#attributeChanger');
var $attrName = $('.attrName', '#addOrmodifyAttr'),
$attrValue = $('.attrValue', '#addOrmodifyAttr'),
$attrAMUpdate = $('.update', '#addOrmodifyAttr');
//Handler to open the sub-dialog
$attributeChanger.on('click', '.addAttribute', function () {
$attrName.val('').removeClass('nbnbg');
$attrValue.val('');
$('#addOrmodifyAttr, #overlay').show();
});
The problem is the CSS applied to your #attributeChanger div.
If you look at the CSS applied to it:
#attributeChanger {
background-color: #FEFFFF;
border: 1px solid #4169E1;
color: #574353;
font-size: 0.9em;
margin: 10px;
min-height: 50px;
min-width: 150px;
opacity: 0;
padding: 2px;
position: absolute;
top: -200px;
z-index: 1;
}
You'll notice that the position is absolute, and it's positioned over your logo. So what you're clicking is actually your #attributeChanger div.
To fix it, you can hide #attributeChanger using display: none;, then use $('#attributeChanger').show(); in jQuery when it comes into actual view.
The pop up is showing because this code is running:
}).on('click', '.addAttribute', function () {
$attrName.val('').removeClass('nbnbg');
$attrValue.val('');
$('#addOrmodifyAttr, #overlay').show();
This is because the DIV with the class addAttribute is over the title DIV.
You can either move the 'addAttribute' DIV, or remove the last line of that onclick function.
That is because you element is hover your title and detect the click on himself and open(i don't know why it open, i didnt examine your entire code). But when you click anywhere else, your code is changing his position so it is not over the title.
The easiest fix is to change you #attributeChanger CSS top to -100px (that's the value when you click on the document) OR add a display : none.
EDIT : Axel answer show what I mean by "element is hover your title".
I am trying to create a drop-down select menu with custom css (similar to the drop-down selection of language at http://translate.google.com/#).
I have current html code:
<ul id="Select">
<li>
<select id="myId"
onmouseover="mopen('options')"
onmouseout="mclosetime()">
<div id="options"
onmouseover="mcancelclosetime()"
onmouseout="mclosetime()">
<option value="1" selected="selected">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</div>
</select>
</li>
</ul>
and the Javascript:
function mopen(id)
{
// cancel close timer
mcancelclosetime();
// close old layer
if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';
// get new layer and show it
ddmenuitem = document.getElementById(id);
ddmenuitem.style.visibility = 'visible';
}
But document.getElementById returns null.
Though if I use the code with a div element that does not contain a select list the document.getElementById(id) returns proper div value.
How do I fix this? or is there a better way to create drop-down select menu like http://translate.google.com ?
You've got your div placed inside of the select tag. I'm not sure this is valid, try moving the div outside of the select tag. As far as a better way, the dropdown at the link you've provided isn't using a select tag at all. It is simply styled to look like a dropdown menu, and is using a hidden div with all of the links inside of it. I hope this helps! --> here's some free code to get you started. The CSS triangle trick comes at no extra charge ;)
<div id='fakeDropdown'>
<div class='triangle'> </div>
<div id='menu'>
<a href='#'> link </a>
<a href='#'> link </a>
<a href='#'> link </a>
<a href='#'> link </a>
</div>
</div>
CSS
#fakeDropdown{
background-color: #888;
height: 30px;
width: 150px;
cursor: pointer;
}
#menu{
display: none;
background-color: #888;
height: 200px;
width: 800px;
position: relative;
top: 30px;
}
.triangle{
font-size: 0px; line-height: 0%; width: 0px;
border-top: 20px solid #000;
border-left: 10px solid #888;
border-right: 10px solid #888;
float: right;
margin-top: 5px;
}
JAVASCRIPT(assuming you're using jQuery)
$(document).ready(function(){
$('#fakeDropdown').hover(function(){
$(this).find('#menu').show('fast');
});
$('#fakeDropdown').mouseleave(function(){
$(this).find('#menu').hide('fast');
});
});
JSfiddle example
If you want a dropdown like Google Translate's, just look through the source code! There is no <select> element. It's almost entirely CSS.
http://jsfiddle.net/mattball/BA4v3/1/
That's because you can't nest a div tag within a select tag.
Google's fancy drop down is not a select tag at all, it's a set of div elements with the appropriate Javascript to accomplish something similar to a classic select element.
You'll need to change up your markup a bit for this to work out.
Here's a bunch of links to jQuery plugins/tutorials for creating custom drop-down menus.
http://vandelaydesign.com/blog/web-development/jquery-drop-down-menus/
http://www.hv-designs.co.uk/tutorials/sliding_menu/sliding_menu.html
http://www.filamentgroup.com/lab/jquery_ipod_style_and_flyout_menus/
check the value of alert(id):
alert(id);
ddmenuitem = document.getElementById(id);