Skip to main content
Cypress应用

clock

cy.clock() 覆盖与时间相关的原生全局函数,使其可以通过 cy.tick() 或返回的 clock 对象进行同步控制。这包括控制以下函数:

  • setTimeout
  • clearTimeout
  • setInterval
  • clearInterval
  • Date 对象

时钟从 Unix 纪元(时间戳为 0)开始。这意味着当你在应用中实例化 new Date 时,它将显示 1970 年 1 月 1 日 的时间。

语法

cy.clock()
cy.clock(now)
cy.clock(now, functionNames)
cy.clock(options)
cy.clock(now, options)
cy.clock(now, functionNames, options)

用法

正确用法

cy.clock()

参数

now (number)

指定时钟起始时间的时间戳。

functionNames (Array)

时钟应覆盖的原生函数名称。

options (Object)

传入一个选项对象以更改 cy.clock() 的默认行为。

选项默认值描述
logtrue命令日志 中显示该命令

生成结果 了解主题管理

cy.clock() 返回一个包含以下方法的 clock 对象:

  • clock.tick(milliseconds)

    将时钟向前移动指定的 milliseconds 毫秒。受影响的计时器将被触发。

  • clock.restore()

    恢复所有被覆盖的原生函数。此操作会在测试之间自动调用,通常无需手动执行。

  • clock.setSystemTime(now)

    将系统时间更改为新的 now 时间。now 可以是时间戳、日期对象,或不传参(默认为 0)。不会触发任何计时器,也不会改变它们剩余的触发时间。

你也可以在 .then() 回调中通过 this.clock 访问 clock 对象。

示例

无参数

创建一个时钟并用它触发 setInterval

// 你的应用代码
let seconds = 0

setInterval(() => {
$('#seconds-elapsed').text(++seconds + ' seconds')
}, 1000)
cy.clock()
cy.visit('/index.html')
cy.tick(1000)
cy.get('#seconds-elapsed').should('have.text', '1 seconds')
cy.tick(1000)
cy.get('#seconds-elapsed').should('have.text', '2 seconds')

访问时钟对象以同步移动时间

大多数情况下,使用 cy.tick() 移动时间更为方便,但你也可以使用 cy.clock() 返回的 clock 对象。

cy.clock().then((clock) => {
clock.tick(1000)
})

如果需要,你可以在链式调用中再次调用 cy.clock() 来实现这一目的。

cy.clock()
cy.get('input').type('Jane Lane')
cy.clock().then((clock) => {
clock.tick(1000)
})

时钟对象也可以通过 this.clock 在任何 .then() 回调中访问。

cy.clock()
cy.get('form').then(($form) => {
this.clock.tick(1000)
// 对 $form 进行某些操作...
})

访问时钟对象以恢复原生函数

通常不需要手动恢复 cy.clock() 覆盖的原生函数,因为这会自动在测试之间完成。但如果需要,可以通过返回的 clock 对象的 .restore() 方法实现。

cy.clock().then((clock) => {
clock.restore()
})

或通过 this.clock

cy.clock()
cy.get('.timer').then(($timer) => {
this.clock.restore()
// 对 $timer 进行某些操作...
})

Now 参数

指定起始时间戳

const now = new Date(2021, 3, 14) // 月份从 0 开始

cy.clock(now)
cy.visit('/index.html')
cy.get('#date').should('have.value', '04/14/2021')

函数名参数

指定要覆盖的函数

以下示例仅覆盖 setTimeoutclearTimeout,其他时间相关函数保持不变。

cy.clock(null, ['setTimeout', 'clearTimeout'])

注意,要覆盖当前日期时间必须显式指定 Date。以下示例仅影响当前日期时间而不影响已计划的计时器。

cy.clock(Date.UTC(2018, 10, 30), ['Date'])

结合 cy.clock()cy.tick() 使用

恢复时钟

你可以恢复时钟,让应用正常继续运行而不操纵与时间相关的原生全局函数。此操作会在测试之间自动调用。

cy.clock()
cy.visit('http://localhost:3333')
cy.get('#search').type('Acme Company')
cy.tick(1000)
// 更多测试代码...

// 恢复时钟
cy.clock().then((clock) => {
clock.restore()
})
// 更多测试代码...

你也可以使用 .invoke() 调用 restore 函数来恢复。

cy.clock().invoke('restore')

更改当前系统时间

以下示例测试计时器在运行一小时后是否仍然正常显示,而无需触发一小时的 setIntervalrequestAnimationFrame 计时器,避免 CPU 过载。

cy.clock(0)
cy.visit('http://localhost:3333')
cy.clock().then((clock) => {
clock.setSystemTime(60 * 60 * 1000 - 60);
// setSystemTime 不会触发任何计时器,所以我们用 tick 触发最后一帧的回调来更新时间显示
clock.tick(60);
})
cy.get('#timer').should(...) // 断言它是否适应屏幕等
// 更多测试代码...

你也可以使用 .invoke() 调用 setSystemTime 函数来更改系统时间。

cy.clock().invoke('setSystemTime', 60 * 60 * 1000)

注意事项

iframes

不支持 iframes

注意 cy.clock() 仅适用于网页的 top 窗口,不会覆盖页面中任何 iframe 的时间函数。

行为

cy.mount() 前的时钟行为

在 Cypress 组件测试中使用 cy.mount() 命令会渲染你的组件,但不会影响页面或 window 对象的行为。这意味着你可以在调用 cy.clock() 后直接 mount,以测试组件对时钟对象更改的反应。

cy.visit() 前的时钟行为

如果在使用 cy.visit() 访问页面之前调用 cy.clock(),页面的原生全局函数将在窗口加载时被覆盖,早于任何应用代码运行。因此即使 setTimeout 在页面加载时调用,仍然可以通过 cy.tick() 控制。这也适用于测试过程中被测页面被重新加载或更改的情况。

规则

要求 了解命令链

  • cy.clock() 需要链式调用 cy

断言 了解断言

  • cy.clock() 是一个实用命令。
  • cy.clock() 不会运行断言。断言会直接通过,就像该命令不存在一样。

超时设置 了解超时机制

  • cy.clock() 不会超时。

命令日志

创建一个时钟并将其移动 1 秒

cy.clock()
cy.tick(1000)

以上命令将在命令日志中显示为:

命令日志中的 clock

点击命令日志中的 clock 命令时,控制台会输出以下内容:

console.log clock 命令

历史

版本变更
10.7.0在返回的 clock 对象中添加了 setSystemTime 方法

另请参阅