How to load an Aurelia plugin in Karma

匿名 (未验证) 提交于 2019-12-03 00:56:02

问题:

I've this ViewModel which is a login confirmation page viewmodel:

src/pages/confirm.ts

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); 

I want to test it by unit test using aurelia-cli, I wrote this specs:

test/pages/confirm.spec.ts

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');     }) }); 

When I launch au test I get this error :

Chrome 53.0.2785 (Windows 7 0.0.0) ERROR Uncaught Error: Did you forget to add ".plugin('aurelia-validation)" to your main.js? at C:/Users/olefebvre/Source/Repos/chatle.aurelia/wwwroot/scripts/app-bundle.js:2616

How to fix it ?

The full project is on github at https://github.com/aguacongas/chatle.aurelia

UPDATE

I tried to workaround by put the validation in a custom element (and because I need it on an other page)
My component user-name code is :

user-name.html

<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> 

user-name.ts

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); 

the component spec is:

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();   }); }); 

when I run au test I receive this warning and the component is not created

WARN: '%cUnhandled rejection Error: Did you forget to add ".plugin('aurelia-validation)" to your main.js? at FluentEnsure.assertInitialized (http://localhost:9876/base/wwwroot/scripts/app-bundle.js?f3fa3f9ce9b587af8455ab05a0d491f872123546:9:197927) at FluentEnsure.ensure (http://localhost:9876/base/wwwroot/scripts/app-bundle.js?f3fa3f9ce9b587af8455ab05a0d491f872123546:9:196845) at Function.ValidationRules.ensure (http://localhost:9876/base/wwwroot/scripts/app-bundle.js?f3fa3f9ce9b587af8455ab05a0d491f872123546:9:198743) at Object. (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) at Object.check (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3774:12) at Object.enable (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3779:58) at Object.enable (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3783:433) at Object. (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3778:436) at http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3763:140 at y (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3762:207) at Object.enable (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3777:469) at Object.init (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3772:154) at http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?8e5718043dfbefd1c3ad0ea29315a48c1ff7a645:3782:308

UPDATE 2

Based on Matthew James Davis answer, I rewrote the spec:

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();   }); }); 

but now I get this error on load module :

WARN: '%cUnhandled rejection Error: Unable to parse accessor function: function (c){__cov_YrDLEqGJfOMLMH3Hdk8_ZA.f['231']++;__cov_YrDLEqGJfOMLMH3Hdk8_ZA.s['724']++;return c.userName;} at ValidationParser.getAccessorExpression (http://localhost:9876/base/wwwroot/scripts/app-bundle.js?4e630e49e067afd65b1f5906dc4064c434c5e5df:9:177914) at ValidationParser.parseProperty (http://localhost:9876/base/wwwroot/scripts/app-bundle.js?4e630e49e067afd65b1f5906dc4064c434c5e5df:9:178586) at FluentEnsure.ensure (http://localhost:9876/base/wwwroot/scripts/app-bundle.js?4e630e49e067afd65b1f5906dc4064c434c5e5df:9:196210) at Function.ValidationRules.ensure (http://localhost:9876/base/wwwroot/scripts/app-bundle.js?4e630e49e067afd65b1f5906dc4064c434c5e5df:9:197995) at Object. (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) at Object.check (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3774:12) at Object.enable (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3779:58) at Object.enable (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3783:433) at Object. (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3778:436) at http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3763:140 at y (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3762:207) at Object.enable (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3777:469) at Object.init (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3772:154) at http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:3782:308 From previous event: at DefaultLoader.loadModule (http://localhost:9876/base/wwwroot/scripts/vendor-bundle.js?89c5527ca11655b8716186a7a911ca39c4069f47:11444:14)

UPDATE 3

Ok, the error is throw only when I cover app-bundle.js in karma, if I comment it the parser error is not throwed :

preprocessors: {   [project.unitTestRunner.source]: [project.transpiler.id],   //[appBundle]: ['coverage'] }, 

But the value is not bound to the input field

回答1:

Use a custom bootstrap function

The code you're using uses the default bootstrapper, which loads a default aurelia configuration. Instead, you need to use a custom bootstrapper that matches your main.js. Try this:

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();     });   }); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!