Protractor 如何在量角器中更改浏览器日期

Protractor 如何在量角器中更改浏览器日期,protractor,Protractor,我的用例是,我有一个UI,它可以阻止操作B,除非操作a在上一个日历月发生(会计生命周期疯狂-无所谓) 我正在编写一个测试来验证操作B是否正常工作,但除非上个月发生了操作a,否则我无法执行操作B是否正常工作。我的量角器设置在真实API的顶部运行,嘲笑数据不是我考虑的选项(如果我选择模拟API响应,这将更容易)。 API不允许我操纵操作A的创建/更新日期,因此我测试此场景的选项是操纵底层数据库或在测试时将浏览器推到下个月。假设我想采用浏览器方法,如何使用量角器来实现这一点?一旦我有了一种控制浏览器时

我的用例是,我有一个UI,它可以阻止操作B,除非操作a在上一个日历月发生(会计生命周期疯狂-无所谓)

我正在编写一个测试来验证操作B是否正常工作,但除非上个月发生了操作a,否则我无法执行操作B是否正常工作。我的量角器设置在真实API的顶部运行,嘲笑数据不是我考虑的选项(如果我选择模拟API响应,这将更容易)。
API不允许我操纵操作A的创建/更新日期,因此我测试此场景的选项是操纵底层数据库或在测试时将浏览器推到下个月。假设我想采用浏览器方法,如何使用量角器来实现这一点?

一旦我有了一种控制浏览器时间的机制,那么我选择的解决方案就是开始一个场景,执行操作a,将浏览器时间提前到未来一个月,然后执行操作B

这涉及到使用量角器
browser.executeScript
在浏览器上下文中运行JS,并使用模块覆盖JS日期对象

这是密码

此代码正在使用:

  • 角度:1.5.10
  • 量角器:5.1.2
  • 黄瓜js:1.3.3
  • timeshift js:1.0.1
我可以写这样的场景:

Feature: Travelling in time

  Scenario: Scenario that manipulates time
    When I view some page
    And I check what time it is
    And I do operation A
    And I advance the browser by 1 days
    And I check what time it is
    Then I can do operation B

  Scenario: Scenario Double Check that the next scenario gets the correct time
    When I view the list of maintenance requests
    And I check what time it is
下面是实现的步骤。这里没有具体的内容,因此应该很容易适应基于茉莉花或摩卡的描述/it框架:

const timeShiftLibraryString = fs.readFileSync(`path/to/node_modules/timeshift-js/timeshift.js`, 'utf-8')

module.exports = function () {

  this.When(/I advance the browser by (-?[0-9]+) (day|month)s?$/, function (offset, unit) {
    const now = moment()
    const future = moment().add(offset, unit)
    const amountOfMillisecondsToAdvanceBrowser = (future.unix() - now.unix()) * 1000
    const tolerance = 15 * 1000

    const advanceTime = function (futureOffsetInMilliseconds, timeShiftLibraryString) {
      // these two lines are only necessary because I dont want Timeshift in my production code, only during test
      const timeshiftLibrary = new Function(timeShiftLibraryString)
      timeshiftLibrary.call(window)

      Date = window.TimeShift.Date
      window.TimeShift.setTime(Date.now() + futureOffsetInMilliseconds)
      return Date.now()
    }

    return browser.executeScript(advanceTime, amountOfMillisecondsToAdvanceBrowser, timeShiftLibraryString).then((browserTime) => {
      const expectedTime = Date.now() + amountOfMillisecondsToAdvanceBrowser - tolerance
      this.logger.debug(`Time manipulation complete: browserTime = ${moment(browserTime)}`)
      if (browserTime >= expectedTime) {
        return Promise.resolve(browserTime)
      }

      return Promise.reject(new Error(`advanceTime did not work: reported browserTime: ${browserTime}. Expected Time: ${expectedTime}`))
    })
  })

  this.When(/I check what time it is/, function () {
    const whatTimeIsItInTheBrowser = function () {
      return Date.now()
    }
     return browser.executeScript(whatTimeIsItInTheBrowser).then((browserTime) => {
      console.log(`Browser Time = ${moment(browserTime)}`)
    })
  })
}
考虑事项:

  • 棘手的部分是序列化timeshift js库。我不想把它和我的应用打包在一起,所以这意味着我必须在测试期间按需注入它
  • 除非您明确地使用
  • 在至少完成一个页面获取之前,您无法操纵浏览器时间,浏览器需要先加载一些HTML和JS,然后才能在浏览器JS上下文中操纵日期

一旦我有了操纵浏览器时间的机制,那么我选择的解决方案就是开始一个场景,执行操作a,将浏览器时间提前到未来一个月,然后执行操作B

这涉及到使用量角器
browser.executeScript
在浏览器上下文中运行JS,并使用模块覆盖JS日期对象

这是密码

此代码正在使用:

  • 角度:1.5.10
  • 量角器:5.1.2
  • 黄瓜js:1.3.3
  • timeshift js:1.0.1
我可以写这样的场景:

Feature: Travelling in time

  Scenario: Scenario that manipulates time
    When I view some page
    And I check what time it is
    And I do operation A
    And I advance the browser by 1 days
    And I check what time it is
    Then I can do operation B

  Scenario: Scenario Double Check that the next scenario gets the correct time
    When I view the list of maintenance requests
    And I check what time it is
下面是实现的步骤。这里没有具体的内容,因此应该很容易适应基于茉莉花或摩卡的描述/it框架:

const timeShiftLibraryString = fs.readFileSync(`path/to/node_modules/timeshift-js/timeshift.js`, 'utf-8')

module.exports = function () {

  this.When(/I advance the browser by (-?[0-9]+) (day|month)s?$/, function (offset, unit) {
    const now = moment()
    const future = moment().add(offset, unit)
    const amountOfMillisecondsToAdvanceBrowser = (future.unix() - now.unix()) * 1000
    const tolerance = 15 * 1000

    const advanceTime = function (futureOffsetInMilliseconds, timeShiftLibraryString) {
      // these two lines are only necessary because I dont want Timeshift in my production code, only during test
      const timeshiftLibrary = new Function(timeShiftLibraryString)
      timeshiftLibrary.call(window)

      Date = window.TimeShift.Date
      window.TimeShift.setTime(Date.now() + futureOffsetInMilliseconds)
      return Date.now()
    }

    return browser.executeScript(advanceTime, amountOfMillisecondsToAdvanceBrowser, timeShiftLibraryString).then((browserTime) => {
      const expectedTime = Date.now() + amountOfMillisecondsToAdvanceBrowser - tolerance
      this.logger.debug(`Time manipulation complete: browserTime = ${moment(browserTime)}`)
      if (browserTime >= expectedTime) {
        return Promise.resolve(browserTime)
      }

      return Promise.reject(new Error(`advanceTime did not work: reported browserTime: ${browserTime}. Expected Time: ${expectedTime}`))
    })
  })

  this.When(/I check what time it is/, function () {
    const whatTimeIsItInTheBrowser = function () {
      return Date.now()
    }
     return browser.executeScript(whatTimeIsItInTheBrowser).then((browserTime) => {
      console.log(`Browser Time = ${moment(browserTime)}`)
    })
  })
}
考虑事项:

  • 棘手的部分是序列化timeshift js库。我不想把它和我的应用打包在一起,所以这意味着我必须在测试期间按需注入它
  • 除非您明确地使用
  • 在至少完成一个页面获取之前,您无法操纵浏览器时间,浏览器需要先加载一些HTML和JS,然后才能在浏览器JS上下文中操纵日期