2017-10-05 61 views
1

我正在使用茉莉花/量角器對我公司管理的多個站點運行測試套件。 (這些網站是訂單/結帳網站)目前,我爲每個網站設置了一個單獨的測試套件,該套件使用我創建並存儲在幫助器中的函數來填寫每個表單,以便我可以將這些函數我的規格,並通過訂單流程來執行測試訂單,目前這項工作正常,並且呼叫助手經歷了沒有問題。檢查數組中的任何值是否與dom中的某個元素相匹配,然後將數值傳送到量角器中的該元素

量角器:V5.1.2
茉莉花:V2.6
節點:V8.0.0

這裏的問題是,每個站點傾向於使用任意數量的字段標識符的每個字段,並且我最終爲特定網站上的特定表單編寫了特定函數。每個站點使用2到4種表單之間的任何地方,最終結果是數百個相同的功能只在選擇器中有所不同。所以我試圖重構我的代碼,這樣我就可以爲每個站點上使用的每個表單創建一個函數。

輸入我的問題:我無法弄清楚如何使我的測試檢查在頁面上加載的元素的值與可能的元素列表。基本上是我需要做的是這樣的:

  • 打開頁面
  • 檢查元素(by.name(「someName」)對名單上有
  • 一旦找到匹配,使用匹配的對於someName值
  • 的SendKeys( 'someValue中'),該值
  • 重複的表單上的所有字段

我有什麼:

我的規格:

這是在我的測試文件中的實際規範。

it('Checks for fieldName and then fills in the form', function(done) { 
     cQualify(); 
     done(); 
    }); 

cQualify功能:

功能是存儲在一個叫幫手formFill.js。

cQualify = function() { 
    findElementByFieldName(cartData.fName).sendKeys('Jimmy'); 
    findElementByFieldName(cartData.cGender).sendKeys('Male'); 
    findElementByFieldName(cartData.cAge).sendKeys('34'); 
    findElementByFieldName(cartData.cZip).sendKeys('33071'); 
//more fields here and a submit button 
}; 

findElementByFieldName功能:

這個功能是存儲在一個名爲助手和arrayLoop.js是爲了使這項工作我的最新嘗試。本來這是一起的線路更多:

browser.driver.findElement(by.name('someName')).sendKeys('nameToSend'); 
//repeated for each field on the form 

下面是函數:

可能的元素被存儲在一個名爲FORMDATA幫手裏面:

findElementByFieldName = function(fieldName) { 
     if (fieldName.constructor === Array) { 
      console.log('Array found, looping values for array: ' + fieldName); 

      for(var i=0; i < fieldName.length; i++) { 
       expect(element(by.name(fieldName[i])).isDisplayed()).toBe(true); 
       console.log('Checking if page element ' + fieldName[i] + ' exists'); 
      } 
//some code that checks if the current value of fieldName[i] is in the page DOM 
//and if so; returns that and exits the loop 

     } else { 
      return browser.driver.findElement(by.name(fieldName)); 
     } 
    } 

可能元素的列表.js(注意:只有那些有多個可能值的數組是在一個數組中;其他的我沒有問題)

cartData = { 
    fName: ['cShipFname', 'zang_fname', 'fname'], 
    lName: ['cShipLname', 'zang_lname', 'lname'], 
    cZip: ['cShipZip', 'zang_zip', 'zip'], 
    cGender: 'zang_gender', 
    cAge: 'zang_age', 
    cProblem: 'zang_problem' 
//lots of additional values here 
}; 

結果:

當我運行該原樣,測試遍歷包含在cartData.fName所有值,認爲它們全部顯示出來,然後失敗嘗試的SendKeys用時:

Failed: Cannot read property 'sendKeys' of undefined 

所以這裏是我卡住的地方。我不僅需要循環來檢查數組中的值是否在頁面上,我需要它在找到匹配項時停止循環,並返回該值,以便我可以按照它在cQualify()中的佈局方式使用它。功能。我嘗試了一些不同的東西,例如在if中使用isDisplayed(),但似乎這隻能用於expect。我也試圖把我的規格在函數中,然後直接循環該功能在測試 - 但是這也有類似的結果,也將打敗formFill.js

更新的目的:

我發現處理類似的事情在SO另一個問題:here
從接受答案的代碼是:

var link = element.all(by.css('a')).reduce(function (result, elem, index) { 
    if(result) return result; 

    return elem.getText().then(function(text){ 
     if(text === "mylink") return elem; 
    }); 

}).then(function(result){ 
    if(!result) throw new Error("Element not found"); 
    return result; 
}); 

雖然我無法弄清楚(到目前爲止)我怎麼會適應它來滿足我的需求。

回答

0

您可以簡單地構建一個具有多個或條件的動態XPath表達式,而不是使其更加複雜。看下面的示例代碼。

function getElement(nameList) { 
    if(nameList.constructor != Array){ 
     nameList=[nameList] 
    } 

    var xpathExpression = ".//*[" 
    nameList.forEach(function(name,index){ 
     xpathExpression += "@name='"+name+"'"; 
      if(index != nameList.length-1){ 
       xpathExpression+=" or "; 
      } else { 
       xpathExpression+= "]"; 
      } 
     }); 
    return element(by.xpath(xpathExpression)); 
} 

所以,如果你想找到fName: ['cShipFname', 'zang_fname', 'fname']的元素,你可以簡單地調用getElement,它將返回您基於匹配的XPath expression.The XPath表達式的Web元素爲fname是,

.//*[@name='cShipFname' or @name='zang_fname' or @name='fname']

+0

完美!這工作很好,非常感謝你! – Carlosyn

0

儘管已經回答了,但我並不是XPath的忠實粉絲。因此,我想提供使用filter()indexOf()includes()的替代方法。

首先使用indexOf()

function getElement(nameList) { 
    //keeping it an array for all calls (thumbs up for this thought of @SudharsanSevaraj) 
    if(nameList.constructor != Array){ 
     nameList=[nameList] 
    } 
    //selecting all elements with a name-attribute 
    //then filter the one(s), that is/are present in nameList and use first 
    return $$('[name]').filter(function(elem, index){ 
     return elem.getAttribute('name').then(function(elName){ 
      //return the element, if its name-attribute is present in nameList 
      return nameList.indexOf('elName') !== -1 
     }); 
    }).first(); 
}; 

而同樣略有不同,使用includes()這一次。

function getElement(nameList) { 
    //keeping it an array for all calls (thumbs up for this thought of @SudharsanSevaraj) 
    if(nameList.constructor != Array){ 
     nameList=[nameList] 
    } 
    //selecting all elements with a name-attribute, 
    //then filter the one(s), that is/are present in nameList and use first 
    return $$('[name]').filter(function(elem, index){ 
     return elem.getAttribute('name').then(function(elName){ 
      return nameList.includes(elName); 
     }); 
    }).first(); 
}; 
相關問題