我正在编写一个Typescript/Productor测试,它需要评估和选择网格上的复选框元素。这些复选框缺少ID。因为我可以获得与这些复选框位于同一行的输入元素的句柄,所以我尝试通过元素查找器(by.id、by.xpath和by.css)的组合来获取它们。但我的尝试失败了。
我想写的是一个小函数,它将根据行上的html" target="_blank">远程“兄弟”元素和行上的复选框索引,从行中返回目标复选框元素。我已经尝试了几件事,我认为最有希望的尝试在这里发布。
这是我针对的网格中的一部分标记。为了清楚起见,省略了几列信息。这是我正在努力解决的问题。我无权更改标记,我只是被要求编写量角器测试。
<div ng-repeat="(rowRenderIndex, row) in rowContainer.renderedRows track by $index" class="ui-grid-row ng-scope" ng-style="Viewport.rowStyle(rowRenderIndex)">
<div ui-grid-row="row" row-render-index="rowRenderIndex" class="ng-isolate-scope">
<div ng-repeat="(colRenderIndex, col) in colContainer.renderedColumns track by col.uid" class="ui-grid-cell ng-scope ui-grid-coluiGrid-09T" ng-class="{ 'ui-grid-row-header-cell': col.isRowHeader }" ui-grid-cell="">
<div ng-click="grid.appScope.rowColumnSelect(row, 'rating')" ng-class="{'px-grid-row-selected': grid.appScope.highlightCell(row, 'rating'), 'px-can-edit': grid.appScope.clickableCell(row.entity, 'rating'), 'px-grid-total-row': row.entity.isTotal, 'px-grid-notable-row': row.entity.isNotable}" class="ng-scope">
<div class="ui-grid-cell-contents ng-hide" ng-hide="grid.appScope.showCell(row, 'rating')">
</div>
<div ng-show="grid.appScope.showCell(row, 'rating')" name="loanLossAssumption3" class="ui-grid-cell-contents">
<div ng-if="grid.appScope.haveData(row)" class="text-right ng-scope">
<div error-display-strategy="grid" px-input-field="" id="loanLossAssumptionrating3" name="loanLossAssumptionrating3" ng-if="grid.appScope.inEditMode(row, 'rating')" input-type="number" px-input-required="true" px-round-value="0" ng-model="row.entity.rating" class="ng-pristine ng-untouched ng-valid ng-scope ng-isolate-scope">
<div ng-class="{'row': !vm.isGridErrorDisplay && !vm.autoWidth}">
<div>
<div tooltip="" tooltip-placement="bottom" tooltip-append-to-body="true" tooltip-trigger="open" class="ng-scope">
<div px-validation="loanLossAssumptionrating3InputField" ng-class="{'col-xs-12': !vm.isGridErrorDisplay && !vm.autoWidth}" min="" max="" input-type="number" maxlength="" minlength="" error-display-strategy="grid" px-tooltip="" class="ng-isolate-scope">
<div class="row">
<div ng-class="vm.inputFieldClass()" class="col-xs-12">
<div class="input-group px-input-group-overrides px-no-grid-padding" ng-hide="vm.pxInputDisabled">
<span id="loanLossAssumptionrating3Prefix" name="loanLossAssumptionrating3Prefix" class="input-group-addon input-left-addon ng-binding ng-hide" ng-show="vm.prefix" ng-class="{'px-auto-width': vm.autoWidth}">
</span>
<div class="inner-addon">
<input id="loanLossAssumptionrating3InputField" name="loanLossAssumptionrating3InputField" class="form-control ng-pristine ng-untouched ng-valid ng-valid-px-email ng-valid-required ng-valid-unique" ng-class="{'px-input-with-tooltip': !!vm.pxTooltip, 'px-auto-width': vm.autoWidth}" ng-required="vm.pxInputRequired" px-round-value="0" px-edit-rate="false" type="text" ng-model="vm.ngModel" px-email-validator="" ng-disabled="vm.pxControlDisabled" placeholder="" ng-change="vm.onChange()" ng-focus="vm.showTooltip(true)" ng-blur="vm.showTooltip(false)" px-unique-field="" autocomplete="off" required="required">
</div>
<span class="fa fa-exclamation-circle inline-error form-control-feedback" ng-style="{left:vm.feedbackIconLeft()}" style="left: 0px;">
</span>
<span class="input-group-addon input-empty-addon" ng-hide="vm.postfix" ng-class="{'px-auto-width': vm.autoWidth}">
</span>
</div>
</div>
<span ng-transclude="" class="px-vertical-middle">
</span>
</div>
</div>
</div>
</div>
<div px-tooltip-view="" px-tooltip="vm.pxTooltip" ng-click="vm.applyAdjustment()" class="ng-isolate-scope">
</div>
</div>
</div>
<span ng-hide="grid.appScope.inEditMode(row, 'rating')" ng-class="{'px-font-highlighted': grid.appScope.showHighlighted(row, 'rating'), 'px-font-enabled': grid.appScope.showEnabled(row, 'rating'), 'px-font-disabled': grid.appScope.showDisabled(row, 'rating'), 'px-cannot-edit': !grid.appScope.clickableCell(row.entity, 'rating')}" class="ng-binding px-font-enabled px-cannot-edit ng-hide">3</span>
</div>
</div>
</div>
</div>
<div ng-repeat="(colRenderIndex, col) in colContainer.renderedColumns track by col.uid"
class="ui-grid-cell ng-scope ui-grid-coluiGrid-09Y" ng-class="{ 'ui-grid-row-header-cell': col.isRowHeader }" ui-grid-cell="">
<div ng-click="grid.appScope.rowColumnSelect(row, 'isDefault')"
ng-class="{'px-grid-row-selected': grid.appScope.highlightCell(row, 'isDefault'), 'px-can-edit': grid.appScope.clickableCell(row.entity, 'isDefault'), 'px-grid-total-row': row.entity.isTotal, 'px-grid-notable-row': row.entity.isNotable}"
class="ng-scope">
<div class="ui-grid-cell-contents ng-hide" ng-hide="grid.appScope.showCell(row, 'isDefault')">
</div>
<div ng-show="grid.appScope.showCell(row, 'isDefault')" name="loanLossAssumptionfalse" class="ui-grid-cell-contents"> <!-- Changes to loanLossAssumptiontrue-->
<div ng-if="grid.appScope.haveData(row)" class="text-center ng-scope">
<input ng-disabled="!grid.appScope.inEditMode(row, 'isDefault')" type="checkbox" ng-input="row.entity.isDefault" ng-model="row.entity.isDefault"
class="ng-pristine ng-valid ng-touched">
</div>
</div>
</div>
</div>
</div>
</div>
在此方案中,我有一个输入字段的句柄,其 ID 为贷款丢失假设 3输入字段。从这里开始,我需要从这个ui网格行中获取其他复选框。在此示例中,一个复选框出现在标记末尾附近,位于 6 个结束 div 标记之前。
随着时间的推移,我们已经构建了一个函数库,因此在这段代码中引用了“lib”。那只是对我们库的工作引用。这段代码在pageObject中。
lib.getCheckboxInRow(fields.ratingFieldId, 0).then(function (checkboxElement) {
// The fields.ratingFieldId value = "loanLossAssumptionrating3InputField"
checkboxElement.click();
});
这只是一次“单击”尝试,但我还需要获取该元素并确定复选框是否被单击。在我的例子中,通过标记做到这一点的唯一方法是读取父元素中的属性。我知道怎么做,但是我提供这个细节来说明为什么我试图返回元素本身。
这是我的目标函数。下面显示了两种尝试。这两次都失败了。这是在我的图书馆里。
// Attempt A
public getCheckboxInRow(siblingElementId: string, checkboxIndex: number): webdriver.promise.Promise<protractor.ElementFinder> {
var xPathToRow : string = "./ancestor::div[contains(concat(' ', @class, ' '), ' ui-grid-row ')][1]";
return element(by.id(siblingElementId)).element(by.xpath(xPathToRow)).then(function (row) {
return row.all(by.css("input[@type='checkbox']")).filter.then(function (checkboxArray) {
return checkboxArray[checkboxIndex];
});
});
}
// Attempt B
public getCheckboxInRow(siblingElementId: string, checkboxIndex: number): webdriver.promise.Promise<protractor.ElementFinder> {
var xPathToRow : string = "./ancestor::div[contains(concat(' ', @class, ' '), ' ui-grid-row ')][1]";
var cssToCheckbox : string = "input[@type='checkbox']";
return element(by.id(siblingElementId)).element(by.xpath(xPathToRow)).all(by.css(cssToCheckbox)).filter(function(checkbox) {
return true;
}).then(function (checkboxArray) {
return checkboxArray[checkboxIndex];
});
}
使用“尝试A”会发生以下错误。
TypeError: element(...).元素(...)。则不是函数
“尝试B”的错误更加剧烈。
InvalidSelectorError:无效选择器:指定的选择器无效或非法(会话信息:chrome=47.0.2526.111)(驱动程序信息:chronidriver=2.19.346078(6f1f0cde889532d48ce8242342d0b84f94b114a1),平台=Windows NT 6.3 x86_64)(警告:服务器未提供任何堆栈跟踪信息)命令持续时间或超时:30毫秒有关此错误的文档,请访问:http://seleniumhq.org/exceptions/invalid_selector_exception.html内部版本信息:版本:“2.47.1”,修订版:“411b314”,时间:“2015-07-30 03:03:16”系统信息:主机:“PSIDEVKPALM”,ip:“10.226.128.27”,os。name:'Windows Server 2012 R2',操作系统。arch:'x86',操作系统。版本:'6.3',java。版本:“1.8.0_66”驱动程序信息:org.openqa.selenium.chrome。ChromeDriver功能[{applicationCacheEnabled=false,rotatable=false;mobileEmulationEnabled=false,chrome={userDataDir=C:\Users\kpalmer\AppData\Local\Temp\2\scoped_dir7352_8503},takesHeapSnapshot=true,databaseEnabled=false,handlesAlerts=true、hasTouchScreen=false、version=47.0.2526.111,platform=WIN8_1,browserConnectionEnabled=false,nativeEvents=true,acceptSslCerts=true,locationContextEnabled=2true,webStorageEnabled=3true,browerserName=chrome,takessScreenshot=true、javascriptEnabled=1true,cssSelectorsEnabled=true}]会话ID:12959162beeed374185734ef29b03b57***元素信息:{Using=css选择器,value=input[@type='checkbox']}
花了很多时间研究这个,我不知道为什么这些会失败。
最终,我想要的是一个函数,它将返回一个复选框元素,该元素与该行中的另一个元素位于同一行,基于复选框索引,以便我们可以单击该复选框或确定该元素是否选中。
谢谢你的帮助。
===2016年1月2日下午编辑===
谢谢你@alecxe,你帮了大忙。这是我运行的最终实现。这两种方法都有效。
这些都可以在我的pageObject中使用。
lib.getCheckboxInRow(fields.ratingFieldId, 0).click();
lib.getCheckboxArrayInRow(fields.ratingFieldId).filter(function (checkboxArray, index) {
return (index === 0);
}).first().click();
这些是库中的目标函数。我必须调整的一件事是返回类型,从promise到element finder。这些像冠军一样工作。
public getCheckboxInRow(siblingElementId: string, checkboxIndex: number): protractor.ElementFinder {
var xPathToRow : string = "./ancestor::div[contains(concat(' ', @class, ' '), ' ui-grid-row ')][1]";
return element(by.id(siblingElementId)).element(by.xpath(xPathToRow)).all(by.css("input[type=checkbox]")).filter(function (checkboxArray, index) {
return index === checkboxIndex;
}).first();
};
public getCheckboxArrayInRow(siblingElementId: string): protractor.ElementArrayFinder {
var xPathToRow : string = "./ancestor::div[contains(concat(' ', @class, ' '), ' ui-grid-row ')][1]";
return element(by.id(siblingElementId)).element(by.xpath(xPathToRow)).all(by.css("input[type=checkbox]"));
};
让我们回顾一下你的尝试。
尝试A
您将获得TypeError:element(…).element(……)。则不是函数
错误,因为您无法使用then()
Protractor 2.0.0(changelog)来解析ElementFinder。
在这种情况下,您可以继续链接
元素
和all()
:
public getCheckboxInRow(siblingElementId: string, checkboxIndex: number): webdriver.promise.Promise<protractor.ElementFinder> {
var xPathToRow : string = "./ancestor::div[contains(concat(' ', @class, ' '), ' ui-grid-row ')][1]";
return element(by.id(siblingElementId)).element(by.xpath(xPathToRow)).all(by.css("input[type=checkbox]")).filter(function (checkboxArray, index) {
return index === checkboxIndex;
}).first();
}
我还修复了应用
filter()
函数的方式。请注意first()
调用-这将帮助我们获得单个过滤元素,而不是数组。
尝试B
由于实际上您有一个无效的CSS选择器< code >输入[@type='checkbox']
,您将得到< code >指定了无效或非法的选择器错误-您不需要在CSS中的属性名称前加上< code > @ -用< code >输入[type=checkbox]来替换它(也不需要单引号)。
而且,在此尝试中,您也没有正确应用 filter()
函数。固定版本:
public getCheckboxInRow(siblingElementId: string, checkboxIndex: number): webdriver.promise.Promise<protractor.ElementFinder> {
var xPathToRow : string = "./ancestor::div[contains(concat(' ', @class, ' '), ' ui-grid-row ')][1]";
var cssToCheckbox : string = "input[type=checkbox]";
return element(by.id(siblingElementId)).element(by.xpath(xPathToRow)).all(by.css(cssToCheckbox)).filter(function(checkbox, index) {
return checkboxIndex === index;
}).first();
}
这基本上与尝试A相同。
我现在被困在这个问题上。我想如果复选框被选中,它应该返回一个值,但是当您将public更改为int时,您会得到一个错误。它似乎只对void有效,void不会返回任何东西。有办法做到这一点吗?
我有一个SPA,其中有多个具有相同类的div。我希望量角器选择可见的div并单击它。我一直得到,这让人相信它得到了一些不在这个特定页面上的元素(也许?)。我还得到,这再次让我认为它不是单击可见的,而是不可见的。 这是我的规格: 如何选择可见的 并单击它?
tbody和thead中的复选框使表呈现得很好。我可以在DataTable init外部编写简单的onChange函数,但它只检测表的可见页上选中或未选中的复选框。 如何或在哪里可以编写一个函数,当一个复选框被更改时会触发,然后返回表中被选中的复选框总数?
问题内容: 我有一组复选框,这些复选框在选中时将值传递为1,否则将值传递为0。但是,不是将未选中的复选框的值发送为“ 0”,而是发送的值为“ NULL”。 我在下面的JS代码中应将值相应地设置为0/1,但是仍然将该值作为NULL发送。有什么方法可以确保在未选中复选框的情况下传递的值为0? 更新 这是我的html: 默认情况下,它们都被选中。 如果未选中其中之一,则MySQL报告以下错误:0SQLS
我正在用量角器编写一些e2e测试。我的应用程序是Angular材料2应用程序。在我的测试中,我想按值选择md-select的一个选项。当我检查打开的md-select时,我看到了md-选项项。选项的值在一个属性ng-反映-值中。 假设我有一个值为“optionA”的选项。如何通过该值选择某个选项? 我试过这个: 在里面,我看到了选项的正确数目,但是我如何选择值为“of options”的选项呢?
问题内容: 我需要有关jQuery选择器的帮助。假设我有一个标记,如下所示: 除了用户单击时,如何获取所有复选框? 问题答案: 一个更完整的示例适用于您的情况: 当被点击复选框,该复选框的状态进行检查,并在当前形式的所有复选框被设置为相同的状态。 请注意,您无需从选择中排除该复选框,因为该复选框的状态将与其他所有复选框相同。如果出于某些原因确实需要排除,则可以使用以下方法: