什么时候应该使用 element.all(locator).then(thenFunction) 或 element.all(locator)?

When should element.all(locator).then(thenFunction) or element.all(locator) be used?

在量角器中,(source):

有什么区别

示例 1

const allOptions = element.all(by.options('fruit for fruit in fruits'));
expect(await allOptions.count()).toEqual(4);

和(source):

示例 2

const arr = await element.all(by.model('color'));
expect(arr.length).toEqual(3);

为什么如果我这样做...

示例 3

let allOptions = await element.all(by.css('.mat-option-text > span'));
let firstOption = allOptions.first();

...我收到这个静态打字稿错误?

Property 'first' does not exist on type 'any[] | ElementFinder[]'. Property 'first' does not exist on type 'any[]'.ts(2339)


element.all(locator).then(thenFunction) and element.all(locator) 的正确用法是什么?

本质上,element.all return 是一个 ElementArrayFinder object but await element.all will return an array of ElementFinder 对象。

等待的 ElementArrayFinder 是一个简单的 ElementFinder 对象数组,因此可以调用所有现有的 array methods(例如长度)。 unawaited ElementArrayFinder 是一个用量角器定义的特殊对象,并具有可用的特殊方法(例如 count()、get() 和 first())。

量角器中列出了 ElementArrayFinder 可用的方法 api。

例子

对于此示例,请转到页面 https://angular.io/$([class="button hero-cta"]) 在此页面上仅找到一个元素

console.log(element.all('[class="button hero-cta"]')) 将 return以下 ElementArrayFinder 对象

ElementArrayFinder {
  browser_: ProtractorBrowser {
    controlFlow: [Function],
    schedule: [Function],
    setFileDetector: [Function],
    getExecutor: [Function],
    getSession: [Function],
    getCapabilities: [Function],
    quit: [Function],
    actions: [Function],
    touchActions: [Function],
    executeScript: [Function],
    executeAsyncScript: [Function],
    call: [Function],
    wait: [Function],
    sleep: [Function],
    getWindowHandle: [Function],
    getAllWindowHandles: [Function],
    getPageSource: [Function],
    close: [Function],
    getCurrentUrl: [Function],
    getTitle: [Function],
    findElementInternal_: [Function],
    findElementsInternal_: [Function],
    takeScreenshot: [Function],
    manage: [Function],
    switchTo: [Function],
    driver: thenableWebDriverProxy {
      flow_: [ControlFlow],
      session_: [ManagedPromise],
      executor_: [Executor],
      fileDetector_: null,
      onQuit_: undefined,
      cancel: [Function],
      then: [Function: bound then],
      catch: [Function: bound then],
      getNetworkConnection: [Function],
      setNetworkConnection: [Function],
      toggleAirplaneMode: [Function],
      toggleWiFi: [Function],
      toggleData: [Function],
      toggleLocationServices: [Function],
      getGeolocation: [Function],
      setGeolocation: [Function],
      getCurrentDeviceActivity: [Function],
      startDeviceActivity: [Function],
      getAppiumSettings: [Function],
      setAppiumSettings: [Function],
      getCurrentContext: [Function],
      selectContext: [Function],
      getScreenOrientation: [Function],
      setScreenOrientation: [Function],
      isDeviceLocked: [Function],
      lockDevice: [Function],
      unlockDevice: [Function],
      installApp: [Function],
      isAppInstalled: [Function],
      removeApp: [Function],
      pullFileFromDevice: [Function],
      pullFolderFromDevice: [Function],
      pushFileToDevice: [Function],
      listContexts: [Function],
      uploadFile: [Function],
      switchToParentFrame: [Function],
      fullscreen: [Function],
      sendAppToBackground: [Function],
      closeApp: [Function],
      getAppStrings: [Function],
      launchSession: [Function],
      resetApp: [Function],
      hideSoftKeyboard: [Function],
      getDeviceTime: [Function],
      openDeviceNotifications: [Function],
      rotationGesture: [Function],
      shakeDevice: [Function],
      sendChromiumCommand: [Function],
      sendChromiumCommandAndGetResult: [Function]
    },
    element: [Function: element] { all: [Function] },
    '$': [Function],
    '$$': [Function],
    baseUrl: '',
    getPageTimeout: 10000,
    params: {},
    resetUrl: 'data:text/html,<html></html>',
    debugHelper: DebugHelper { browserUnderDebug_: [Circular] },
    ready: ManagedPromise {
      flow_: [ControlFlow],
      stack_: null,
      parent_: null,
      callbacks_: null,
      state_: 'fulfilled',
      handled_: true,
      value_: [Circular],
      queue_: null
    },
    trackOutstandingTimeouts_: true,
    mockModules_: [ [Object] ],
    ExpectedConditions: ProtractorExpectedConditions { browser: [Circular] },
    plugins_: Plugins {
      setup: [Function],
      onPrepare: [Function],
      teardown: [Function],
      postResults: [Function],
      postTest: [Function],
      onPageLoad: [Function],
      onPageStable: [Function],
      waitForPromise: [Function],
      waitForCondition: [Function],
      pluginObjs: [],
      assertions: {},
      resultsReported: false
    },
    allScriptsTimeout: 11000,
    getProcessedConfig: [Function],
    forkNewDriverInstance: [Function],
    restart: [Function],
    restartSync: [Function],
    internalRootEl: '',
    internalIgnoreSynchronization: true
  },
  getWebElements: [Function: getWebElements],
  locator_: name(name) {
    return By.css('*[name="' + escapeCss(name) + '"]');
  } {
    using: 'css selector',
    value: '[class="button hero-cta"]'
  },
  actionResults_: null,
  click: [Function],
  sendKeys: [Function],
  getTagName: [Function],
  getCssValue: [Function],
  getAttribute: [Function],
  getText: [Function],
  getSize: [Function],
  getLocation: [Function],
  isEnabled: [Function],
  isSelected: [Function],
  submit: [Function],
  clear: [Function],
  isDisplayed: [Function],
  getId: [Function],
  takeScreenshot: [Function]
}

console.log(等待element.all('[class="button hero-cta"]'))将return ElementFinder 对象数组

[
  ElementFinder {
    browser_: ProtractorBrowser {
      controlFlow: [Function],
      schedule: [Function],
      setFileDetector: [Function],
      getExecutor: [Function],
      getSession: [Function],
      getCapabilities: [Function],
      quit: [Function],
      actions: [Function],
      touchActions: [Function],
      executeScript: [Function],
      executeAsyncScript: [Function],
      call: [Function],
      wait: [Function],
      sleep: [Function],
      getWindowHandle: [Function],
      getAllWindowHandles: [Function],
      getPageSource: [Function],
      close: [Function],
      getCurrentUrl: [Function],
      getTitle: [Function],
      findElementInternal_: [Function],
      findElementsInternal_: [Function],
      takeScreenshot: [Function],
      manage: [Function],
      switchTo: [Function],
      driver: [thenableWebDriverProxy],
      element: [Function],
      '$': [Function],
      '$$': [Function],
      baseUrl: '',
      getPageTimeout: 10000,
      params: {},
      resetUrl: 'data:text/html,<html></html>',
      debugHelper: [DebugHelper],
      ready: [ManagedPromise],
      trackOutstandingTimeouts_: true,
      mockModules_: [Array],
      ExpectedConditions: [ProtractorExpectedConditions],
      plugins_: [Plugins],
      allScriptsTimeout: 11000,
      getProcessedConfig: [Function],
      forkNewDriverInstance: [Function],
      restart: [Function],
      restartSync: [Function],
      internalRootEl: '',
      internalIgnoreSynchronization: true
    },
    then: null,
    parentElementArrayFinder: ElementArrayFinder {
      browser_: [ProtractorBrowser],
      getWebElements: [Function: getWebElements],
      locator_: [name(name) {
    return By.css('*[name="' + escapeCss(name) + '"]');
  }],
      actionResults_: null,
      click: [Function],
      sendKeys: [Function],
      getTagName: [Function],
      getCssValue: [Function],
      getAttribute: [Function],
      getText: [Function],
      getSize: [Function],
      getLocation: [Function],
      isEnabled: [Function],
      isSelected: [Function],
      submit: [Function],
      clear: [Function],
      isDisplayed: [Function],
      getId: [Function],
      takeScreenshot: [Function]
    },
    elementArrayFinder_: ElementArrayFinder {
      browser_: [ProtractorBrowser],
      getWebElements: [Function: getWebElements],
      locator_: [name(name) {
    return By.css('*[name="' + escapeCss(name) + '"]');
  }],
      actionResults_: null,
      click: [Function],
      sendKeys: [Function],
      getTagName: [Function],
      getCssValue: [Function],
      getAttribute: [Function],
      getText: [Function],
      getSize: [Function],
      getLocation: [Function],
      isEnabled: [Function],
      isSelected: [Function],
      submit: [Function],
      clear: [Function],
      isDisplayed: [Function],
      getId: [Function],
      takeScreenshot: [Function]
    },
    click: [Function],
    sendKeys: [Function],
    getTagName: [Function],
    getCssValue: [Function],
    getAttribute: [Function],
    getText: [Function],
    getSize: [Function],
    getLocation: [Function],
    isEnabled: [Function],
    isSelected: [Function],
    submit: [Function],
    clear: [Function],
    isDisplayed: [Function],
    getId: [Function],
    takeScreenshot: [Function]
  }
]
.


1 spec, 0 failures
Finished in 3.881 seconds

[13:33:25] I/local - Shutting down selenium standalone server.
[13:33:25] I/launcher - 0 instance(s) of WebDriver still running
[13:33:25] I/launcher - chrome #01 passed

C:\ProtractorProjects\ddg>

我觉得你对每一个的作用都不是很清楚...

element(...) - returns ElementFinder(一个元素)

element.all(...) - returns ElementArrayFinder(许多元素)

两者都用于指向元素。然后你想与他们互动——点击、计数、获取文本等……无论你想用它们做什么都是 Promise。所以

element().count()element().getText() - return 承诺

Promise本质上什么都不是...因为后面可能会解决,可能是pending,可能会被拒绝(其实也不是什么都没有,只是这样想更容易)

await 关键字解析 Promise 和 returns 一个值,对于 .count() 将是一个数字或对于 .getText()

是一个字符串

所以你应该做的是这个

// declare an element
let elem = element(by.css('some css'));

// then you declare a promise and resolve it
let value = await elem.getText()
// or
await elem.click()