I have been stuck on this issue for a bit and have not had success with any other questions on here regarding testing uiRouter with requirejs. I have a fairly basic controller setup that uses the $state.go to transition between states once a button is clicked.
runsController.js
define([],
function() {
"use strict"
var runsController = function($scope, $window, $http, $state) {
function getRuns() {
$http.get($window.apiLinks.runs).success(function(data) {
$scope.runs = data.objects;
}).error(function(data) {
console.error();
console.error(data);
});
}
getRuns();
$scope.refresh = getRuns;
$scope.createRun = function() {
//$state.go('createRun');
}
return ["$scope", "$window", "$http", "$state", runsController];
});
The controller is added to an app that depends on uiRouter.
app.js
define(["angular", "js/controllers/runsController", "js/router", "uiRouter"],
function(angular, runsController, router) {
'use strict'
var appName = "myApp";
var app = angular.module(appName, ["ui.router"]);
app.config(router);
app.controller("runsController", runsController);
function getName() {
return appName;
}
return {
app : app,
getName : getName
};
});
router.js
define(["./controllers/runsController"],
function(runsController){
var routes = function($stateProvider, $urlRouterProvider) {
// For any unmatched url, redirect to /runs
$urlRouterProvider.otherwise("/runs");
// Set up the states
$stateProvider
.state('runs', {
url: "/runs",
templateUrl: "partials/runs.html",
controller: "runsController"
})
.state('createRun', {
url: "/createRun",
templateUrl: "partials/runCreator.html"
});
};
return ["$stateProvider", "$urlRouterProvider", routes];
});
Here's the test I have setup for this controller:
define(["angular", "angularMocks", "js/app", "js/controllers/runsController"],
function(angular, mocks, app, runsController) {
'use strict'
describe('runsController Unit Tests', function() {
var mockApp, scope, httpBackend, objects, state;
objects = [
{rid : 1, filename : "myFile.txt", exitCode : 0},
{rid : 2, filename : "test.zip", exitCode : 0},
{rid : 3, filename : "test2.tar", exitCode : 0}
];
beforeEach(function() {
mockApp = angular.module(app.getName());
});
beforeEach(inject(function ($rootScope, $controller, $httpBackend, $http, $state) {
scope = $rootScope.$new();
window.apiLinks = {"runs" : "/mock/api/runs"};
httpBackend = $httpBackend;
state = $state;
httpBackend.when("GET", "/mock/api/runs").respond({
"objects" : objects
});
$controller(runsController[4], {
$scope : scope,
$window : window,
$http : $http,
$state : $state
});
httpBackend.flush();
}));
it("Get state working in test environment", function() {
});
it("Test that controller automatically gets the runs", function() {
// Because of the way our controller files are setup, we have to specify the
// last element in the array instead of just
expect(scope.runs.length).toBe(3);
});
});
This is currently giving me an error message of: Error: [$injector:unpr] Unknown provider: $stateProvider <- $state
From what I have been reading I believe this means I need to be injecting the dependencies that the controller needs in order to run state, but if I am using the app before every test I run then the dependencies should be in there when the .config() is done right? Can anybody help me figure out what it is I am not seeing with this?
Thanks in advance!
I had this same issue this is what I came up with.
This is very important:
karma.conf.js
{
pattern: 'ROOT/TO/YOUR/angular-ui-router/release/angular-ui-router.js',
included: false
},
test-main.js : This is your karma - require - config file
paths: {
// External libraries
'angular': '/base/PATH/TO/YOUR/angular/angular',
'angularMocks': '/base/PATH/TO/YOUR/angular-mocks/angular-mocks',
'uiRouter' : '/base/PATH/TO/YOUR/angular-ui-router/release/angular-ui-router',
.....
/base/ + your path
DO THE SHIMMY
shim: {
'angular': { 'exports': 'angular' },
'angularMocks': { deps: ['angular'], 'exports': 'angular.mock' },
'uiRouter' : {deps: ['angular'], 'exports' : 'uiRouter'},
Now we are inside out test.
define the module
define([
'angular',
'angularMocks',
'uiRouter',
.....
Now when you set up your beforeEach
BeforeEach(inject(function ($injector){
$state = $injector.get('$state');
....
Hope this helps you out.
Related
I'm trying to test my app, which has each controller defined on it's own module i.e., not as a controller of the app module, and then loaded as a dependency of the main app module. When I try to run a test that just checks that the loginController is defined, using Karma/Jasmine, I get the following output:
'Expected undefined to be defined.'
edit
I updated login.controller.spec and switched the karma browser to chrome, which gave me more useful debug info. Now I'm getting an error related to a factory that is added to $httpProvider.interceptors in the main app file:
Unknown provider: authFactoryProvider <- authFactory <- $http <- $translateStaticFilesLoader <- $translate
I found similar issues related to this which were resolved by including angular-translate-loader-static-files.js, which is being loaded when karma runs:
DEBUG [web-server]: serving (cached): /path/to/my/app/bower_components/angular-translate-loader-static-files/angular-translate-loader-static-files.js
How do I resolve all these dependency issues with karma?
index.js
'use strict';
angular.module('app',
[
//'mockBackend', //uncomment when loading mock backend
'ngAnimate',
'ngCookies',
'ngTouch',
'ngSanitize',
'ngResource',
'ui.bootstrap',
'ui.router',
'ui.router.stateHelper',
'pascalprecht.translate',
'utilsModule',
'loginModule',
'vsmsPackageModule',
'vsmsCampaignModule',
'vdmsCampaignModule',
'vdmsDashboardModule',
'daterangepicker',
'ui.event',
'idmAdminModule',
'helpdeskModule',
'ncy-angular-breadcrumb',
'rzModule',
'vsmsDashboardModule',
'highcharts-ng',
'permission',
'dndLists'
])
.config(function ($stateProvider, $urlRouterProvider, $httpProvider, $locationProvider, $translateProvider, $breadcrumbProvider, $compileProvider) {
$urlRouterProvider.otherwise('/');
//initialize get if not there
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
//disable IE ajax request caching
$httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
// extra
$httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
$httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
$locationProvider.html5Mode({
enabled: false,
requireBase: false
});
$translateProvider.useSanitizeValueStrategy('sanitize');
$translateProvider.useStaticFilesLoader({
prefix: '/locales/',
suffix: '.json'
});
$translateProvider
.preferredLanguage('en_us')
.fallbackLanguage('en_us');
$breadcrumbProvider.setOptions({
templateUrl: 'components/templates/breadcrumb.tpl.html'
});
$compileProvider.debugInfoEnabled(false);
// $compileProvider.aHrefSanitizationWhitelist(/^\s*(|blob|):/);
$httpProvider.interceptors.push('authFactory');
$httpProvider.interceptors.push('headersFactory');
})
login.module.js
angular.module('loginModule', []);
login.controller.js
angular.module('loginModule')
.controller('loginController', login);
login.$inject = [
'$log',
'$uibModal',
'$rootScope',
'storageFactory',
'loginFactory',
'$state',
'RoleStore',
'PermissionStore'
];
function login($log, $uibModal, $rootScope, storageFactory, loginFactory, $state, RoleStore, PermissionStore) {
/* jshint validthis: true */
var vm = this;
vm.loginUser = loginUser;
vm.forgotPassword = forgotPassword;
vm.errorCode = null;
PermissionStore.clearStore();
function loginUser() {
...
I'm just trying to test if the controller exists and I can't get past the error:
Expected undefined to be defined.
login.controller.spec.js
describe('loginController', function() {
beforeEach(module('app'));
var $controller,
$scope,
$log,
$uibModal,
$rootScope,
storageFactory,
loginFactory,
$state,
RoleStore,
PermissionStore,
vsmsCoreFactory;
beforeEach(inject(function(_$controller_, _$log_, _$uibModal_, _$rootScope_, _storageFactory_, _loginFactory_, _$state_, _RoleStore_, _PermissionStore_, _vsmsCoreFactory_){
$controller = _$controller_;
$scope = $rootScope.new();
$log = _$log_;
$uibModal = _$uibModal_;
$rootScope = _$rootScope_;
storageFactory = _storageFactory_;
loginFactory = _loginFactory_;
$state = _$state_;
RoleStore = _RoleStore_;
PermissionStore = _PermissionStore_;
vsmsCoreFactory = _vsmsCoreFactory_;
}));
describe('vm.loginUser', function() {
it('should be defined', function() {
var loginController = $controller('loginController', {
$log: $log,
$uibModal: $uibModal,
$rootScope: $rootScope,
storageFactory: storageFactory,
loginFactory: loginFactory,
$state: $state,
RoleStore: RoleStore,
PermissionStore: PermissionStore,
vsmsCoreFactory: vsmsCoreFactory
});
expect(loginController).toBeDefined();
// expect(testController.model.name).toEqual("controllerAs vm test");
});
});
});
unit-tests.js
'use strict';
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var wiredep = require('wiredep');
var paths = gulp.paths;
function runTests (singleRun, done) {
var bowerDeps = wiredep({
directory: 'bower_components',
exclude: ['bootstrap-sass-official'],
dependencies: true,
devDependencies: true
});
var testFiles = bowerDeps.js.concat([
'./src/app/index.js',
'./src/components/scripts/ui-bootstrap-custom-tpls-2.1.3.js',
'./src/{app,components}/**/*.module.js',
'./src/{app,components}/**/*.factory.js',
'./src/{app,components}/**/*.controller.js',
'./src/{app,components}/**/*.spec.js'
]);
gulp.src(testFiles)
.pipe($.karma({
configFile: 'karma.conf.js',
action: (singleRun)? 'run': 'watch'
}))
.on('error', function (err) {
// Make sure failed tests cause gulp to exit non-zero
throw err;
});
}
gulp.task('test', function (done) { runTests(true /* singleRun */, done) });
gulp.task('test:auto', function (done) { runTests(false /* singleRun */, done) });
Please refer the the below link it is already answered.
How to inject controller dependencies in Jasmine tests?
loginController dependencies are not passed in your unit test.
The second parameter of $controller is for controller dependencies.
Empty dependency is passed.
$controller('loginController', {});
Make sure all the dependent modules are loaded before testing loginColtroller.
I have modified your code. I hope it will work.
'use strict';
describe('loginController', function() {
beforeEach(module('loginModule'));
var loginController;
beforeEach(inject(function($controller, _$log_, _$uibModal_, _$rootScope_, _storageFactory_, _loginFactory_, _$state_, _RoleStore_, _PermissionStore_ ){
scope = _$rootScope_.$new();
loginController = $controller('loginController',
{ // all dependencies has to be passed in order
'$log' : _$log_,
'$uibModal' : _$uibModal_,
'$rootScope' : _$rootScope_,
'storageFactory' : _storageFactory_,
'loginFactory': _loginFactory_,
'$state': _$state_,
'RoleStore': _RoleStore_,
'PermissionStore': _PermissionStore_
},
{});
}));
it('should be defined', function() {
expect(loginController).toBeDefined();
});
});
The issue is with your login.module.js file.
You'll have to inject ui.bootstrap and ui.router as dependencies while defining the loginModule. Otherwise it will not be able to get $uibModal and $state while defining the loginController.
This should be the definition of your loginModule
angular.module('loginModule', ['ui.bootstrap', 'ui.router']);
PS: I'm assuming here that storageFactory, loginFactory, RoleStore and PermissionStore are defined on loginModule itself.
Hope this helps!
I have looked through all the similar questions I can find but none was helpful in resolving this error:
Error: [ng:areq] Argument 'loginController' is not a function, got undefined.
Below are my files:
LoginController.js
"use strict";
define(['app-config', 'loginService'], function (app) {
app.controller('LoginController', ['$scope', '$location', 'loginService',
function (sc, loc, loginService) {
sc.login = function () {
console.log("Email Address = " + sc.EmailAddress);
console.log("Password = " + sc.Password);
}
}]);
app-config.js
"use strict";
define(['angularAMD', 'angular-route', 'angular-resource'], function (angularAMD) {
var app = angular.module("openInterviewApp", ['ngRoute', 'ngResource']);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider
/* .when('/login', angularAMD.route({
templateUrl: 'Accounts/Login.html',
controllerUrl: 'Accounts/LoginController'
})) */
.when("/:section/:tree", angularAMD.route({
templateUrl: function (rp) { return rp.section + '/' + rp.tree + '.html'; },
resolve: {
load: ['$q', '$rootScope', '$location', function ($q, $rootScope, $location) {
var path = $location.path();
var parsePath = path.split("/");
var parentPath = parsePath[1];
var controllerName = parsePath[2];
var loadController = parentPath + "/" + controllerName + "Controller";
console.log ("loadController=" + loadController);
var deferred = $q.defer();
require([loadController], function () {
$rootScope.$apply(function () {
deferred.resolve();
});
});
return deferred.promise;
}]
}
}))
.otherwise({ redirectTo: '/' });
}]);
angularAMD.bootstrap(app);
return app;
});
main.js
require.config({
//By default load any module IDs from baseUrl
//baseUrl is normally set to the same directory as the script used in a data-main attribute
baseUrl: "",
// paths config is relative to the baseUrl
// never includes a ".js" extension since the paths config could be for a directory.
// ex: app: 'app' means if the module ID starts with "app", load it from the /app directory
paths: {
'app-config': 'scripts/app-config',
'angular': 'scripts/angular-1.3.15',
'angular-route': 'scripts/angular-route-1.3.15',
'angular-resource': 'scripts/angular-resource-1.3.15',
'angularAMD': 'scripts/angularAMD-4.13.2015',
'jquery': 'scripts/jquery-2.1.3.min',
'loginService': 'services/loginService'
},
// Add angular modules that does not support AMD out of the box, put it in a shim
shim: {
'angularAMD': ['angular'],
'angular-route': ['angular'], //angular-route depends on angular module
'angular-resource': ['angular']
},
// kick start application
deps: ['app-config']
});
Login.html
<div class="container" ng-controller="LoginController" ng-cloak>
loginService.js
define(['app-config'], function (app) {
app.factory('loginService', ['$resource',
function ($resource) {
return $resource(
'jbossews-1.0/login',
{}, {
login: { method: 'POST', cache: false, isArray: false }
});
}]);
});
Your controller should like this,Try this
"use strict";
define(['app-config', 'loginService'], function (app) {
app.register.controller('LoginController', ['$scope', '$location', 'loginService',
function (sc, loc, loginService) {
console.log("LoginController calling");
sc.login = function () {
console.log("Email Address = " + sc.EmailAddress);
console.log("Password = " + sc.Password);
};
}]);
});
and loginService.js should be like this
define(['app-config'], function (app) {
app.register.factory('loginService', ['$resource',
function ($resource) {
return $resource(
'jbossews-1.0/login',
{}, {
login: { method: 'POST', cache: false, isArray: false }
});
}]);
});
Note: This is something which you are missing, Let me try to explain here in more detail.(Considering you have a basic knowledge of require and angularAMD)
Controllers and services in the application rely on RequireJS to
access the object representing the application’s module and then
access the register property to register a controller script with
AngularJS.
This type of registration is required since using the standard
angular.module(“ModuleName”).controller() code won’t work properly
with dynamically loaded controller scripts.
RequireJS’s define() function to get to the app object and then uses
it to register the controller.
The app.register.controller() function points to AngularJS’s
$controllerProvider.register() function behind the scenes with app.js.
All of the controllers,services in the application follow this
pattern.
I got a problem when I tried to test my controller. When I run my test I got an error
Error: [ng:areq] Argument 'MainCtrl' is not a function, got undefined http://errors.angularjs.org/1.3.8/ng/areq?p0=MainCtrl&p1=not%20a%20function%2C%20got%20undefined
at assertArg (/Users/tetianachupryna/project/bower_components/angular/angular.js:1577)
at assertArgFn (/Users/tetianachupryna/project/bower_components/angular/angular.js:1588)
at /Users/tetianachupryna/project/bower_components/angular/angular.js:8418
at /Users/tetianachupryna/project/src/spec/controllers/main-controller.spec.js:11
at /Users/tetianachupryna/project/src/spec/controllers/main-controller.spec.js:17
at /Users/tetianachupryna/project/node_modules/karma-jasmine/lib/adapter.js:184
at http://localhost:9877/karma.js:185
at http://localhost:9877/context.html:51
I know that SO is full of similar questions. But I'm a total null in Angular and JS in general, so those answers didn't help me. From similar questions on SO I discovered that my problem is in wrong definition of the controller but I still can't figure out what I did wrong. I've stack and I'm begging for your help.
First of all here is my src/app/index.js file where my module is defined
var app = angular.module('myModule', [
'ngAnimate',
'ngSanitize',
'ngResource',
'ui.router',
'pascalprecht.translate',
'thing1',
'thing2']);
Here is src/app/controllers/main-controller.js
angular.module('myModule').controller('MainCtrl', [
'$scope',
'$state',
function ($scope, $state) {
$scope.state = $state;
//***
$scope.isBigStep = function isBigStep() {
return $state.$current.step == 3;
};
}]);
And finally this a file with the test src/spec/controllers/main-controller.spec.js
describe('MainCtrl', function() {
var scope, $state, createController;
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
createController = function() {
return $controller('MainCtrl', {
'$scope': scope
});
};
}));
it('should make 3 as current step', function() {
var controller = createController();
expect(scope.isBigStep()).toBe(true);
});
});
In karma config I have all those files
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'src/app/index.js',
'src/app/controllers/*.js',
'src/spec/controllers/*.js'
],
For run my test I use karma-runner plugin in RubyMine.
I'd be thankful for any help!
What you are missing is to add the module in the beforeEach hook for test setup. Otherwise the controller will not be found. So add beforeEach(module('myModule')).
describe('MainCtrl', function() {
var scope, $state, createController;
beforeEach(module('myModule')); //<--- Hook module
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
createController = function() {
return $controller('MainCtrl', {
'$scope': scope
});
};
}));
it('should make 3 as current step', function() {
var controller = createController();
expect(scope.isBigStep()).toBe(true);
});
});
I am in the middle of writing some tests for my application (AngularJS).
As we speak I encountered a problem with verifying if onEnter property of my state was called correctly.
Let me share some code with You
describe('Midway :: routesTest', function () {
var $state,
$rootScope,
$injector,
navigationService;
beforeEach(function () {
module('springatom', function ($provide) {
$provide.value('navigationService', navigationService = {});
});
states.configure();
inject(function (_$rootScope_, _$state_, _$injector_, $templateCache) {
$rootScope = _$rootScope_;
$state = _$state_;
$injector = _$injector_;
// We need add the template entry into the templateCache if we ever
// specify a templateUrl
$templateCache.put('/static/sa/views/home/home.html', '');
$templateCache.put('/static/sa/tpls/grid.html', '');
});
navigationService.getNavigationModel = jasmine.createSpy('getNavigationModel').and.returnValue([]);
navigationService.setNavigatorModel = jasmine.createSpy('setNavigatorModel').and.callFake(function (arg) {
});
});
it("should have a working home route", inject(function () {
var homeState = $state.get('home');
expect(homeState).toBeDefined();
expect($state.href(homeState)).toEqual('#/sa');
$rootScope.$apply(function () {
$state.go(homeState);
});
var current = $state.current;
expect($injector.invoke(current.resolve.actionModel)).toEqual([]);
expect($injector.invoke(current.onEnter)).toHaveBeenCalled();
}));
});
The failing assertion is the last one I am trying to verify therefore mentioned onEnter.
Error is:
Error: [$injector:unpr] Unknown provider: actionModelProvider <- actionModel
http://errors.angularjs.org/1.3.8/$injector/unpr?p0=actionModelProvider%20%3C-%20actionModel
As it is expected Angular tries to resolve actionModel which is the property from the resolve.
I dont know what I might be doing wrong here, so any help will be gladly welcomed.
I am attaching the state configuration as well:
define(
[
'views/home/homeController',
'views/home/recentlyUpdatedController',
// angular deps
'services/navigation'
],
function homeState(homeController, recentlyUpdatedController) {
return {
name : 'home',
definition: {
url : '/sa',
templateUrl: '/static/sa/views/home/home.html',
resolve : {
actionModel: function (navigationService) {
return navigationService.getNavigationModel('main.navigation')
}
},
onEnter : function (actionModel, navigationService) {
navigationService.setNavigatorModel('main.navigation');
},
views : {
'': {
controller : recentlyUpdatedController,
templateUrl: '/static/sa/tpls/grid.html'
}
}
}
}
}
);
I am trying to lazy load my controllers for my AngularJS app I built along side with requireJS. I have created a custom "lazyLoad" library that creates a resolve object in app.config() routes (also I am using ui-router). If I code the state (without my library) to look like so it works
define(['angular', 'lazyLoader', 'uiRouter'], function(angular, lazyLoader, uiRouter){
var app = angular.module('myApp', ['ui.router']);
app.config(function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
window.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
$urlRouterProvider.otherwise('/');
$stateProvider
.state('campaigns', {
url:'/campaigns',
views: {
"top-nav" : {
templateUrl: 'views/home/top-nav.html',
resolve : {
load : ['$q', '$rootScope', function($q, $rootScope){
var d = $q.defer();
require(['../app/controllers/header-controller'], function() {
$rootScope.$apply(function(){
d.resolve();
});
});
return d.promise;
}]
}
},
"fullpage": {
templateUrl: 'views/home/index.html',
resolve : {
load : ['$q', '$rootScope', function($q, $rootScope){
var d = $q.defer();
require(['../app/controllers/home-controller'], function() {
$rootScope.$apply(function(){
d.resolve();
});
});
return d.promise;
}]
}
//controller: 'home-controller'
}
}
});
});
return app;
});
If I attempt to replace the resolve object with my library function it looks would look like this:
define(['angular', 'lazyLoader', 'uiRouter'], function(angular, lazyLoader, uiRouter){
and
.state('home', lazyLoader.route({
url:'/',
views: {
"top-nav" : {
templateUrl: 'views/home/top-nav.html',
controllerUrl: '../app/controllers/header-controller'
},
"fullpage": {
templateUrl: 'views/home/index.html',
controllerUrl: '../app/controllers/home-controller'
}
}
}));
lazyLoader.js
define(function () {
'use strict';
function LazyLoader() {}
LazyLoader.prototype.route = function(config){
var controllerPath;
if(config && config.views){
var singleView = Object.keys(config.views);
for(var i in singleView){
var viewName = singleView[i];
controllerPath = config.views[viewName].controllerUrl;
delete config.views.controllerUrl;
config.views[viewName].resolve = {
load : ['$q', '$rootScope', function($q, $rootScope){
var d = $q.defer();
require([controllerPath], function() {
$rootScope.$apply(function(){
d.resolve();
});
});
return d.promise;
}]
};
}
}
return config;
}
return new LazyLoader();
});
Example Controller
define(['app/module'], function (module) {
lazy.controller('header-controller', ['$scope', function ($scope) {
// stuff here
}]);
});
On a side note I plan on implementing something better than attaching lazy variable to window.
When I code the router like the first example it works. When I use my lazyLoader the one of the two views loads it's controller, the second view's controller's file is started to load (console.logs at the beginning show this) but it cannot resolve "module" in the example above.
link to error: AngularJS Error
Again this issue only happens when using my lazyloader which is producing the same resolve object that I have hard coded in for the version that works.
I have searched high and low and there are a lot of resources out there but I could not find anything that addressed this issue.
Any advice is appreciated!
You are taking too much pain to do lazy loading of controllers & services. There is simple approach to lazy load files with ocLazyLoad. This article might help you resolve the same issue.
https://routerabbit.com/blog/convert-angularjs-yeoman-spa-lazyload/
What you should do is
Add a reference of ocLayzLoad & updated JS files’ reference to load on demand from app.js or .html file of their views.
`bower install oclazyload --save-dev`
Now load the module ‘oc.lazyLoad’ in application. Update app.js file
angular
.module('helloWorldApp', [
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'oc.lazyLoad',
])
Load JS file by adding reference of JS in .html file
<div oc-lazy-load="['scripts/controllers/about.js', 'scripts/services/helloservice.js']">
<div ng-controller="AboutCtrl as about">
Your html goes here
</div>
</div>
If you using Grunt, update Gruntfile to uglyfy, renamed file name & update references in the final .html or .js file.
On the 'myApp' module definition, shouldn't you be returning app variable instead of myApp?
And to avoid exposing lazy to window, you could define it as a property of app variable, this way when you define new functions, you require app first and you can use it:
app.js:
app.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.register,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
...
return app;
controller.js:
define(['app'], function (app) {
app.lazy.controller('header-controller', ['$scope', function ($scope) {
// stuff here
}]);
});