From e579df9d5d2133300f9fe0c3686bc9efbbb5260e Mon Sep 17 00:00:00 2001 From: Andrew Kimpton Date: Thu, 28 May 2015 08:32:25 -0400 Subject: [PATCH] feat(app): add support for --typescript option Uses grunt-tsd to retrieve an initial set of typescript definitions. Adds templates for typescript versions of angular items. Based upon commit 'refs/pull/539/head' of github.com:yeoman/generator-angular --- app/index.js | 19 +++++++ main/index.js | 3 ++ readme.md | 41 ++++++++++++-- route/index.js | 7 ++- script-base.js | 19 +++++++ templates/common/app/.buildignore | 3 +- templates/common/root/_Gruntfile.js | 68 ++++++++++++++++++++---- templates/common/root/_package.json | 4 +- templates/common/root/_tsd.json | 33 ++++++++++++ templates/typescript/app.ts | 19 +++++++ templates/typescript/controller.ts | 23 ++++++++ templates/typescript/decorator.ts | 18 +++++++ templates/typescript/directive.ts | 22 ++++++++ templates/typescript/filter.ts | 18 +++++++ templates/typescript/service/constant.ts | 6 +++ templates/typescript/service/factory.ts | 22 ++++++++ templates/typescript/service/provider.ts | 24 +++++++++ templates/typescript/service/service.ts | 16 ++++++ templates/typescript/service/value.ts | 6 +++ templates/typescript/spec/controller.ts | 26 +++++++++ templates/typescript/spec/directive.ts | 24 +++++++++ templates/typescript/spec/filter.ts | 23 ++++++++ templates/typescript/spec/service.ts | 22 ++++++++ test/test-file-creation.js | 30 +++++++++++ 24 files changed, 478 insertions(+), 18 deletions(-) create mode 100644 templates/common/root/_tsd.json create mode 100644 templates/typescript/app.ts create mode 100644 templates/typescript/controller.ts create mode 100644 templates/typescript/decorator.ts create mode 100644 templates/typescript/directive.ts create mode 100644 templates/typescript/filter.ts create mode 100644 templates/typescript/service/constant.ts create mode 100644 templates/typescript/service/factory.ts create mode 100644 templates/typescript/service/provider.ts create mode 100644 templates/typescript/service/service.ts create mode 100644 templates/typescript/service/value.ts create mode 100644 templates/typescript/spec/controller.ts create mode 100644 templates/typescript/spec/directive.ts create mode 100644 templates/typescript/spec/filter.ts create mode 100644 templates/typescript/spec/service.ts diff --git a/app/index.js b/app/index.js index eda06037d..84b77fd71 100644 --- a/app/index.js +++ b/app/index.js @@ -56,6 +56,21 @@ var Generator = module.exports = function Generator(args, options) { this.env.options.coffee = this.options.coffee; } + if (typeof this.env.options.typescript === 'undefined') { + this.option('typescript', { + desc: 'Generate TypeScript instead of JavaScript' + }); + + // attempt to detect if user is using TS or not + // if cml arg provided, use that; else look for the existence of ts + if (!this.options.typescript && + this.expandFiles(path.join(this.appPath, '/scripts/**/*.ts'), {}).length > 0) { + this.options.typescript = true; + } + + this.env.options.typescript = this.options.typescript; + } + this.hookFor('angular:common', { args: args }); @@ -303,10 +318,14 @@ Generator.prototype.createIndexHtml = function createIndexHtml() { Generator.prototype.packageFiles = function packageFiles() { this.coffee = this.env.options.coffee; + this.typescript = this.env.options.typescript; this.template('root/_bower.json', 'bower.json'); this.template('root/_bowerrc', '.bowerrc'); this.template('root/_package.json', 'package.json'); this.template('root/_Gruntfile.js', 'Gruntfile.js'); + if (this.typescript) { + this.template('root/_tsd.json', 'tsd.json'); + } this.template('root/README.md', 'README.md'); }; diff --git a/main/index.js b/main/index.js index 9a3efc014..1dcdba9e4 100644 --- a/main/index.js +++ b/main/index.js @@ -12,6 +12,9 @@ util.inherits(Generator, ScriptBase); Generator.prototype.createAppFile = function createAppFile() { this.angularModules = this.env.options.angularDeps; + this.ngCookies = this.env.options.ngCookies; + this.ngResource = this.env.options.ngResource; + this.ngSanitize = this.env.options.ngSanitize; this.ngRoute = this.env.options.ngRoute; this.appTemplate('app', 'scripts/app'); }; diff --git a/readme.md b/readme.md index 895cf9904..6dcee086c 100644 --- a/readme.md +++ b/readme.md @@ -188,8 +188,8 @@ angular.module('myMod').config(function ($provide) { ## Options In general, these options can be applied to any generator, though they only affect generators that produce scripts. -### CoffeeScript -For generators that output scripts, the `--coffee` option will output CoffeeScript instead of JavaScript. +### CoffeeScript and TypeScript +For generators that output scripts, the `--coffee` option will output CoffeeScript instead of JavaScript, and `--typescript` will output TypeScript instead of JavaScript. For example: ```bash @@ -202,9 +202,42 @@ angular.module('myMod') .controller 'UserCtrl', ($scope) -> ``` -A project can mix CoffeScript and JavaScript files. +For example: +```bash +yo angular:controller user --typescript +``` + +Produces `app/scripts/controller/user.ts`: +```typescript +/// + +'use strict'; + +module demoApp { + export interface IUserScope extends ng.IScope { + awesomeThings: any[]; + } + + export class UserCtrl { + + constructor (private $scope:IUserScope) { + $scope.awesomeThings = [ + 'HTML5 Boilerplate', + 'AngularJS', + 'Karma' + ]; + } + } +} + +angular.module('demoApp') + .controller('UserCtrl', demoApp.UserCtrl); +``` + + +A project can mix TypeScript, CoffeScript, and JavaScript files. -To output JavaScript files, even if CoffeeScript files exist (the default is to output CoffeeScript files if the generator finds any in the project), use `--coffee=false`. +To output JavaScript files, even if CoffeeScript (or TypeScript) files exist (the default is to output CoffeeScript files if the generator finds any in the project), use `--coffee=false` and/or `--typescript=false`. ### Minification Safe diff --git a/route/index.js b/route/index.js index d1c3de93b..70ed11ff7 100644 --- a/route/index.js +++ b/route/index.js @@ -14,10 +14,12 @@ var Generator = module.exports = function Generator() { required: false }); + var coffee = this.env.options.coffee; + var typescript = this.env.options.typescript; var bower = require(path.join(process.cwd(), 'bower.json')); var match = require('fs').readFileSync(path.join( this.env.options.appPath, - 'scripts/app.' + (this.env.options.coffee ? 'coffee' : 'js') + 'scripts/app.' + (coffee ? 'coffee' : typescript ? 'ts': 'js') ), 'utf-8').match(/\.when/); if ( @@ -52,10 +54,11 @@ Generator.prototype.rewriteAppJs = function () { this.uri = this.options.uri; } + var typescript = this.env.options.typescript; var config = { file: path.join( this.env.options.appPath, - 'scripts/app.' + (coffee ? 'coffee' : 'js') + 'scripts/app.' + (coffee ? 'coffee' : typescript ? 'ts': 'js') ), needle: '.otherwise', splicable: [ diff --git a/script-base.js b/script-base.js index 09e209b98..de4ff1c3f 100644 --- a/script-base.js +++ b/script-base.js @@ -34,6 +34,20 @@ var Generator = module.exports = function Generator() { this.env.options.testPath = this.env.options.testPath || bowerJson.testPath || 'test/spec'; + this.env.options.typescript = this.options.typescript; + if (typeof this.env.options.typescript === 'undefined') { + this.option('typescript'); + + // attempt to detect if user is using TS or not + // if cml arg provided, use that; else look for the existence of ts + if (!this.options.typescript && + this.expandFiles(path.join(this.env.options.appPath, '/scripts/**/*.ts'), {}).length > 0) { + this.options.typescript = true; + } + + this.env.options.typescript = this.options.typescript; + } + this.env.options.coffee = this.options.coffee; if (typeof this.env.options.coffee === 'undefined') { this.option('coffee'); @@ -56,6 +70,11 @@ var Generator = module.exports = function Generator() { this.scriptSuffix = '.coffee'; } + if (this.env.options.typescript) { + sourceRoot = '/templates/typescript'; + this.scriptSuffix = '.ts'; + } + this.sourceRoot(path.join(__dirname, sourceRoot)); }; diff --git a/templates/common/app/.buildignore b/templates/common/app/.buildignore index fc98b8eb5..548f58c3c 100644 --- a/templates/common/app/.buildignore +++ b/templates/common/app/.buildignore @@ -1 +1,2 @@ -*.coffee \ No newline at end of file +*.coffee +*.ts \ No newline at end of file diff --git a/templates/common/root/_Gruntfile.js b/templates/common/root/_Gruntfile.js index d0db6c779..e6e3029e6 100644 --- a/templates/common/root/_Gruntfile.js +++ b/templates/common/root/_Gruntfile.js @@ -44,6 +44,14 @@ module.exports = function (grunt) { coffeeTest: { files: ['test/spec/{,*/}*.{coffee,litcoffee,coffee.md}'], tasks: ['newer:coffee:test', 'karma'] + },<% } else if (typescript) { %> + typescript: { + files: ['<%%= yeoman.app %>/scripts/{,*/}*.ts'], + tasks: ['typescript:base'] + }, + typescriptTest: { + files: ['test/spec/{,*/}*.ts'], + tasks: ['typescript:test', 'karma'] },<% } else { %> js: { files: ['<%%= yeoman.app %>/scripts/{,*/}*.js'], @@ -73,7 +81,7 @@ module.exports = function (grunt) { }, files: [ '<%%= yeoman.app %>/{,*/}*.html', - '.tmp/styles/{,*/}*.css',<% if (coffee) { %> + '.tmp/styles/{,*/}*.css',<% if (coffee || typescript) { %> '.tmp/scripts/{,*/}*.js',<% } %> '<%%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' ] @@ -139,10 +147,10 @@ module.exports = function (grunt) { }, all: { src: [ - 'Gruntfile.js'<% if (!coffee) { %>, + 'Gruntfile.js'<% if (!coffee && !typescript) { %>, '<%%= yeoman.app %>/scripts/{,*/}*.js'<% } %> ] - }<% if (!coffee) { %>, + }<% if (!coffee && !typescript) { %>, test: { options: { jshintrc: 'test/.jshintrc' @@ -248,7 +256,41 @@ module.exports = function (grunt) { src: ['<%%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], ignorePath: /(\.\.\/){1,2}bower_components\// }<% } %> - },<% if (coffee) { %> + }, <% if (typescript) { %> + // Compiles TypeScript to JavaScript + typescript: { + base: { + src: ['<%%= yeoman.app %>/scripts/{,*/}*.ts'], + dest: '.tmp/scripts', + options: { + module: 'amd', //or commonjs + target: 'es5', //or es3 + 'base_path': '<%%= yeoman.app %>/scripts', //quoting base_path to get around jshint warning. + sourcemap: true, + declaration: true + } + }, + test: { + src: ['test/spec/{,*/}*.ts', 'test/e2e/{,*/}*.ts'], + dest: '.tmp/spec', + options: { + module: 'amd', //or commonjs + target: 'es5', //or es3 + sourcemap: true, + declaration: true + } + } + }, + tsd: { + refresh: { + options: { + // execute a command + command: 'reinstall', + config: 'tsd.json' + } + } + }, + <% } %><% if (coffee) { %> // Compiles CoffeeScript to JavaScript coffee: { @@ -496,17 +538,20 @@ module.exports = function (grunt) { // Run some tasks in parallel to speed up the build process concurrent: { server: [<% if (coffee) { %> - 'coffee:dist',<% } %><% if (compass) { %> + 'coffee:dist',<% } %><% if (typescript) { %> + 'typescript:base',<% } %><% if (compass) { %> 'compass:server'<% } else { %> 'copy:styles'<% } %> ], test: [<% if (coffee) { %> - 'coffee',<% } %><% if (compass) { %> + 'coffee',<% } %><% if (typescript) { %> + 'typescript',<% } %><% if (compass) { %> 'compass'<% } else { %> 'copy:styles'<% } %> ], dist: [<% if (coffee) { %> - 'coffee',<% } %><% if (compass) { %> + 'coffee',<% } %><% if (typescript) { %> + 'typescript',<% } %><% if (compass) { %> 'compass:dist',<% } else { %> 'copy:styles',<% } %> 'imagemin', @@ -534,7 +579,8 @@ module.exports = function (grunt) { grunt.task.run([ 'clean:server', - 'wiredep', + 'wiredep',<% if (typescript) { %> + 'tsd:refresh',<% } %> 'concurrent:server', 'postcss:server', 'connect:livereload', @@ -549,7 +595,8 @@ module.exports = function (grunt) { grunt.registerTask('test', [ 'clean:server', - 'wiredep', + 'wiredep',<% if (typescript) { %> + 'tsd:refresh',<% } %> 'concurrent:test', 'postcss', 'connect:test', @@ -558,7 +605,8 @@ module.exports = function (grunt) { grunt.registerTask('build', [ 'clean:dist', - 'wiredep', + 'wiredep',<% if (typescript) { %> + 'tsd:refresh',<% } %> 'useminPrepare', 'concurrent:dist', 'postcss', diff --git a/templates/common/root/_package.json b/templates/common/root/_package.json index d9520fcad..2dd638508 100644 --- a/templates/common/root/_package.json +++ b/templates/common/root/_package.json @@ -24,7 +24,9 @@ "grunt-newer": "^1.1.0", "grunt-ng-annotate": "^0.9.2", "grunt-postcss": "^0.5.5", - "grunt-svgmin": "^2.0.0", + "grunt-svgmin": "^2.0.0",<% if (typescript) { %> + "grunt-tsd": "^0.1.0", + "grunt-typescript": "^0.6.2",<% } %> "grunt-usemin": "^3.0.0", "grunt-wiredep": "^2.0.0", "jit-grunt": "^0.9.1", diff --git a/templates/common/root/_tsd.json b/templates/common/root/_tsd.json new file mode 100644 index 000000000..6b696ab18 --- /dev/null +++ b/templates/common/root/_tsd.json @@ -0,0 +1,33 @@ +{ + "version": "v4", + "repo": "borisyankov/DefinitelyTyped", + "ref": "master", + "path": "typings", + "bundle": "typings/tsd.d.ts", + "installed": { + "jquery/jquery.d.ts": { + "commit": "f3244190e20af6901e865f4cc58127d19216baa1" + }, + "angularjs/angular.d.ts": { + "commit": "f3244190e20af6901e865f4cc58127d19216baa1" + }, + "angularjs/angular-resource.d.ts": { + "commit": "aadd63ecae3feb76ea2d4be80511e266b5c2c4a7" + }, + "angularjs/angular-route.d.ts": { + "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e" + }, + "angularjs/angular-mocks.d.ts": { + "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e" + }, + "angularjs/angular-cookies.d.ts": { + "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e" + }, + "angularjs/angular-sanitize.d.ts": { + "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e" + }, + "jasmine/jasmine.d.ts": { + "commit": "f23cd55e319a0f67362ca0dbc4cf3e2ec1339f4e" + } + } +} diff --git a/templates/typescript/app.ts b/templates/typescript/app.ts new file mode 100644 index 000000000..97dfddb9d --- /dev/null +++ b/templates/typescript/app.ts @@ -0,0 +1,19 @@ +/// <% if (ngCookies) { %> +/// <% } %><% if (ngResource) { %> +/// <% } %><% if (ngSanitize) { %> +/// <% } %><% if (ngRoute) { %> +/// <% } %> + +'use strict'; + +angular.module('<%= scriptAppName %>', [<%= angularModules %>])<% if (ngRoute) { %> + .config(($routeProvider:ng.route.IRouteProvider) => { + $routeProvider + .when('/', { + templateUrl: 'views/main.html', + controller: 'MainCtrl' + }) + .otherwise({ + redirectTo: '/' + }); + })<% } %>; diff --git a/templates/typescript/controller.ts b/templates/typescript/controller.ts new file mode 100644 index 000000000..7a91b6894 --- /dev/null +++ b/templates/typescript/controller.ts @@ -0,0 +1,23 @@ +/// + +'use strict'; + +module <%= scriptAppName %> { + export interface I<%= classedName %>Scope extends ng.IScope { + awesomeThings: any[]; + } + + export class <%= classedName %>Ctrl { + + constructor (private $scope: I<%= classedName %>Scope) { + $scope.awesomeThings = [ + 'HTML5 Boilerplate', + 'AngularJS', + 'Karma' + ]; + } + } +} + +angular.module('<%= scriptAppName %>') + .controller('<%= classedName %>Ctrl', <%= scriptAppName %>.<%= classedName %>Ctrl); diff --git a/templates/typescript/decorator.ts b/templates/typescript/decorator.ts new file mode 100644 index 000000000..8272e1d5a --- /dev/null +++ b/templates/typescript/decorator.ts @@ -0,0 +1,18 @@ +/// + +'use strict'; + +module <%= scriptAppName %> { + export function <%= cameledName %>DecoratorProvider($provide: ng.auto.IProvideService): void { + //decorate <%= cameledName %> + $provide.decorator('<%= cameledName %>', <%= cameledName %>Decorator); + } + + export function <%= cameledName %>Decorator($delegate: any) { + // decorate the $delegate + return $delegate; + } +} + +angular.module('<%= scriptAppName %>') + .config(<%= scriptAppName %>.<%= cameledName %>DecoratorProvider); diff --git a/templates/typescript/directive.ts b/templates/typescript/directive.ts new file mode 100644 index 000000000..9c0940391 --- /dev/null +++ b/templates/typescript/directive.ts @@ -0,0 +1,22 @@ +/// + +'use strict'; + +module <%= scriptAppName %> { + + export class <%= classedName %> implements ng.IDirective { + template = '
'; + restrict = 'E'; + link = (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes): void => { + element.text('this is the <%= cameledName %> directive'); + } + } + + export function <%= cameledName %>Factory() { + return new <%= scriptAppName %>.<%= classedName %>(); + } + +} + +angular.module('<%= scriptAppName %>') + .directive('<%= cameledName %>', <%= scriptAppName %>.<%= cameledName %>Factory); diff --git a/templates/typescript/filter.ts b/templates/typescript/filter.ts new file mode 100644 index 000000000..07708ed42 --- /dev/null +++ b/templates/typescript/filter.ts @@ -0,0 +1,18 @@ +/// + +'use strict'; + +module <%= scriptAppName %> { + export function <%= cameledName %>FilterFactory(): Function { + return <%= cameledName %>Filter; + } + + function <%= cameledName %>Filter(input, param) { + //usage {{"text" | <%= cameledName %>: "suffix"}} + //returns '<%= cameledName %> filter: text suffix' + return '<%= cameledName %> filter: ' + input + (param ? ' ' + param: ''); + } +} + +angular.module('<%= scriptAppName %>') + .filter('<%= cameledName %>', <%= scriptAppName %>.<%= cameledName %>FilterFactory); \ No newline at end of file diff --git a/templates/typescript/service/constant.ts b/templates/typescript/service/constant.ts new file mode 100644 index 000000000..30cbacd48 --- /dev/null +++ b/templates/typescript/service/constant.ts @@ -0,0 +1,6 @@ +/// + +'use strict'; + +angular.module('<%= scriptAppName %>') + .constant('<%= cameledName %>', 42); diff --git a/templates/typescript/service/factory.ts b/templates/typescript/service/factory.ts new file mode 100644 index 000000000..bc25a3cb8 --- /dev/null +++ b/templates/typescript/service/factory.ts @@ -0,0 +1,22 @@ +/// + +'use strict'; + +module <%= scriptAppName %> { + export function <%= cameledName %>Factory() { + return new <%= classedName %>(42); + } + + export class <%= classedName %> { + + constructor (private meaningOfLife) { + } + + someMethod() { + return this.meaningOfLife; + } + } +} + +angular.module('<%= scriptAppName %>') + .factory('<%= cameledName %>', <%= scriptAppName %>.<%= cameledName %>Factory); diff --git a/templates/typescript/service/provider.ts b/templates/typescript/service/provider.ts new file mode 100644 index 000000000..0ec9dddad --- /dev/null +++ b/templates/typescript/service/provider.ts @@ -0,0 +1,24 @@ +/// + +'use strict'; + +module <%= scriptAppName %> { + + var salutation: string; + + export class Greeter { + greet = () => salutation; + } + + export class <%= classedName %>Provider { + $get = () => new Greeter(); + + // Public API for configuration + setSalutation = (s: string) => salutation = s; + } + +} + + +angular.module('<%= scriptAppName %>') + .provider('<%= cameledName %>', <%= scriptAppName %>.<%= classedName %>Provider); diff --git a/templates/typescript/service/service.ts b/templates/typescript/service/service.ts new file mode 100644 index 000000000..2e4d750b1 --- /dev/null +++ b/templates/typescript/service/service.ts @@ -0,0 +1,16 @@ +/// + +'use strict'; + +module <%= scriptAppName %> { + export class <%= classedName %> { + awesomeThings:any[] = [ + 'HTML5 Boilerplate', + 'AngularJS', + 'Karma' + ]; + } +} + +angular.module('<%= scriptAppName %>') + .service('<%= cameledName %>', <%= scriptAppName %>.<%= classedName %>); diff --git a/templates/typescript/service/value.ts b/templates/typescript/service/value.ts new file mode 100644 index 000000000..8809e9db6 --- /dev/null +++ b/templates/typescript/service/value.ts @@ -0,0 +1,6 @@ +/// + +'use strict'; + +angular.module('<%= scriptAppName %>') + .value('<%= cameledName %>', 42); diff --git a/templates/typescript/spec/controller.ts b/templates/typescript/spec/controller.ts new file mode 100644 index 000000000..d4e1686c7 --- /dev/null +++ b/templates/typescript/spec/controller.ts @@ -0,0 +1,26 @@ +/// +/// +/// + +'use strict'; + +describe('Controller: <%= classedName %>Ctrl', () => { + + // load the controller's module + beforeEach(module('<%= scriptAppName %>')); + + var <%= classedName %>Ctrl: <%= scriptAppName %>.<%= classedName %>Ctrl, + scope: <%= scriptAppName %>.I<%= classedName %>Scope; + + // Initialize the controller and a mock scope + beforeEach(inject(($controller: ng.IControllerService, $rootScope: ng.IRootScopeService) => { + scope = $rootScope.$new(); + <%= classedName %>Ctrl = $controller('<%= classedName %>Ctrl', { + $scope: scope + }); + })); + + it('should attach a list of awesomeThings to the scope', () => { + expect(scope.awesomeThings.length).toBe(3); + }); +}); diff --git a/templates/typescript/spec/directive.ts b/templates/typescript/spec/directive.ts new file mode 100644 index 000000000..88cf850e5 --- /dev/null +++ b/templates/typescript/spec/directive.ts @@ -0,0 +1,24 @@ +/// +/// +/// + +'use strict'; + +describe('Directive: <%= cameledName %>', () => { + + // load the directive's module + beforeEach(module('<%= scriptAppName %>')); + + var element: JQuery, + scope: ng.IScope; + + beforeEach(inject(($rootScope: ng.IRootScopeService) => { + scope = $rootScope.$new(); + })); + + it('should make hidden element visible', inject(($compile: ng.ICompileService) => { + element = angular.element('<<%= _.dasherize(name) %>>>'); + element = $compile(element)(scope); + expect(element.text()).toBe('this is the <%= cameledName %> directive'); + })); +}); diff --git a/templates/typescript/spec/filter.ts b/templates/typescript/spec/filter.ts new file mode 100644 index 000000000..3c35c3cb4 --- /dev/null +++ b/templates/typescript/spec/filter.ts @@ -0,0 +1,23 @@ +/// +/// +/// + +'use strict'; + +describe('Filter: <%= cameledName %>', () => { + + // load the filter's module + beforeEach(module('<%= scriptAppName %>')); + + // initialize a new instance of the filter before each test + var <%= cameledName %>; + beforeEach(inject($filter => { + <%= cameledName %> = $filter('<%= cameledName %>'); + })); + + it('should return the input prefixed with "<%= cameledName %> filter:"', () => { + var text = 'angularjs'; + expect(<%= cameledName %>(text)).toBe('<%= cameledName %> filter: ' + text); + }); + +}); diff --git a/templates/typescript/spec/service.ts b/templates/typescript/spec/service.ts new file mode 100644 index 000000000..c7366b691 --- /dev/null +++ b/templates/typescript/spec/service.ts @@ -0,0 +1,22 @@ +/// +/// +/// + +'use strict'; + +describe('Service: <%= cameledName %>', () => { + + // load the service's module + beforeEach(module('<%= scriptAppName %>')); + + // instantiate service + var <%= cameledName %>; + beforeEach(inject(_<%= cameledName %>_ => { + <%= cameledName %> = _<%= cameledName %>_; + })); + + it('should do something', () => { + expect(!!<%= cameledName %>).toBe(true); + }); + +}); diff --git a/test/test-file-creation.js b/test/test-file-creation.js index 7b30526cc..3b031cb34 100644 --- a/test/test-file-creation.js +++ b/test/test-file-creation.js @@ -141,6 +141,36 @@ describe('Angular generator file creation', function () { it('should generate a new service', function (done) { generatorTest('service', 'service', 'services', _.capitalize, _.capitalize, '', done); }); + + it('creates typescript files', function (done) { + var expected = ['app/.htaccess', + 'app/404.html', + 'app/favicon.ico', + 'app/robots.txt', + 'app/styles/main.scss', + 'app/views/main.html', + '.bowerrc', + 'Gruntfile.js', + 'package.json', + 'bower.json', + 'app/scripts/app.ts', + 'app/index.html', + 'app/scripts/controllers/main.ts', + 'test/spec/controllers/main.ts' + ]; + helpers.mockPrompt(angular, { + compass: true, + bootstrap: true, + compassBootstrap: true, + modules: [] + }); + + angular.env.options.typescript = true; + angular.run([], function () { + helpers.assertFiles(expected); + done(); + }); + }); }); describe('View', function () {