[C#][Selenium] How to drag-hover-drop an element -
the website running against on internal server can't give link can post of relevant code shown when click "show element"
there 5 elements relevant this:
- group1
- student
- move1
- group2
- move2
this page shows groups of students , allows user drag students between groups. there move element each group. tricky part move button given group shows while user dragging student element on group, , student not group.
the goal move student new group , original group.
notes: students xpath changes when change groups can't confirm believe xpath move buttons different while hidden while visible
my current code:
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 , 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();
this code doesn't move elements , fails when trying find save because nothing changed(which expected given nothing moves).
relevant code page:
<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 </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 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 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 group </span> <a href="" class="right" ng-click="model.removegroup($index)">delete group </a> </div> <!-- end ngif: group.students.length == 0 --> </div> <!-- end ngrepeat: group in model.groupingdata --> </div>
stars mark relevant elements. let me know if there other information may need context.
selenium's actions drag , drop not play nice html5 resorted using jquery drag element.
i used these references: https://gist.github.com/rcorreia/2362544 http://elementalselenium.com/tips/39-drag-and-drop
and result:
public void whenastudentismovedtoanewgroup(string action, string student, string group) { waitforangular(); iwebdriver driver = (iwebdriver)featurecontext.current["driver"]; /* * load version of jquery 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 drag , drop against 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]);";
Comments
Post a Comment