带有 SystemJS 的赛普拉斯
Cypress with SystemJS
我正在尝试创建一些基本测试来试用新的 Cypress 库。在我的测试中,我有 cy.visit('http://mywebsite.com');
正在加载一个使用 SystemJS 的 AngularJS 应用程序。
如果我对 Cypress 的理解正确,我就不必做任何其他事情,它会确保在 运行 其他任何事情之前加载页面。然而,这似乎不起作用,因为页面已加载,但 SystemJS 仍在加载模块。
如何在不使用 cy.wait(5000)
的情况下让 Cypress 等待所有 SystemJS 模块加载,然后再进行 运行 测试?
编辑
感谢 Dwelle,这是适合我的解决方案。我将初始 System.import 包装在一个承诺中,一旦 AngularJS 应用程序被引导,该承诺就会得到解决。
window.APP_READY = new Promise(function(resolve, reject) {
System.import('app').then(function(app) {
angular.element(document).ready(function() {
angular.bootstrap(document, ['app']);
resolve();
});
});
});
然后在测试
cy.visit('http://mywebsite.com').its('APP_READY');
不熟悉 SystemJS 或您的应用程序,但如果我们假设您在加载时执行一些异步工作,您可以设置一些全局 属性 指示应用程序是否准备就绪。
// your main.js
let _appReadyResolver;
window.APP_READY = new Promise( resolve => _appReadyResolver = resolve );
// do some async setup
setTimeout(() => {
_appReadyResolver();
});
然后,在你的测试中:
cy.visit("/")
// by default will wait 4sec for APP_READY prop to exist on
// window object (unfortunately I don't know how to increase timeouts
// of `cy.its` command)
// After that, it will wait indefinitely for your promise to resolve
.its("APP_READY")
话虽这么说 --- 如果您没有在您的应用程序中进行任何异步设置,但 main.js
只是被异步加载并且可能需要超过 4 秒的时间,那么我会这样做:
// index.js
<script>
SystemJS.import('/js/main.js');
window.APP_READY = new Promise( resolve => {
let interval = setInterval(() => {
if ( window.MAIN_READY ) {
resolve();
clearTimeout(interval);
};
}, 100 );
</script>
// main.js
window.MAIN_READY = true;
您需要从生产构建中删除 APP_READY
逻辑。
理论上你也可以用纯Cypress的方式解决
如果您的页面发出任何指示您的应用已准备就绪的请求,您可以让 Cypress 等待它完成后再继续。您可能会发现这比 APP_READY 变通方法更干净。不过,这只是一种意见,因为如果没有您可以信任的请求表明您的应用已准备就绪,这种方法将会失败。
cy.server();
cy.route('**/api/getData').as('getData');
cy.visit('/home');
cy.wait('@getData');
我正在尝试创建一些基本测试来试用新的 Cypress 库。在我的测试中,我有 cy.visit('http://mywebsite.com');
正在加载一个使用 SystemJS 的 AngularJS 应用程序。
如果我对 Cypress 的理解正确,我就不必做任何其他事情,它会确保在 运行 其他任何事情之前加载页面。然而,这似乎不起作用,因为页面已加载,但 SystemJS 仍在加载模块。
如何在不使用 cy.wait(5000)
的情况下让 Cypress 等待所有 SystemJS 模块加载,然后再进行 运行 测试?
编辑
感谢 Dwelle,这是适合我的解决方案。我将初始 System.import 包装在一个承诺中,一旦 AngularJS 应用程序被引导,该承诺就会得到解决。
window.APP_READY = new Promise(function(resolve, reject) {
System.import('app').then(function(app) {
angular.element(document).ready(function() {
angular.bootstrap(document, ['app']);
resolve();
});
});
});
然后在测试
cy.visit('http://mywebsite.com').its('APP_READY');
不熟悉 SystemJS 或您的应用程序,但如果我们假设您在加载时执行一些异步工作,您可以设置一些全局 属性 指示应用程序是否准备就绪。
// your main.js
let _appReadyResolver;
window.APP_READY = new Promise( resolve => _appReadyResolver = resolve );
// do some async setup
setTimeout(() => {
_appReadyResolver();
});
然后,在你的测试中:
cy.visit("/")
// by default will wait 4sec for APP_READY prop to exist on
// window object (unfortunately I don't know how to increase timeouts
// of `cy.its` command)
// After that, it will wait indefinitely for your promise to resolve
.its("APP_READY")
话虽这么说 --- 如果您没有在您的应用程序中进行任何异步设置,但 main.js
只是被异步加载并且可能需要超过 4 秒的时间,那么我会这样做:
// index.js
<script>
SystemJS.import('/js/main.js');
window.APP_READY = new Promise( resolve => {
let interval = setInterval(() => {
if ( window.MAIN_READY ) {
resolve();
clearTimeout(interval);
};
}, 100 );
</script>
// main.js
window.MAIN_READY = true;
您需要从生产构建中删除 APP_READY
逻辑。
理论上你也可以用纯Cypress的方式解决
如果您的页面发出任何指示您的应用已准备就绪的请求,您可以让 Cypress 等待它完成后再继续。您可能会发现这比 APP_READY 变通方法更干净。不过,这只是一种意见,因为如果没有您可以信任的请求表明您的应用已准备就绪,这种方法将会失败。
cy.server();
cy.route('**/api/getData').as('getData');
cy.visit('/home');
cy.wait('@getData');