如何在赛普拉斯返回文档尺寸以供以后测试

问题描述 投票:1回答:2

我在赛普拉斯支持/ index.js中有一个函数,用于获取cy.document outerWidthouterHeight的尺寸,然后将它们返回以供将来在测试中使用。我的问题是,当测试运行并将值与其他值进行比较时,断言表示值为NaN。我通过控制台检查了断言点的值并且它是空的,所以我一定做错了,我只是不确定是什么。我的功能如下,感谢任何帮助,谢谢。

function getViewport() {
  var viewport = {}
  cy.document().then((doc) => {
    let width = Cypress.$(doc).outerWidth()
    let height = Cypress.$(doc).outerHeight()
    viewport['bottom'] = height
    viewport['height'] = height
    viewport['left'] = 0
    viewport['right'] = width
    viewport['top'] = 0
    viewport['width'] = width
    viewport['x'] = 0
    viewport['y'] = 0
  }).then(() => {
    return viewport
  })
  return viewport
}

调用getViewport()的代码是

export const getRect = (obj) => {
  var rect
  if (obj == 'viewport') {
    rect = getViewport()
  } else {
    rect = getElement(obj)
    if (Cypress.config('parseLayoutToInt')) { rect = parseAllToInt(rect) }
  }
  return rect
}

这是由自定义命令调用的,其中subjectprevSubject,元素是字符串“viewport”

Cypress.Commands.add('isInside', { prevSubject: true }, (subject, element, expected) => {
  var minuend, subtrahend, diff
  minuend = getRect(element)
  subtrahend = getRect(subject)
  diff = getRectDiff(minuend, subtrahend, expected);
  expect(diff).to.deep.equal(expected);
})
cypress
2个回答
2
投票

@NoriSte说的那​​样,cy命令是异步的,因此你不能将它们与同步代码混合在一起。

你想做的是:

function getViewport() {
  return cy.document().then( doc => {
    rect = /* do something synchronous */
    return rect;
  });
}

无论如何,为了回答原始问题(在标题中),我使用了几种模式来存储值以供以后在cypress中使用:

  1. then回调中包装下一个命令: cy.document().then( doc => { return doc.documentElement.getBoundingClientRect(); }).then( viewportRect => { cy.doSomething(viewportRect); cy.doSomethingElse(); });
  2. 缓存到变量并从入队命令中访问缓存的值: let viewportRect; cy.document().then( doc => { return doc.documentElement.getBoundingClientRect(); }).then( rect => viewportRect = rect ); cy.doSomething(); // this is important -- you need to access the `viewportRect` // asynchronously, else it will be undefined at the time of access // because it's itself assigned asynchronously in the first command'd callback cy.then(() => { doSomething(viewportRect); });

根据你问题中的实际问题(如果我理解正确),我已经找到了一个你可以学习的解决方案:

const getRect = (selector) => {
    if (selector == 'viewport') {
        return cy.document().then( doc => {
            return doc.documentElement.getBoundingClientRect();
        });
    } else if ( typeof selector === 'string' ) {
        return cy.get(selector).then( $elem => {
            return $elem[0].getBoundingClientRect();
        });
    // assume DOM elem
    } else {
        return cy.wrap(selector).then( elem => {
            return Cypress.$(elem)[0].getBoundingClientRect();
        });
    }
};

const isInside = (containerRect, childRect) => {
    if ( !containerRect || !childRect ) return false;
    return (
        childRect.top >= containerRect.top &&
        childRect.bottom <= containerRect.bottom &&
        childRect.left >= containerRect.left &&
        childRect.right <= containerRect.right
    );
};

Cypress.Commands.add('isInside', { prevSubject: true }, (child, container, expected) => {
    return getRect(child).then( childRect => {
        getRect(container).then( containerRect => {
            expect(isInside(containerRect, childRect)).to.equal(expected);
        });
    });
});

describe('test', () => {
    it('test', () => {
        cy.document().then( doc => {
            doc.body.innerHTML = `
                <div class="one"></div>
                <div class="two"></div>
                <style>
                    .one, .two {
                        position: absolute;
                    }
                    .one {
                        background: rgba(255,0,0,0.3);
                        width: 400px;
                        height: 400px;
                    }
                    .two {
                        background: rgba(0,0,255,0.3);
                        width: 200px;
                        height: 200px;
                    }
                </style>
            `;
        });
        cy.get('.two').isInside('.one', true);
        cy.get('.one').isInside('.two', false);
    });

    it('test2', () => {
        cy.document().then( doc => {
            doc.body.innerHTML = `
                <div class="one"></div>
                <div class="two"></div>
                <style>
                    body, html { margin: 0; padding: 0 }
                    .one, .two {
                        position: absolute;
                    }
                    .one {
                        background: rgba(255,0,0,0.3);
                        width: 400px;
                        height: 400px;
                    }
                    .two {
                        background: rgba(0,0,255,0.3);
                        width: 200px;
                        height: 200px;
                        left: 300px;
                    }
                </style>
            `;
        });
        cy.get('.two').isInside('.one', false);
        cy.get('.one').isInside('.two', false);
    });
    it('test3', () => {
        cy.document().then( doc => {
            doc.body.innerHTML = `
                <div class="one"></div>
                <style>
                    body, html { margin: 0; padding: 0 }
                    .one {
                        position: absolute;
                        background: rgba(255,0,0,0.3);
                        width: 400px;
                        height: 400px;
                        left: -100px;
                    }
                </style>
            `;
        });
        cy.get('.one').isInside('viewport', false);
    });
});

0
投票

为什么getViewport函数中存在同步返回?我说的是最后的return viewport

function getViewport() {
  var viewport = {}
  cy.document().then((doc) => {
    ...
  })

  return viewport // <-- ?????
}

这样做,所有cy.document().then((doc)等代码都没用。

我不知道这是不是问题,但我不能在本地运行你的代码,因为它错过了很多功能。你能分享一个“工作”的GitHub仓库进行更多测试吗?

© www.soinside.com 2019 - 2024. All rights reserved.