有趣的是,这样一个标准组件中的这种标准行为是如此难以测试。
在我的 Ionic React 组件中给出一个 IonRange 元素:
<IonRange
min={0}
max={30}
onIonInput={()=> console.log("changed")}
/>
当我手动测试 IonRange 时,我得到了预期的控制台输出。 然而,当我进行像这样的柏树测试时(几乎是从文档中复制过来的):
cy.get("ion-range")
.as('range')
.invoke('val', 10)
.trigger('change')
我希望在输出中看到日志语句。
实际行为:范围旋钮跳至预期位置,但从未调用
onIonInout
回调。
我还尝试了其他触发器,例如
.trigger('ion-change')
.trigger('input')
.trigger('ion-input')
.trigger('range-change')
.trigger('ionChange')
.trigger('ionInput')
所有这些都会导致相同的行为。
我还尝试使用箭头键来解决问题。 这将是一个非常令人不满意的解决方案,因为它不能推广范围为 0 到 10,000 的情况。我还是尝试了一下:
cy.get("ion-range").type('{rightArrow}') // trows "this is a non-typable element"
范围旋钮跳到中心(奇怪)。
我最终得到的解决方法是:
cy.get("ion-range").click() // clicks in the centre
(@SuchAnIgnorantThingToDo-UKR 也提到过) 然后我期望值 15。但是由于渲染分辨率的差异(即使使用设置的视口),结果在 15 和 16 之间变化。此外,考虑到我们可能想要断言特定值,这个解决方案非常不令人满意)
我回顾了以下内容:
如果您对这个非常琐碎的日常问题有任何想法,请告诉我。
.click()
命令将更改值并触发事件处理程序,但它不如直接设置值那么精确。
cy.window()
.its('console')
.then((console) => {
cy.spy(console, 'log').as('log')
})
cy.get('ion-range')
.click(300,0)
cy.get('@log')
.should('have.been.calledWith', 'changed', 31)
.invoke('getCalls')
.then((calls) => {
// open the DevTools to see the dumped table
console.table(calls)
expect(calls[0].args).to.deep.eq(['changed', 31]) // not exact, a +1 pixel occurs
})
来自
<IonRange onIonChange={({ detail })=> console.log("changed", detail.value)}></IonRange>
IonRange 似乎与您引用的两个链接示例具有不同的内部机制。
那些具有
<input>
底层,但 IonRange 没有。相反,它是一个基于模板的 Web 组件,它以自己的特定方式响应事件。
范围旋钮跳到中心(奇怪)
我得到了与
.click()
相同的结果,但没有指定要单击的坐标。我认为这是因为 .type()
内置了 .click()
。
如果不指定,默认点击位置是元素的中心。
@SuchAnIgnorantThingToDo-UKR 已经非常详细地回答了。
我只是想添加如何测试拖动。你可以这样做:
describe('Components', () => {
it('ion-range', () => {
cy.visit('https://ionicframework.com/docs/usage/v7/range/basic/demo.html?ionic:mode=ios')
cy.get('ion-range').as('slider')
const waitTime = 200
cy.get('@slider') //
.trigger('mouseenter')
.wait(waitTime)
.trigger('mousedown', 100, 0)
.wait(waitTime)
.trigger('mousemove', 150, 1, { force: true })
.wait(waitTime)
.trigger('mousemove', 200, 1, { force: true })
.wait(waitTime)
.trigger('mousemove', 300, 1, { force: true })
.wait(waitTime)
.trigger('mouseup', 300, 1)
})
})
老问题,但您可以使用以下代码触发离子范围的内部机制:
cy.get('@slider').then(($range) => {
const range = $range[0];
range.dispatchEvent(new CustomEvent("ionInput", { detail: { value: 0 }, bubbles: true }));
range.dispatchEvent(new CustomEvent("ionChange", { detail: { value: 0 }, bubbles: true }));
});
并将值设置为您喜欢的值