我运行此网站的网站是在内部服务器上,所以我无法提供链接,但我可以发布一些单击“show element”时显示的相关代码
有5个与此相关的元素:
此页面显示学生组,并允许用户在组之间拖动学生。每个组都有一个移动元素。棘手的部分是,任何给定组的移动按钮仅在用户将学生元素拖过该组时显示,而该学生不是来自该组。
目标是将学生转移到新的小组,然后再转回原来的小组。
注释: 学生XPath在更改组时会发生更改 我无法确认,但我相信移动按钮的XPath在隐藏时比在可见时不同
我的当前代码:
IWebDriver driver = (IWebDriver)FeatureContext.Current["Driver"];
Actions builder = new Actions(driver);
IWebElement originalstudent = driver.FindElement(By.XPath("//*[@id=\"AMTeacherApp\"]/div/div/div[1]/div/div[3]/div/div/div[2]/div[2]/div[2]/div/div[3]/a[1]/div[1]/div"));
IWebElement originalClass = driver.FindElement(By.XPath("//*[@id=\"AMTeacherApp\"]/div/div/div[1]/div/div[3]/div/div/div[2]/div[2]/div[2]/div/div[1]"));
IWebElement newClass = driver.FindElement(By.XPath("//*[@id=\"AMTeacherApp\"]/div/div/div[1]/div/div[3]/div/div/div[2]/div[2]/div[3]/div[1]/div[1]"));
IWebElement originalMove = driver.FindElement(By.XPath("//*[@id=\"AMTeacherApp\"]/div/div/div[1]/div/div[3]/div/div/div[2]/div[2]/div[2]/div/div[2]/div[1]/div"));
IWebElement newMove = driver.FindElement(By.XPath("//*[@id=\"AMTeacherApp\"]/div/div/div[1]/div/div[3]/div/div/div[2]/div[2]/div[3]/div[1]/div[2]/div[1]/div"));
builder.ClickAndHold(originalstudent);
builder.MoveToElement(newClass);
builder.Release(newMove);
builder.Build().Perform();
IWebElement save = driver.FindElement(By.XPath("//*[@id=\"AMTeacherApp\"]/div/div/div[1]/div/div[3]/div/div/div[1]/div/div/button[2]"));
builder.Click(save);
builder.Build().Perform();
//assert group2 has 1 student and group 1 has 3 students
IWebElement newstudent = driver.FindElement(By.XPath("//*[@id=\"AMTeacherApp\"]/div/div/div[1]/div/div[3]/div/div/div[2]/div[2]/div[3]/div/div[3]/a/div[1]/div"));
builder.ClickAndHold(newstudent);
builder.MoveToElement(originalClass);
builder.Release(originalMove);
builder.Click(save);
builder.Build().Perform();
此代码不会移动任何元素,并且在尝试查找保存时失败,因为没有任何更改(假设没有任何动作,这是预期的。)
页面中的相关代码:
<div class="column small-5 filter">
<div class="row groups-header">
<!-- ngIf: !model.configData.groupingMode.autoRegroup -->
<div ng-if="!model.configData.groupingMode.autoRegroup" class="column small-8 ng-scope">
</div>
<!-- end ngIf: !model.configData.groupingMode.autoRegroup -->
<!-- ngIf: model.configData.groupingMode.autoRegroup -->
<div class="column small-4 left-delimiter no-regroup" ng-class="{'no-regroup' : !model.configData.groupingMode.autoRegroup}">
<button type="button" class="light" ng-click="model.addGroup()" ng-disabled="!model.canAddGroup()">Add group
</button>
</div>
</div>
<!-- ngRepeat: group in model.groupingData -->
<div class="group ng-scope" ng-repeat="group in model.groupingData">
******<div index="1" class="drop-outer" ui-on-drop="model.onDrop(group)" ui-drag-enter="model.dragOver(group)" ui-drag-leave="model.dragLeave(group)">
<div class="button radius group-btn" ng-style="{'background-color': group.color}" ng-click="model.toggleState(group)" ui-on-drop="model.onMoveDrop(group)"
ui-drag-enter="moveActive = true;model.autoScroll(el);" ui-drag-leave="moveActive = false;" style="background-color: rgb(0, 155, 159);">
<div class="left group-label ng-binding">Group 1 | 4
<span ng-show="group.students.length !== 1" class="">Students
</span>
<span ng-show="group.students.length === 1" class="ng-hide">Student
</span>
</div>
<div class="right group-collapser" ng-hide="group.students.length == 0">
<!-- ngIf: group.collapsed -->
<!-- ngIf: !group.collapsed -->
<span class="glyph-chevron-collapsed ng-scope" ng-if="!group.collapsed">
</span>
<!-- end ngIf: !group.collapsed -->
</div>
</div>
<div ng-show="group.showAddContainers" class="row drop-container ng-hide">
<div ui-on-drop="model.onMoveDrop(group)" class="column" ng-class="{'active':moveActive}">
**********<div class="move">Move
</div>
</div>
<div ui-on-drop="model.onCopyDrop(group)" class="column">
<div class="copy">Copy
</div>
</div>
</div>
<!-- ngIf: !group.collapsed -->
******<div class="row students slide-animation drag-elements ng-scope" ng-if="!group.collapsed">
<!-- ngRepeat: student in group.students -->
<a no-chrome-href="" title="AM2Paper S" alt="AM2Paper S" class="student-btn-cont fade-animation ng-scope" ng-repeat="student in group.students"
ui-draggable="true" on-drag-begin="model.dragStart(student, group)" drag="student" drag-class="student-btn-cont student-btn-cont-dragged"
on-drop-success="model.dropSuccessHandler($index,group)" draggable="true" style="">
<div ng-style="{'background-color': group.color}" class="radius column student-btn" style="background-color: rgb(0, 155, 159);">
************<div class="left student-label ng-isolate-scope" rl-display-name="" long-name="AM2Paper S" style="font-size: 9px;">AM2Paper S
</div>
</div>
<div class="dots dots-line">
</div>
</a>
<!-- end ngRepeat: student in group.students -->
<a no-chrome-href="" title="AMTest A" alt="AMTest A" class="student-btn-cont fade-animation ng-scope" ng-repeat="student in group.students"
ui-draggable="true" on-drag-begin="model.dragStart(student, group)" drag="student" drag-class="student-btn-cont student-btn-cont-dragged"
on-drop-success="model.dropSuccessHandler($index,group)" draggable="true" style="">
<div ng-style="{'background-color': group.color}" class="radius column student-btn" style="background-color: rgb(0, 155, 159);">
<div class="left student-label ng-isolate-scope" rl-display-name="" long-name="AMTest A" style="font-size: 11px;">AMTest A
</div>
</div>
<div class="dots dots-line">
</div>
</a>
<!-- end ngRepeat: student in group.students -->
<a no-chrome-href="" title="AMTestPaper A" alt="AMTestPaper A" class="student-btn-cont fade-animation ng-scope" ng-repeat="student in group.students"
ui-draggable="true" on-drag-begin="model.dragStart(student, group)" drag="student" drag-class="student-btn-cont student-btn-cont-dragged"
on-drop-success="model.dropSuccessHandler($index,group)" draggable="true" style="">
<div ng-style="{'background-color': group.color}" class="radius column student-btn" style="background-color: rgb(0, 155, 159);">
<div class="left student-label ng-isolate-scope" rl-display-name="" long-name="AMTestPaper A" style="font-size: 9px;">AMTestPaper...
</div>
</div>
<div class="dots dots-line">
</div>
</a>
<!-- end ngRepeat: student in group.students -->
<a no-chrome-href="" title="AM2Online S" alt="AM2Online S" class="student-btn-cont fade-animation ng-scope" ng-repeat="student in group.students"
ui-draggable="true" on-drag-begin="model.dragStart(student, group)" drag="student" drag-class="student-btn-cont student-btn-cont-dragged"
on-drop-success="model.dropSuccessHandler($index,group)" draggable="true" style="">
<div ng-style="{'background-color': group.color}" class="radius column student-btn" style="background-color: rgb(0, 155, 159);">
<div class="left student-label ng-isolate-scope" rl-display-name="" long-name="AM2Online S" style="font-size: 9px;">AM2Online S
</div>
</div>
<div class="dots dots-line">
</div>
</a>
<!-- end ngRepeat: student in group.students -->
</div>
<!-- end ngIf: !group.collapsed -->
<div ng-show="group.showRemoveContainers" class="row drop-container ng-hide">
<div class="column remove" ui-on-drop="model.onRemoveDrop(group)">
<div class="remove ng-binding">Remove from Group 1
</div>
</div>
</div>
</div>
<!-- ngIf: group.students.length == 0 -->
</div>
<!-- end ngRepeat: group in model.groupingData -->
<div class="group ng-scope" ng-repeat="group in model.groupingData">
******<div index="2" class="drop-outer" ui-on-drop="model.onDrop(group)" ui-drag-enter="model.dragOver(group)" ui-drag-leave="model.dragLeave(group)">
<div class="button radius group-btn" ng-style="{'background-color': group.color}" ng-click="model.toggleState(group)" ui-on-drop="model.onMoveDrop(group)"
ui-drag-enter="moveActive = true;model.autoScroll(el);" ui-drag-leave="moveActive = false;" style="background-color: rgb(109, 48, 146);">
<div class="left group-label ng-binding">Group 2 | 0
<span ng-show="group.students.length !== 1" class="">Students
</span>
<span ng-show="group.students.length === 1" class="ng-hide">Student
</span>
</div>
<div class="right group-collapser ng-hide" ng-hide="group.students.length == 0">
<!-- ngIf: group.collapsed -->
<!-- ngIf: !group.collapsed -->
<span class="glyph-chevron-collapsed ng-scope" ng-if="!group.collapsed">
</span>
<!-- end ngIf: !group.collapsed -->
</div>
</div>
<div ng-show="group.showAddContainers" class="row drop-container ng-hide">
<div ui-on-drop="model.onMoveDrop(group)" class="column" ng-class="{'active':moveActive}">
************<div class="move">Move
</div>
</div>
<div ui-on-drop="model.onCopyDrop(group)" class="column">
<div class="copy">Copy
</div>
</div>
</div>
<!-- ngIf: !group.collapsed -->
<div class="row students slide-animation drag-elements ng-scope" ng-if="!group.collapsed" style="">
<!-- ngRepeat: student in group.students -->
</div>
<!-- end ngIf: !group.collapsed -->
<div ng-show="group.showRemoveContainers" class="row drop-container ng-hide">
<div class="column remove" ui-on-drop="model.onRemoveDrop(group)">
<div class="remove ng-binding">Remove from Group 2
</div>
</div>
</div>
</div>
<!-- ngIf: group.students.length == 0 -->
<div class="empty-group-label ng-scope" ng-if="group.students.length == 0">
<span class="left">Drag student icons into this Group
</span>
<a href="" class="right" ng-click="model.removeGroup($index)">Delete this group
</a>
</div>
<!-- end ngIf: group.students.length == 0 -->
</div>
<!-- end ngRepeat: group in model.groupingData -->
</div>
星星标志着相关元素。如果您可能需要其他相关信息,请与我们联系。
答案 0 :(得分:1)
Selenium的拖放动作与HTML5不相称,所以我使用jquery来拖动元素。
我用这些作为参考: https://gist.github.com/rcorreia/2362544 http://elementalselenium.com/tips/39-drag-and-drop
这就是结果:
public void WhenAStudentIsMovedToANewGroup(string action, string student, string group)
{
WaitForAngular();
IWebDriver driver = (IWebDriver)FeatureContext.Current["Driver"];
/*
* Load a version of jQuery that we can access
*/
driver.Manage().Timeouts().SetScriptTimeout(TimeSpan.FromSeconds(10));
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteAsyncScript(loadJQuery, jQueryUrl);
string dragEntity = string.Format("[title=\"{0}\"]", student);
string target = string.Format("[ui-on-drop=\"model.onMoveDrop(group)\"]:contains({0}) ~ div > div .{1}", group, action);
string javaScriptString = string.Format("{0}$('{1}').simulateDragDrop({{ dropTarget: '{2}'}});", dragAndDropHelper, dragEntity, target);
//Execute the drag and drop against the HTML5
js.ExecuteScript(javaScriptString);
}
const string dragAndDropHelper = @"(function( $ ) {
$.fn.simulateDragDrop = function(options) {
return this.each(function() {
new $.simulateDragDrop(this, options);
});
};
$.simulateDragDrop = function(elem, options) {
this.options = options;
this.simulateEvent(elem, options);
};
$.extend($.simulateDragDrop.prototype, {
simulateEvent: function(elem, options) {
/*Simulating drag start*/
var type = 'dragstart';
var event = this.createEvent(type);
this.dispatchEvent(elem, type, event);
/*Simulating drop*/
type = 'drop';
var dropEvent = this.createEvent(type, {});
dropEvent.dataTransfer = event.dataTransfer;
this.dispatchEvent($(options.dropTarget)[0], type, dropEvent);
/*Simulating drag end*/
type = 'dragend';
var dragEndEvent = this.createEvent(type, {});
dragEndEvent.dataTransfer = event.dataTransfer;
this.dispatchEvent(elem, type, dragEndEvent);
},
createEvent: function(type) {
var event = document.createEvent(""CustomEvent"");
event.initCustomEvent(type, true, true, null);
event.dataTransfer = {
data: {
},
setData: function(type, val){
this.data[type] = val;
},
getData: function(type){
return this.data[type];
}
};
return event;
},
dispatchEvent: function(elem, type, event) {
if(elem.dispatchEvent) {
elem.dispatchEvent(event);
}else if( elem.fireEvent ) {
elem.fireEvent(""on""+type, event);
}
}
});
})(jQuery);";
const string loadJQuery = @"(function(jqueryUrl, callback) {
if (typeof jqueryUrl != 'string') {
jqueryUrl = 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js';
}
if (typeof jQuery == 'undefined') {
var script = document.createElement('script');
var head = document.getElementsByTagName('head')[0];
var done = false;
script.onload = script.onreadystatechange = (function() {
if (!done && (!this.readyState || this.readyState == 'loaded'
|| this.readyState == 'complete')) {
done = true;
script.onload = script.onreadystatechange = null;
head.removeChild(script);
callback();
}
});
script.src = jqueryUrl;
head.appendChild(script);
}
else {
callback();
}
})(arguments[0], arguments[arguments.length - 1]);";