【问题标题】:Protractor> TypeError: item.element is not a functionProtractor> TypeError: item.element 不是函数
【发布时间】:2019-03-31 04:00:30
【问题描述】:

我正在从事一个关于量角器的电子商务项目,但老实说,我无法弄清楚 IT 案例出了什么问题。我收到以下错误

Failed: item.element is not a function[0m
  Stack:
    TypeError: item.element is not a function

最后一天我一直在拔头发,但控制台并不清楚具体问题。因为我已经检查过,但看不到问题。

问题:这是什么?我该如何解决这个问题?

课程中的代码乱七八糟,所以我会为你整理一下。

代码

describe('电子商务 Angular 项目', function () {

it('Customer Shopping cart', function () {
    // write your code here!!!

  function selectItem(product) {
      //chain the locators so that you can pick a specific item regardless of where it is located

      element.all(by.tagName("app-card")).then(function (item) {

          item.element(by.css("h4 a")).getText().then(function (text) {

              if (text == "Samsung Note 8") {
                  // add to cart button if loop is correct. 
                  item.element(By.css("button[class*='btn-info']")).click();                           
              } //end of if Loop 


          })//END: this promise add to cart button for samsung

      })//end of command to find samsung 8

  }

  it('Customer registration', function () {
      // write your code here!!!

      //Scenario 3:  Go Shop page and add items to shopping cart

      //Given I am on the home page
      //when I select the shop link 
      //Then I am taken to the shop page
      //When I am in the shop page I select a mobile phone
      //Then the shopping cart  will show 1 item added
      //When I add another mobile phone to the shopping cart 
      //Then the shopping cart  will show 2 items added

      element(by.linkText("Shop")).click();

      //Select 2 items for shopping cart

      selectItem("Samsung Note 8");
      selectItem("iphone X");

      // I want to display the results and confirm there are only 2 items in the shopping cart
      element(by.partialLinkText("Checkout")).getText().then(function (text) {

          // I want to show both items in the console on a separate line confirm that it 2 items
          var res = text.split("(");
          expect(res[1].trim().charAt(0)).toBe("2");

      })//END: this function will display items in console from shopping bag

  })    //end of customer registration & shopping  it block 
})//end of describe block

来自控制台的消息

(请注意,此规范文件中存在 IT 案例,它们仅通过了一次,因此请忽略这些消息,但是当 IT 场景出现时,事情变得非常错误)

(node:10145) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
[16:34:32] I/launcher - Running 1 instances of WebDriver
[16:34:32] I/hosted - Using the selenium server at http://localhost:4444/wd/hub
Started
[16:34:36] W/element - more than one element found for locator By(css selector, *[name="name"]) - the first result will be used
×
Success! The Form has been submitted successfully!.
[16:34:37] W/element - more than one element found for locator By(css selector, *[name="name"]) - the first result will be used
[16:34:37] W/element - more than one element found for locator By(css selector, *[name="name"]) - the first result will be used
Name should be at least 2 characters
[31mF[0m

Failures:
1) Ecommerce Angular Project Customer registration
  Message:
[31m    Failed: item.element is not a function[0m
  Stack:
    TypeError: item.element is not a function
        at /Users/xxx/Documents/JSworkspace/LocatorTraining/ecommerceAutomation.js:10:12
        at ManagedPromise.invokeCallback_ (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:1376:14)
        at TaskQueue.execute_ (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:3084:14)
        at TaskQueue.executeNext_ (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:3067:27)
        at asyncRun (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:2927:27)
        at /Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/selenium-webdriver/lib/promise.js:668:7
        at <anonymous>
        at process._tickCallback (internal/process/next_tick.js:188:7)
    From: Task: Run it("Customer registration") in control flow
        at UserContext.<anonymous> (/Users/xxx/Documents/JSworkspace/LocatorTraining/protractor/node_modules/jasminewd2/index.js:94:19)
    From asynchronous test: 
    Error
        at Suite.<anonymous> (/Users/xxx/Documents/JSworkspace/LocatorTraining/ecommerceAutomation.js:27:2)
        at Object.<anonymous> (/Users/xxx/Documents/JSworkspace/LocatorTraining/ecommerceAutomation.js:1:63)
        at Module._compile (module.js:652:30)
        at Object.Module._extensions..js (module.js:663:10)
        at Module.load (module.js:565:32)
        at tryModuleLoad (module.js:505:12)

1 spec, 1 failure
Finished in 3.801 seconds

[16:34:38] I/launcher - 0 instance(s) of WebDriver still running
[16:34:38] I/launcher - chrome #01 failed 1 test(s)
[16:34:38] I/launcher - overall: 1 failed spec(s)
[16:34:38] E/launcher - Process exited with error code 1

【问题讨论】:

  • console.log(item)console.log(item.element),如果你这样做了,那么共享日志。很明显,您正在尝试调用函数element,这不是函数。像var data = 10; 然后调用data(); 这会给我同样的错误。
  • 不,我无法 console.log(item)。我不认为代码有那么远
  • 我不确定你想在这里实现什么element.all(by.tagName("app-card")).then(function (item) {})。如果你想用text=="Samsung Note 8"获取所有元素,那么你缺少过滤器。因此你会有element.all(by.tagName("app-card")).filter(function (item) {return item.element(by.css("h4 a")).gettext().then(function(text){return text==="Samsung Note 8"})})。它会返回给你满足此要求的元素数组。但是,如果您只寻找一件商品,那么为什么不使用element(by.tagName("app-card")).element(by.cssContainingText("h4 a","Samsung Note 8"))
  • @SergeyPleshakov 非常感谢。 Sergy 我在阅读课程材料时完全同意,我不明白为什么三星仍然处于“功能”中,或者我认为应该保留空白以打开其他项目可以在大批。但是 Yong 好心地为我提供了答案,我尝试了他的代码,它运行良好。我将对这段代码进行逆向工程,并在未来使用它。

标签: javascript automation protractor automated-tests


【解决方案1】:

element.all() 返回ElementArrayFinder,你可以认为它是一个元素数组。因此then() 中的item 代表一个数组,而不是单个元素。

element.all(by.tagName("app-card")).then(function (item) {
    item.element(...)
    ...
})

您不能在 array 对象上调用 .element()。但是您可以在单个元素上调用.element(),如下所示:

element.all(by.tagName("app-card")).then(function (items) {
    items[0].element(...) // items[0] is single element.
    ...
})

对于您的情况,函数selectItem 应更改如下:

function selectItem(product) {
    //chain the locators so that you can pick a specific item regardless of where it is located

    element.all(by.tagName("app-card")).filter(function(item){
        return item.element(by.css("h4 a")).getText().then(function(txt){
            return txt === product;
        });
    }).then(function(items){
        if(items.length > 0) {
            items[0].element(by.css("button[class*='btn-info']")).click();
        }
        else {
            console.error('Not find product: ' + product);
        }
    }).catch(function(err){
       console.error(err);
    });
}

【讨论】:

  • 请原谅我的无知。我仍在使用量角器进行学习。你的回答让我有点困惑。您是说在这种情况下我不能使用 element.all() 而应该使用 .element() 吗?这是对的还是我误解了你?
  • 你可以使用 element.all() 在你的情况下,我的重点是element.all().then(function(item){ // the item at here is an array, in javascript Array object has no such element() function , this is why you get error "item.element is not a function" })
  • 感谢您的回复。那么我应该怎么做才能解决这个问题呢?尽可能用最基本的方式告诉我。如何修复这段代码以使其正常工作。
  • 你看不懂我的回答?我已经在我的回答 element.all(by.tagName("app-card")).then(function (items) { items[0].element(...) // items[0] is single element. ... }) 中显示了修复代码
  • 首先我要感谢你帮助我解决这个问题。我还在学习使用量角器,我的理解是你给了我答案并没有像我想的那样迅速地跳出来喜欢过。感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 2020-06-29
  • 2020-06-17
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 2018-06-12
  • 2021-06-05
  • 2019-10-03
相关资源
最近更新 更多