Как вернуть размеры документа в Cypress для использования в тесте позже - PullRequest
2 голосов
/ 29 апреля 2019

У меня есть функция в Cypress support / index.js, которая предназначена для получения размеров cy.document outerWidth и outerHeight, а затем возвращает их для будущего использования в тесте.Моя проблема в том, что когда тест запускается и значения сравниваются с другими, утверждение утверждает, что значения 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
}

И он вызывается с помощью пользовательской команды,где subject - это prevSubject, а элементом является строка "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);
})

Ответы [ 2 ]

3 голосов
/ 30 апреля 2019

Как сказал @ NoriSte , команды cy являются асинхронными, поэтому вы не можете смешивать их с кодом синхронизации.

То, что вы хотите сделать, выглядит примерно так:

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

В любом случае, чтобы ответить на исходный вопрос (в заголовке), есть пара шаблонов, которые я использую для хранения значения для последующего использования в кипарисе:

  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 голосов
/ 30 апреля 2019

Почему в вашей функции getViewport есть синхронный возврат? Я говорю о последних return viewport

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

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

при этом весь код cy.document().then((doc) и т. Д. Бесполезен.

Я не знаю, в этом ли проблема, но я не могу запустить ваш код локально, потому что он пропускает много функций. Не могли бы вы поделиться «рабочим» репозиторием GitHub, чтобы провести еще несколько тестов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...