因此它混合和没有模块的旧angularjs,我决定将所有.ts编译成一个bundle.js文件,因为避免了文件排序问题(当我每个.ts有单个.js文件并将其注入gulp任务时发生的index.html).
我的tsconfig.js:
{ "compileOnSave": true,"compilerOptions": { "noImplicitAny": false,"removeComments": false,"outFile": "./wwwroot/bundle.js","sourceMap": true,"inlineSources": true,"module": "amd","moduleResolution": "node","target": "es5","sourceRoot": "./wwwroot" },"include": [ "wwwroot/app/**/*" ],"exclude": [ "node_modules/**/*","tests/**/*" ] }
测试类的示例:
///<reference path="../models/paymentCondition.model.ts"/> ///<reference path="../../../../../node_modules/@types/angular/index.d.ts"/> 'use strict'; module PaymentCondition { export class ConnectedCustomersListController { name: string; static $inject = ['paymentCondition']; constructor(private paymentCondition: PaymentConditionModel) { this.name = paymentCondition.Name; this.bindData(); } bindData() { // do something } } angular .module('app.paymentConditions') .controller('ConnectedCustomersListController',ConnectedCustomersListController); }
我的模块声明:
///<reference path="../../../../node_modules/@types/angular/index.d.ts"/> 'use strict'; module PaymentCondition { angular.module('app.paymentConditions',['ui.router','ui.bootstrap']); }
我正在将这个模块“注入”主模块文件,该文件已经在javascript-App.module.js中:
(function () { 'use strict'; var module = angular.module('app',[ 'app.paymentCondition','ui.router','ui.bootstrap',]); })();
最后我的测试类:
///<reference path="../../../node_modules/@types/angular/index.d.ts"/> ///<reference path="../../../wwwroot/app/domain/paymentConditions/connectedCustomersList/connectedCustomersList.controller.ts"/> ///<reference path="../../../node_modules/@types/angular-mocks/index.d.ts"/> import { expect } from 'chai'; import "angular-mocks/index"; import * as angular from "angular"; describe("app.paymentConditions.connectedCustomersList",() => { var mock; // inject main module beforeEach(angular.mock.module('app.paymentConditions')); beforeEach(angular.mock.inject(($controller: ng.IControllerService) => { mock = { connectedCustomersListModel: { columnDefinitions() { } },paymentCondition: {},createController(): PaymentCondition.ConnectedCustomersListController { return $controller<PaymentCondition.ConnectedCustomersListController >('ConnectedCustomersListController',{ connectedCustomersListModel: mock.connectedCustomersListModel,}); } }; })); describe("ConnectedCustomersListController",() => { var controller: PaymentCondition.ConnectedCustomersListController; beforeEach(() => { controller = mock.createController(); }); it("should be defined",() => { expect(controller).not.undefined; }); }); });
当我尝试使用命令运行mocha测试时:
./node_modules/.bin/mocha --compilers ts:ts-node/register ./tests/**/*.spec.ts
我有这个例外:
ReferenceError: define is not defined at Object.<anonymous> (C:\Projects\App.Frontend\EasyFrontend\src\EasyFrontend\tests\paymentConditions\connec edCustomersList\connectedCustomersList.controller.spec.ts:5:1) at Module._compile (module.js:643:30) at Module.m._compile (C:\Projects\App.Frontend\EasyFrontend\src\EasyFrontend\node_modules\ts-node\src\index. s:422:23) at Module._extensions..js (module.js:654:10) at Object.require.extensions.(anonymous function) [as .ts] (C:\Projects\App.Frontend\EasyFrontend\src\EasyFr ntend\node_modules\ts-node\src\index.ts:425:12) at Module.load (module.js:556:32) at tryModuleLoad (module.js:499:12) at Function.Module._load (module.js:491:3) at Module.require (module.js:587:17) at require (internal/module.js:11:18) at C:\Projects\App.Frontend\EasyFrontend\src\EasyFrontend\node_modules\mocha\lib\mocha.js:231:27 at Array.forEach (<anonymous>) at Mocha.loadFiles (C:\Projects\App.Frontend\EasyFrontend\src\EasyFrontend\node_modules\mocha\lib\mocha.js:2 8:14) at Mocha.run (C:\Projects\App.Frontend\EasyFrontend\src\EasyFrontend\node_modules\mocha\lib\mocha.js:536:10) at Object.<anonymous> (C:\Projects\App.Frontend\EasyFrontend\src\EasyFrontend\node_modules\mocha\bin\_mocha: 82:18) at Module._compile (module.js:643:30) at Object.Module._extensions..js (module.js:654:10) at Module.load (module.js:556:32) at tryModuleLoad (module.js:499:12) at Function.Module._load (module.js:491:3) at Function.Module.runMain (module.js:684:10) at startup (bootstrap_node.js:187:16) at bootstrap_node.js:608:3 npm ERR! Test Failed. See above for more details.
我知道这是因为我使用amd模块将我的打字稿编译成一个js文件,但我真的不知道如何修复它.或者,如果它无法修复,也许您有一些建议如何将类型脚本“混合”到现有的AngularJs解决方案.
PS.我使用mocha和支持的typescript编译器,因为我不知道如何使用这种组合运行jasmine测试.
我的Index.html:
<!DOCTYPE html> <html> <head ng-controller="AppCtrl"> <Meta charset="utf-8" /> <Meta name="viewport" content="width=device-width,initial-scale=1.0" /> <Meta lang="da" /> <title>{{ Page.title() }}</title> <!-- endbuild --> <!-- inject:css --> <link rel="stylesheet" type="text/less" href="less/site.less" /> <!-- endinject --> <!-- build:remove --> <script src="less/less.js"></script> <!-- endbuild --> <!-- bower:js --> <script src="lib/jquery/dist/jquery.js"></script> <script src="lib/bootstrap/dist/js/bootstrap.js"></script> <script src="lib/angular/angular.js"></script> <script src="lib/toastr/toastr.js"></script> <script src="lib/angular-ui-router/release/angular-ui-router.js"></script> <script src="lib/angular-ui-grid/ui-grid.js"></script> <script src="lib/angular-bootstrap/ui-bootstrap-tpls.js"></script> <script src="lib/sugar/release/sugar-full.development.js"></script> <script src="lib/ng-context-menu/dist/ng-context-menu.js"></script> <script src="lib/ng-messages/angular-messages.js"></script> <script src="lib/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js"></script> <script src="lib/bootstrap-datepicker/dist/locales/bootstrap-datepicker.da.min.js"></script> <script src="lib/angular-ui-tree/dist/angular-ui-tree.js"></script> <script src="lib/angular-sanitize/angular-sanitize.js"></script> <script src="lib/color-hash/dist/color-hash.js"></script> <script src="lib/angular-ui-mask/dist/mask.js"></script> <script src="lib/google-maps-js-marker-clusterer/src/markerclusterer.js"></script> <script src="lib/ngDraggable/ngDraggable.js"></script> <script src="lib/requirejs/require.js"></script> <!-- endbower --> <!-- endbuild --> <!-- build:site_js js/site.min.js --> <!-- inject:app:js -- > <script src="bundle.js"></script> <script src="app/app.module.js"></script> <script src="app/app.route.config.js"></script> <script src="app/app.module.config.js"></script> <script src="app/app.constants.js"></script> <script src="app/app.appCtrl.js"></script> <!-- endinject --> <!-- endbuild --> <!-- endbuild --> <!-- build:remove --> <script src="init.js"></script> <!-- endbuild --> </head> <body> <div class="fluid-container"> <ee-global-context-menu></ee-global-context-menu> <ui-view></ui-view> </div> </body> </html>
解决方法
Hence it hybrid and an old angularjs without modules
你已经声明你没有使用模块,但实际上你是.
您显示的tsconfig.json表示您已配置TypeScript以将代码转换为AMD模块.此外,您的index.html相应地设置,因为您实际上使用的是AMD加载程序,即RequireJS.
所有这一切都很好.您应该使用模块,并且使用AngularJS这样做不仅可行而且容易.
但是,顺便说一句,ts-node采用了你的TypeScript代码,然后自动转换并运行它.执行此操作时,它会从tsconfig.json加载设置,实例化传递这些设置的TypeScript编译器,编译代码,然后将结果传递给Node.js以便执行.
NodeJS不是AMD模块环境.它不支持AMD,也不提供定义功能.
有几种有效的方法可以执行测试.
一种选择是对ts节点使用不同的配置,具体来说,告诉它输出CommonJS模块而不是AMD模块.这将产生Node.js理解的输出.
就像是
./node_modules/.bin/mocha --compilers ts:ts-node/register --project tsconfig.tests.json
tsconfig.tests.json的样子
{ "extends": "./tsconfig.json","compilerOptions": { "module": "commonjs","esModuleInterop": true },"include": ["tests/**/*.spec.ts"] }
请记住,AMD和CommonJS模块具有不同的语义,虽然您可能永远不会在测试代码中遇到任何差异,但您的代码将使用不同的加载程序进行测试而不是生产代码.
另一种选择是在节点中使用兼容AMD的加载程序来运行测试.您可以使用mocha的–require选项执行此操作.例如
mocha --require requirejs
备注:
您的代码中存在一些错误,即使它们不是问题的直接原因,它们也应该被解决,它们与模块,路径等有关.
>不要使用///< reference path =“...”/>加载声明文件.编译器会自动选择它们.
>不要使用module关键字在TypeScript代码中创建名称空间.这一点很久就被弃用了,因为它引入了术语混淆.请改用namespace关键字.
>永远不要混合模块语法,从’y’导入x,并且///< reference path =“x.ts”/>实际加载代码.
换句话说,在您的测试中,替换
///<reference path="../../../wwwroot/app/domain/paymentConditions/connectedCustomersList/connectedCustomersList.controller.ts"/>
同
import "../../../wwwroot/app/domain/paymentConditions/connectedCustomersList/connectedCustomersList.controller.ts";
立刻!
在此更改后,您的测试将如下所示
import "../../../wwwroot/app/domain/paymentConditions/connectedCustomersList/connectedCustomersList.controller.ts"; import chai from 'chai'; import "angular-mocks/index"; // just like controller.ts import angular from "angular"; const expect = chai.expect;
这很严重.不要考虑,只是这样做.
>考虑将整个代码库转换为适当的模块. AngularJS可以很好地使用这种方法,它可以降低工具链的整体复杂性,同时使您的系统更好地考虑因素,并且您的代码更易于维护和重用.
这个想法最终会改变
namespace PaymentConditions { angular.module('app.paymentConditions','ui.bootstrap']); }
至
import angular 'angular'; import uiRouter from 'angular-ui-router'; import uiBootstrap from 'angular-ui-bootstrap'; import ConnectedCustomersListController from './connectedCustomersList/connectedCustomersList.controller'; const paymentConditions = angular.module('app.paymentConditions',[ uiRouter,uiBootstrap ]) .controller({ ConnectedCustomersListController }); export default paymentConditions;
和你的控制器一起
export default class ConnectedCustomersListController { static $inject = ['paymentCondition']; name: string; constructor(public paymentCondition: PaymentConditionModel) { this.name = paymentCondition.Name; this.bindData(); } bindData() { // do something } }