最近在为下一个项目做前端技术选型,Angular是必须要用的(BOSS指定,个人感觉也不错,开发效率会很高)。由于需要加载的JS很多,所以打算看看angular和requirejs一起用会怎么样。在git上有一个模板加《angular-requirejs-seed》,这个对angular和requirejs结合有很好的指导。但是他把karma的单元测试js放在项目中了,我更喜欢放在test目录下。
由于为linux下没有截图工具,就手打了。求Linux下好用的截图工具分享。要用karma测试首先使用karma init命令生成测试文件karma.conf.js。
在项目下输入命令karma init
Which testing framework do you want to use? jasmine
Do you want to use Require.js? yes 注意:按上下键就可以选择
Do you want to capture any browsers automatically? Chrome 注意,可以选多个
What is the location of your source and test files? app/**/**/*.js enter键 app/app.js enter键 app/require-config.js enter键 test/**/*Spec.js 这里的路径更加实际项目情况来确定。可以多个路径。
Should any of the files included by the previous patterns be excluded ? enter键跳过。
Do you wanna generate a bootstrap file for RequireJS? yes
Do you want karma to watch all the files and run the tests on change? yes
在这些步骤完成之后,会在根目录生成叫做karma.conf.js和test-main.js的两个文件。由于习惯,我喜欢将karma.conf.js放入test目录下,这时需要将karma.conf.js的basePath改为"..";这里的test-main.js文件就是karma在测试的代替app下的require-config.js的文件,所以test-main.js文件和require-config的内容几乎完全一样,只是由于位置不一样,所以在test-main中增加一个baseUrl.
1 var allTestFiles = []; 2 var TEST_REGEXP = /(spec|test).js$/i; 3 4 Object.keys(window.__karma__.files).forEach(function(file) { 5 if (TEST_REGEXP.test(file)) { 6 // Normalize paths to RequireJS module names. 7 allTestFiles.push(file); 8 } 9 }); 10 11 require.config({ 12 // Karma serves files under /base, which is the basePath from your config file 13 baseUrl: '/base/app', 14 paths: { 15 angular: 'bower_components/angular/angular', 16 angularRoute: 'bower_components/angular-route/angular-route', 17 angularMocks: 'bower_components/angular-mocks/angular-mocks', 18 angularCookies:'bower_components/angular-cookies/angular-cookies', 19 angularResource:'bower_components/angular-resource/angular-resource' 20 }, 21 shim: { 22 'angular' : {'exports' : 'angular'}, 23 'angularRoute': ['angular'], 24 'angularCookies': ['angular'], 25 'angularResource': ['angular'], 26 'angularMocks': { 27 deps:['angular'], 28 'exports':'angular.mock' 29 } 30 }, 31 priority: [ 32 "angular" 33 ], 34 // dynamically load all test files 35 deps: allTestFiles, 36 37 // we have to kickoff jasmine, as it is asynchronous 38 callback: window.__karma__.start 39 }); 40 require([ 41 'angular', 42 'app' 43 ], function(angular, app) { 44 var $html = angular.element(document.getElementsByTagName('html')[0]); 45 angular.element().ready(function() { 46 // bootstrap the app manually 47 angular.bootstrap(document, ['cxriaApp']); 48 }); 49 } 50 );
1 'use strict'; 2 3 if(window.__karma__) { 4 var allTestFiles = []; 5 var TEST_REGEXP = /spec.js$/; 6 7 var pathToModule = function(path) { 8 return path.replace(/^/base/app//, '').replace(/.js$/, ''); 9 }; 10 11 Object.keys(window.__karma__.files).forEach(function(file) { 12 if (TEST_REGEXP.test(file)) { 13 // Normalize paths to RequireJS module names. 14 allTestFiles.push(pathToModule(file)); 15 } 16 }); 17 } 18 19 require.config({ 20 paths: { 21 angular: 'bower_components/angular/angular', 22 angularRoute: 'bower_components/angular-route/angular-route', 23 angularMocks: 'bower_components/angular-mocks/angular-mocks', 24 angularCookies:'bower_components/angular-cookies/angular-cookies', 25 angularResource:'bower_components/angular-resource/angular-resource', 26 uiBootstrap:'bower_components/angular-bootstrap/ui-bootstrap' 27 }, 28 shim: { 29 'angular' : {'exports' : 'angular'}, 30 'angularRoute': ['angular'], 31 'angularCookies': ['angular'], 32 'angularResource': ['angular'], 33 'angularMocks': { 34 deps:['angular'], 35 'exports':'angular.mock' 36 } 37 }, 38 priority: [ 39 "angular" 40 ], 41 deps: window.__karma__ ? allTestFiles : [], 42 callback: window.__karma__ ? window.__karma__.start : null, 43 baseUrl: window.__karma__ ? '../app' : '' 44 }); 45 46 require([ 47 'angular', 48 'app' 49 ], function(angular, app) { 50 var $html = angular.element(document.getElementsByTagName('html')[0]); 51 angular.element().ready(function() { 52 // bootstrap the app manually 53 angular.bootstrap(document, ['cxriaApp']); 54 }); 55 } 56 );
下面是为测试路由的代码:
1 /** 2 * Created by taox on 15-6-19. 3 */ 4 'use strict'; 5 6 define([ 7 'angular', 8 'angularMocks', 9 'app' 10 ], function() { 11 describe('Routes test', function() { 12 var location,route,rootScope; 13 beforeEach(module('cxriaApp')); 14 beforeEach(inject(function(_$location_,_$route_,_$rootScope_){ 15 location = _$location_; 16 route = _$route_; 17 rootScope = _$rootScope_; 18 })); 19 describe('index route', function(){ 20 var httpbackend; 21 beforeEach(inject(function($httpBackend){ 22 httpbackend = $httpBackend; 23 })); 24 it('should load the homepage on successful load of /.', inject(function() { 25 httpbackend.expectGET('./partials/home/home.html').respond('200','main HTML'); 26 location.path('/'); 27 rootScope.$digest(); 28 expect(route.current.controller).toBe('HomeCtrl'); 29 })); 30 it('should redirect to the homepage on non-existent route',function(){ 31 httpbackend.expectGET('./partials/home/home.html').respond('200','main HTML'); 32 location.path('/non-existent-path'); 33 rootScope.$digest(); 34 expect(route.current.controller).toBe('HomeCtrl'); 35 }); 36 it('should redirect to room page on successful load of /room/1',function(){ 37 httpbackend.expectGET('./partials/room/room.html').respond('200','main HTML'); 38 location.path('/room/1'); 39 rootScope.$digest(); 40 expect(route.current.controller).toBe('RoomCtrl'); 41 }) 42 }); 43 }); 44 45 });
对于karma再测试angular的指令时,为现在遇到一个很蛋疼的问题,那就时在当指令使用templateUrl时,需要karma-ng-html2js-preprocessor才能测试,这时需要修改karma.conf.js.
1.在files中增加模板的地址如:'app/directives/chatroom/*.html',
2.在plugins中增加''karma-ng-html2js-preprocessor',
3.在preprocessors中增加'app/directives/chatroom/*.html':['ng-html2js']
在这3步完成后,下面是我的测试文件,也通过测试了。
1 /** 2 * Created by taox on 15-6-30. 3 */ 4 describe('Unit:Directives',function(){ 5 var scope,compile; 6 7 beforeEach(module('chatroomDirective')); 8 beforeEach(module('directives/chatroom/chatroom.html')); 9 beforeEach(inject(function($compile,$rootScope){ 10 compile = $compile; 11 scope = $rootScope; 12 })); 13 14 it('should content words 发送',function(){ 15 var ele = angular.element('<chatroom></chatroom>'); 16 var chatroom = compile(ele)(scope); 17 scope.$digest(); 18 expect(chatroom.html()).toContain('发送'); 19 }); 20 });
但是如果我在模板中绑定了ng-controller,则会报错。有人知道怎么将controller绑定到模板上吗?如果有知道的,求在http://www.cnblogs.com/towersxu/p/4600298.html 上面留言。下面是为尝试将controller绑定到模板上的方法:
/** * Created by taox on 15-6-30. */ describe('Unit:Directives',function(){ var scope,compile,chatroomCtrl; beforeEach(module('chatroomDirective')); beforeEach(module('directives/chatroom/chatroom.html')); beforeEach(inject(function($compile,$controller,$rootScope){ compile = $compile; scope = $rootScope.$new(); chatroomCtrl = $controller('chatroomCtrl',{$scope:scope,$routeParams:{roomId:'1'}}); })); it('should display words 发送',function(){ var ele = angular.element('<chatroom></chatroom>'); var chatroom = compile(ele)(scope); scope.$digest(); expect(chatroom.html()).toContain('发送'); }); });
错误提示为:Unknown provider:$routeParamsProvider<- $routeParams <-chatroomCtrl.我在测试controller的时候就不会出现这个错误。