[C#] [Selenium]如何拖曳一个元素 [英] [C#][Selenium] How to drag-hover-drop an element

查看:163
本文介绍了[C#] [Selenium]如何拖曳一个元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行的网站是在内部服务器上,所以我不能给一个链接,但我可以发布一些当你点击显示元素显示的相关代码

The website I am running this against is on an internal server so I can't give a link but I can post some of the relevant code that is shown when you click "show element"

有5个元素与此相关:


  • Group1

  • 学生

  • move1

  • Group2

  • move2

  • Group1
  • student
  • move1
  • Group2
  • move2

此页面显示学生组,并允许用户在学生之间拖动学生。每个组都有一个移动元素。棘手的部分是,任何给定组的移动按钮只会在用户将该学生元素拖动到该组中时显示,而学生不是来自该组。

This page shows groups of students and allows the user to drag students between groups. There is a move element for each group. The tricky part is that the move button for any given group only shows up while the user is dragging a student element over that group, and the student was not from that group.

目标是将学生移动到新组,然后返回原始组。

The goal is to move a student to a new group and then back to the original group.

注意:
学生XPath更改组时更改
我无法确认,但我相信移动按钮的XPath是不同的,而隐藏而不是可见

notes: The students XPath changes when they change groups I can't confirm but I believe the XPath for the move buttons are different while hidden than while visible

我当前的代码:

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();

此代码不会移动任何元素,并尝试查找保存时失败,因为没有更改(其中预期没有任何动作)。

This code doesn't move any elements and fails when trying to find save because nothing was changed(which is expected given that nothing moves).

页面上的相关代码:

  <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>

星标记相关元素。如果还有其他可能需要上传的信息,请告知我。

Stars mark the relevant elements. Let me know if there is other information that you may need for context.

推荐答案

Selenium的拖放操作不会很好使用HTML5,所以我诉诸使用jquery来拖动元素。

Selenium's actions for drag and drop do not play nice with HTML5 so I resorted to using jquery to drag the element.

我用这些作为参考:
https://gist.github.com/rcorreia/2362544
http://elementalselenium.com/tips/39-drag-and-drop

I used these as references: 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]);";

这篇关于[C#] [Selenium]如何拖曳一个元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆