我有一个ViewModel,它是一个登录确认页面viewmodel:
import { autoinject } from 'aurelia-framework';
import { Router, NavigationInstruction } from 'aurelia-router';
import { ValidationControllerFactory, ValidationController, ValidationRules } from 'aurelia-validation';
import { LoginService } from '../services/login.service';
import { Settings } from '../config/settings';
import { State } from '../services/state';
import { Helpers } from '../services/helpers';
@autoinject
export class Confirm {
userName: string;
error: Error;
controller: ValidationController;
provider: string;
constructor(public service: LoginService,
private router: Router,
private state: State,
private helpers: Helpers,
controllerFactory: ValidationControllerFactory) {
this.controller = controllerFactory.createForCurrentScope();
this.provider = this.helpers.getUrlParameter('p');
this.userName = this.helpers.getUrlParameter('u');
window.history.replaceState(null, null, '/');
}
confirm() {
this.controller.validate()
.then(() => {
this.service.confirm(this.userName)
.then(() => {
this.router.navigateToRoute('home');
})
.catch((e: Error) => {
if (e.name === 'NullInfo') {
this.router.navigateToRoute('login');
} else {
this.error = e;
}
});
})
.catch(e => this.error = e);
}
}
ValidationRules
.ensure((c: Confirm) => c.userName)
.satisfies((value, obj) => obj.service.exists(value))
.withMessage('This user name already exists, please choose another one')
.on(Confirm);
我想使用 aurelia-cli 进行单元测试,我写了这个规格:
import { Router, NavigationInstruction } from 'aurelia-router';
import { Confirm } from '../../../src/pages/confirm';
import { LoginService } from '../../../src/services/login.service';
import { Settings } from '../../../src/config/settings';
import { State } from '../../../src/services/state';
import { Helpers } from '../../../src/services/helpers';
describe('confirm page spec', () => {
let service: LoginService;
let router: Router;
let state: State;
let helpers: Helpers;
let controllerFactory;
let userName;
let promise;
let resolveCallback;
let rejectCallback;
beforeEach(() => {
// mock Promise
promise = {
then: r => {
resolveCallback = r;
return {
catch: e => {
rejectCallback = e;
}
}
}
};
// mock LoginService
service = {
confirm: u => {
userName = u;
return promise;
}
} as LoginService;
// mock Router
router = {
navigateToRoute: r => { }
} as Router;
state = new State();
helpers = new Helpers(state);
spyOn(helpers, 'getUrlParameter')
// mock controllerFactory
controllerFactory = {
createForCurrentScope: () => { }
};
spyOn(controllerFactory, 'createForCurrentScope')
.and.returnValue({
validate: () => {
return promise;
}
});
});
it('constructor should get url paratemeters', () => {
// prepare
spyOn(helpers, 'getUrlParameter');
// act
let page = new Confirm(service, router, state, helpers, controllerFactory);
// verify
expect(helpers.getUrlParameter).toHaveBeenCalledWith('p');
expect(helpers.getUrlParameter).toHaveBeenCalledWith('u');
})
});
当我启动 au test 时,我收到此错误:
Chrome 53.0.2785(Windows 7 0.0.0)错误未捕获错误:你有没有? 忘记将“.plugin('aurelia-validation)”添加到你的main.js中?在 C:/Users/olefebvre/Source/Repos/chatle.aurelia/wwwroot/scripts/app-bundle.js:2616
如何解决?
完整项目位于https://github.com/aguacongas/chatle.aurelia
的github上我尝试通过将验证放在自定义元素中来解决(因为我需要在另一个页面上)
我的组件用户名代码是:
<template>
<div validation-errors.bind="userNameErrors" class.bind="userNameErrors.length ? 'has-error' : ''">
<input class="form-control" name="UserName" value.bind="userName & validate" />
<span class="help-block" repeat.for="errorInfo of userNameErrors">
${errorInfo.error.message}
<span>
</div>
</template>
import { autoinject, bindable, bindingMode } from 'aurelia-framework';
import { ValidationControllerFactory, ValidationController, ValidationRules } from 'aurelia-validation';
import { LoginService } from '../services/login.service';
@autoinject
export class UserName {
@bindable({ defaultBindingMode: bindingMode.twoWay })
userName: string;
controller: ValidationController;
constructor(private service: LoginService, controllerFactory: ValidationControllerFactory) {
this.controller = controllerFactory.createForCurrentScope();
}
userNameAvailable(value: string) {
return new Promise<boolean>(resolve => {
this.service.exists(value)
.then(r => resolve(!r));
})
}
}
ValidationRules
.ensure((c: UserName) => c.userName)
.satisfies((value, obj) => obj.userNameAvailable(value))
.withMessage('This user name already exists, please choose another one')
.on(UserName);
组件规范是:
import {StageComponent} from 'aurelia-testing';
import {bootstrap} from 'aurelia-bootstrapper';
describe('user-name component specs', () => {
let component;
beforeEach(() => {
component = StageComponent
.withResources('components/user-name')
.inView('<user-name userName.bind="firstName"></user-namet>')
.boundTo({ firstName: 'Test' });
});
it('should render first name', done => {
component.create(bootstrap).then(() => {
const nameElement = document.querySelector('.form-control');
expect(nameElement.attributes['value']).toBe('Test');
done();
});
});
afterEach(() => {
component.dispose();
});
});
当我运行au测试时,我收到此警告并且未创建组件
警告:'%c未处理拒绝错误:您是否忘了添加 “.plugin('aurelia-validation)”到你的main.js? 在FluentEnsure.assertInitialized(http://localhost:9876/base/wwwroot/scripts/app-bundle.js?f3fa3f9ce9b587af8455ab05a0d491f872123546:9:197927) 在FluentEnsure.ensure(http://localhost:9876/base/wwwroot/scripts/app-bundle.js?f3fa3f9ce9b587af8455ab05a0d491f872123546:9:196845) 在Function.ValidationRules.ensure(http://localhost:9876/base/wwwroot/scripts/app-bundle.js?f3fa3f9ce9b587af8455ab05a0d491f872123546:9:198743) 在对象。 (http://localhost:9876/base/wwwroot/scripts/app-bundle.js?f3fa3f9ce9b587af8455ab05a0d491f872123546:9:95049) at Object.execCb(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3785:299) 在Object.check(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3774:12) 在Object.enable(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3779:58) 在Object.enable(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3783:433) 在对象。 (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3778:436) 在http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3763:140 在y(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3762:207) 在Object.enable(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3777:469) 在Object.init(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3772:154) 在http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3782:308
根据Matthew James Davis的回答,我重新编写了规范:
import { Aurelia } from 'aurelia-framework';
import { StageComponent } from 'aurelia-testing';
import { bootstrap } from 'aurelia-bootstrapper';
describe('user-name component specs', () => {
let component;
beforeEach(() => {
component = StageComponent
.withResources('components/user-name')
.inView('<user-name userName.bind="firstName"></user-namet>')
.boundTo({ firstName: 'Test' });
// bootstrap function call the component configure function with an Aurelia instance
component.configure = (aurelia:Aurelia) => {
aurelia.use
.standardConfiguration()
.plugin('aurelia-validation');
}
});
it('should render user name', done => {
component.create(bootstrap).then(() => {
const nameElement = document.querySelector('.form-control');
expect(nameElement['value']).toBe('Test');
done();
});
});
afterEach(() => {
component.dispose();
});
});
但现在我在加载模块上出现了这个错误:
警告:'%cUnhandled rejection错误:无法解析访问者函数: 功能 (C){__ cov_YrDLEqGJfOMLMH3Hdk8_ZA.f [ '231'] ++; __ cov_YrDLEqGJfOMLMH3Hdk8_ZA.s [ '724'] ++;返回 c.userName;} 在ValidationParser.getAccessorExpression(http://localhost:9876/base/wwwroot/scripts/app-bundle.js?4e630e49e067afd65b1f5906dc4064c434c5e5df:9:177914) 在ValidationParser.parseProperty(http://localhost:9876/base/wwwroot/scripts/app-bundle.js?4e630e49e067afd65b1f5906dc4064c434c5e5df:9:178586) 在FluentEnsure.ensure(http://localhost:9876/base/wwwroot/scripts/app-bundle.js?4e630e49e067afd65b1f5906dc4064c434c5e5df:9:196210) 在Function.ValidationRules.ensure(http://localhost:9876/base/wwwroot/scripts/app-bundle.js?4e630e49e067afd65b1f5906dc4064c434c5e5df:9:197995) 在对象。 (http://localhost:9876/base/wwwroot/scripts/app-bundle.js?4e630e49e067afd65b1f5906dc4064c434c5e5df:9:94307) at Object.execCb(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3785:299) 在Object.check(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3774:12) 在Object.enable(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3779:58) 在Object.enable(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3783:433) 在对象。 (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3778:436) 在http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3763:140 在y(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3762:207) 在Object.enable(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3777:469) 在Object.init(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3772:154) 在http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3782:308 从以前的事件: 在DefaultLoader.loadModule(http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:11444:14)
好的,只有当我在业力中覆盖app-bundle.js
时才会抛出错误,如果我对其进行评论,则不会抛出解析器错误:
preprocessors: {
[project.unitTestRunner.source]: [project.transpiler.id],
//[appBundle]: ['coverage']
},
但该值未绑定到输入字段
答案 0 :(得分:2)
您正在使用的代码使用默认的bootstrapper,它会加载默认的aurelia配置。相反,您需要使用与main.js
匹配的自定义引导程序。试试这个:
it('should render first name', done => {
component
.create(
bootstrap((aurelia) => {
aurelia.use
.standardConfiguration()
.plugin('aurelia-validation');
})
).then(() => {
const nameElement = document.querySelector('.form-control');
expect(nameElement.attributes['value']).toBe('Test');
done();
});
});