From 929ff7658b1ee9d644c74645af57eabda03b6789 Mon Sep 17 00:00:00 2001 From: Ed Moore Date: Fri, 17 Jan 2014 13:08:45 +0800 Subject: [PATCH] App framework setup with coffee and tests --- app/index.js | 68 +++++++++++------ app/templates/Gruntfile.js | 108 ++++++++++++++------------ app/templates/af/app/init.coffee | 10 +++ app/templates/bowerrc | 4 +- package.json | 5 +- test/test-creation.js | 127 ++++++++++++++++++++++++++----- 6 files changed, 229 insertions(+), 93 deletions(-) create mode 100644 app/templates/af/app/init.coffee diff --git a/app/index.js b/app/index.js index 7ff985b..88956d0 100644 --- a/app/index.js +++ b/app/index.js @@ -132,10 +132,10 @@ SmartTVGenerator.prototype.mainStylesheet = function mainStylesheet() { var css; if (this.noAppFramework) { css = 'main.' + (this.includeCompass ? 's' : '') + 'css'; - this.copy(css, 'app/stylesheets/' + css); + this.copy(css, 'src/stylesheets/' + css); } else { css = 'Main.' + (this.includeCompass ? 's' : '') + 'css'; - this.template('af/app/stylesheets/' + css, 'app/stylesheets/' + css); + this.template('af/app/stylesheets/' + css, 'src/app/stylesheets/' + css); } }; @@ -143,23 +143,36 @@ SmartTVGenerator.prototype.mainJavaScript = function mainJavaScript() { var js; if (this.noAppFramework) { js = 'scripts/main.' + (this.coffee ? 'coffee' : 'js'); - this.copy(js, 'app/' + js); + this.copy(js, 'src/' + js); } else { js = 'Main.' + (this.coffee ? 'coffee' : 'js'); - this.copy('af/app/scenes/' + js, 'app/scenes/' + js); + this.copy('af/app/scenes/' + js, 'src/app/scenes/' + js); } }; //Only for use with app framework SmartTVGenerator.prototype.initFile = function initFile() { if (!this.noAppFramework) { - this.copy('af/app/init.js', 'app/init.js'); + var js = 'init.' + (this.coffee ? 'coffee' : 'js'); + this.copy('af/app/' + js, 'src/app/' + js); + } +}; + +SmartTVGenerator.prototype.appJSON = function appJSON() { + if (!this.noAppFramework) { + this.copy('af/app.json', 'src/app.json'); + } +}; + +SmartTVGenerator.prototype.widgetInfo = function widgetInfo() { + if (!this.noAppFramework) { + this.copy('af/widget.info', 'src/widget.info'); } }; SmartTVGenerator.prototype.writeHtmls = function() { if (!this.noAppFramework) { - this.copy('af/app/htmls/Main.html', 'app/htmls/Main.html'); + this.copy('af/app/htmls/Main.html', 'src/app/htmls/Main.html'); } }; @@ -175,8 +188,8 @@ SmartTVGenerator.prototype.writeIndex = function writeIndex() { // wire Twitter Bootstrap plugins if (this.includeBootstrap) { - var bs = 'bower_components/' + (this.includeCompass ? 'sass-' : '') + 'bootstrap/js/'; - this.indexFile = this.appendScripts(this.indexFile, 'scripts/plugins.js', [ + var bs = (this.noAppFramework ? '' : 'app/') + 'bower_components/' + (this.includeCompass ? 'sass-' : '') + 'bootstrap/js/'; + this.indexFile = this.appendScripts(this.indexFile, 'app/vendor/plugins.js', [ bs + 'affix.js', bs + 'alert.js', bs + 'dropdown.js', @@ -192,35 +205,42 @@ SmartTVGenerator.prototype.writeIndex = function writeIndex() { ]); } - this.indexFile = this.appendFiles({ - html: this.indexFile, - fileType: 'js', - optimizedPath: 'scripts/main.js', - sourceFileList: ['scripts/main.js'], - searchPath: '{app,.tmp}' - }); + if (this.noAppFramework) { + this.indexFile = this.appendFiles({ + html: this.indexFile, + fileType: 'js', + optimizedPath: 'scripts/main.js', + sourceFileList: ['scripts/main.js'], + searchPath: '{app,.tmp}' + }); + } }; SmartTVGenerator.prototype.writeConfigXML = function jshint() { - this.copy('config.xml', 'app/config.xml'); + this.copy('config.xml', 'src/config.xml'); }; SmartTVGenerator.prototype.app = function app() { - this.mkdir('app'); + this.mkdir('src'); + if (this.noAppFramework) { - this.mkdir('app/scripts'); + this.mkdir('src/scripts'); + this.mkdir('src/stylesheets'); + this.mkdir('src/images'); } else { - this.mkdir('app/scenes'); - this.mkdir('app/htmls'); + this.mkdir('src/app'); + this.mkdir('src/app/scenes'); + this.mkdir('src/app/htmls'); + this.mkdir('src/app/stylesheets'); + this.mkdir('src/app/images'); } - this.mkdir('app/stylesheets'); - this.mkdir('app/images'); - this.write('app/index.html', this.indexFile); + this.write('src/index.html', this.indexFile); }; SmartTVGenerator.prototype.imageFiles = function () { this.sourceRoot(path.join(__dirname, 'templates')); - this.directory('images', 'app/images', true); + var dir = this.noAppFramework ? 'src/' : 'src/app/' + this.directory('images', dir + 'images', true); }; SmartTVGenerator.prototype.install = function () { diff --git a/app/templates/Gruntfile.js b/app/templates/Gruntfile.js index 0390440..47f199f 100644 --- a/app/templates/Gruntfile.js +++ b/app/templates/Gruntfile.js @@ -21,16 +21,20 @@ module.exports = function (grunt) { // Project settings yeoman: { // Configurable paths - app: 'app', + app: 'src', dist: 'dist' }, // Watches files for changes and runs tasks based on the changed files - watch: {<% if (coffee) { %> + watch: {<% if (coffee) { if (noAppFramework) { %> coffee: { files: ['<%%= yeoman.app %>/scripts/{,*/}*.{coffee,litcoffee,coffee.md}'], tasks: ['coffee:dist'] - }, + },<% } else { %> + coffee: { + files: ['<%%= yeoman.app %>/{,*/}*.{coffee,litcoffee,coffee.md}'], + tasks: ['coffee:dist'] + },<% } %> coffeeTest: { files: ['test/spec/{,*/}*.{coffee,litcoffee,coffee.md}'], tasks: ['coffee:test', 'test:watch'] @@ -48,13 +52,17 @@ module.exports = function (grunt) { },<% } %> gruntfile: { files: ['Gruntfile.js'] - },<% if (includeCompass) { %> + },<% if (includeCompass) { if (noAppFramework) { %> compass: { - files: ['<%%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], + files: ['<%%= yeoman.app %>/stylesheets/{,*/}*.{scss,sass}'], tasks: ['compass:server', 'autoprefixer'] - },<% } %> + },<% } else { %> + compass: { + files: ['<%%= yeoman.app %>/app/stylesheets/{,*/}*.{scss,sass}'], + tasks: ['compass:server', 'autoprefixer'] + },<% }} %> styles: { - files: ['<%%= yeoman.app %>/styles/{,*/}*.css'], + files: ['<%%= yeoman.app %>/stylesheets/{,*/}*.css'], tasks: ['newer:copy:styles', 'autoprefixer'] }, livereload: { @@ -62,10 +70,13 @@ module.exports = function (grunt) { livereload: '<%%= connect.options.livereload %>' }, files: [ - '<%%= yeoman.app %>/{,*/}*.html', - '.tmp/styles/{,*/}*.css',<% if (coffee) { %> + '<%%= yeoman.app %>/{,*/}*.html',<% if (noAppFramework) { %> + '.tmp/stylesheets/{,*/}*.css',<% if (coffee) { %> '.tmp/scripts/{,*/}*.js',<% } %> - '<%%= yeoman.app %>/images/{,*/}*.{gif,jpeg,jpg,png,svg,webp}' + '<%%= yeoman.app %>/images/{,*/}*.{gif,jpeg,jpg,png,svg,webp}'<% } else { %> + '.tmp/app/stylesheets/{,*/}*.css',<% if (coffee) { %> + '.tmp/app/**/*.js',<% } %> + '<%%= yeoman.app %>/app/images/{,*/}*.{gif,jpeg,jpg,png,svg,webp}'<% } %> ] } }, @@ -128,9 +139,10 @@ module.exports = function (grunt) { reporter: require('jshint-stylish') }, all: [ - 'Gruntfile.js', + 'Gruntfile.js',<% if (noAppFramework) { %> '<%%= yeoman.app %>/scripts/{,*/}*.js', - '!<%%= yeoman.app %>/scripts/vendor/*', + '!<%%= yeoman.app %>/scripts/vendor/*',<% } else { %> + '<%%= yeoman.app %>/app/**/*.js',<% } %> 'test/spec/{,*/}*.js' ] }, @@ -160,9 +172,9 @@ module.exports = function (grunt) { dist: { files: [{ expand: true, - cwd: '<%%= yeoman.app %>/scripts', + cwd: '<%%= yeoman.app %>/<% if (!noAppFramework) { %>app/<% } %>scripts', src: '{,*/}*.{coffee,litcoffee,coffee.md}', - dest: '.tmp/scripts', + dest: '.tmp/<% if (!noAppFramework) { %>app/<% } else { %>scripts<% } %>', ext: '.js' }] }, @@ -181,22 +193,22 @@ module.exports = function (grunt) { // Compiles Sass to CSS and generates necessary files if requested compass: { options: { - sassDir: '<%%= yeoman.app %>/styles', - cssDir: '.tmp/styles', - generatedImagesDir: '.tmp/images/generated', - imagesDir: '<%%= yeoman.app %>/images', - javascriptsDir: '<%%= yeoman.app %>/scripts', - fontsDir: '<%%= yeoman.app %>/styles/fonts', - importPath: '<%%= yeoman.app %>/bower_components', - httpImagesPath: '/images', - httpGeneratedImagesPath: '/images/generated', - httpFontsPath: '/styles/fonts', - relativeAssets: false, + sassDir: '<%%= yeoman.app %>/<% if (!noAppFramework) { %>app/<% } %>stylesheets', + cssDir: '.tmp/<% if (!noAppFramework) { %>app/<% } %>stylesheets', + generatedImagesDir: '.tmp/<% if (!noAppFramework) { %>app/<% } %>images/generated', + imagesDir: '<%%= yeoman.app %>/<% if (!noAppFramework) { %>app/<% } %>images', + javascriptsDir: '<%%= yeoman.app %>/<% if (!noAppFramework) { %>app/<% } else { %>scripts<% } %>', + fontsDir: '<%%= yeoman.app %>/<% if (!noAppFramework) { %>app/<% } %>stylesheets/fonts', + importPath: '<%%= yeoman.app %>/<% if (!noAppFramework) { %>app/<% } %>bower_components', + httpImagesPath: '/<% if (!noAppFramework) { %>app/<% } %>images', + httpGeneratedImagesPath: '/<% if (!noAppFramework) { %>app/<% } %>images/generated', + httpFontsPath: '/<% if (!noAppFramework) { %>app/<% } %>stylesheets/fonts', + relativeAssets: true, assetCacheBuster: false }, dist: { options: { - generatedImagesDir: '<%%= yeoman.dist %>/images/generated' + generatedImagesDir: '<%%= yeoman.dist %>/<% if (!noAppFramework) { %>app/<% } %>images/generated' } }, server: { @@ -214,9 +226,9 @@ module.exports = function (grunt) { dist: { files: [{ expand: true, - cwd: '.tmp/styles/', + cwd: '.tmp/<% if (!noAppFramework) { %>app/<% } %>stylesheets/', src: '{,*/}*.css', - dest: '.tmp/styles/' + dest: '.tmp/<% if (!noAppFramework) { %>app/<% } %>stylesheets/' }] } }, @@ -233,11 +245,12 @@ module.exports = function (grunt) { rev: { dist: { files: { - src: [ - '<%%= yeoman.dist %>/scripts/{,*/}*.js', - '<%%= yeoman.dist %>/styles/{,*/}*.css', - '<%%= yeoman.dist %>/images/{,*/}*.{gif,jpeg,jpg,png,webp}', - '<%%= yeoman.dist %>/styles/fonts/{,*/}*.*' + src: [<% if (noAppFramework) { %> + '<%%= yeoman.dist %>/scripts/{,*/}*.js',<% } else { %> + '<%%= yeoman.dist %>/app/{,*/}.*.js',<% } %> + '<%%= yeoman.dist %>/<% if (!noAppFramework) { %>app/<% } %>stylesheets/{,*/}*.css', + '<%%= yeoman.dist %>/<% if (!noAppFramework) { %>app/<% } %>images/{,*/}*.{gif,jpeg,jpg,png,webp}', + '<%%= yeoman.dist %>/<% if (!noAppFramework) { %>app/<% } %>stylesheets/fonts/{,*/}*.*' ] } } @@ -259,7 +272,7 @@ module.exports = function (grunt) { assetsDirs: ['<%%= yeoman.dist %>'] }, html: ['<%%= yeoman.dist %>/{,*/}*.html'], - css: ['<%%= yeoman.dist %>/styles/{,*/}*.css'] + css: ['<%%= yeoman.dist %>/<% if (!noAppFramework) { %>app/<% } %>stylesheets/{,*/}*.css'] }, // The following *-min tasks produce minified files in the dist folder @@ -267,9 +280,9 @@ module.exports = function (grunt) { dist: { files: [{ expand: true, - cwd: '<%%= yeoman.app %>/images', + cwd: '<%%= yeoman.app %>/<% if (!noAppFramework) { %>app/<% } %>images', src: '{,*/}*.{gif,jpeg,jpg,png}', - dest: '<%%= yeoman.dist %>/images' + dest: '<%%= yeoman.dist %>/<% if (!noAppFramework) { %>app/<% } %>images' }] } }, @@ -277,9 +290,9 @@ module.exports = function (grunt) { dist: { files: [{ expand: true, - cwd: '<%%= yeoman.app %>/images', + cwd: '<%%= yeoman.app %>/<% if (!noAppFramework) { %>app/<% } %>images', src: '{,*/}*.svg', - dest: '<%%= yeoman.dist %>/images' + dest: '<%%= yeoman.dist %>/<% if (!noAppFramework) { %>app/<% } %>images' }] } }, @@ -310,9 +323,9 @@ module.exports = function (grunt) { // cssmin: { // dist: { // files: { - // '<%%= yeoman.dist %>/styles/main.css': [ - // '.tmp/styles/{,*/}*.css', - // '<%%= yeoman.app %>/styles/{,*/}*.css' + // '<%%= yeoman.dist %>/stylesheets/main.css': [ + // '.tmp/stylesheets/{,*/}*.css', + // '<%%= yeoman.app %>/stylesheets/{,*/}*.css' // ] // } // } @@ -340,19 +353,18 @@ module.exports = function (grunt) { dest: '<%%= yeoman.dist %>', src: [ '*.{ico,png,txt}', - '.htaccess', - 'images/{,*/}*.webp', + '<% if (!noAppFramework) { %>app/<% } %>images/{,*/}*.webp', '{,*/}*.html', - 'styles/fonts/{,*/}*.*'<% if (includeBootstrap) { %>, - 'bower_components/' + (this.includeCompass ? 'sass-' : '') + 'bootstrap/' + (this.includeCompass ? 'fonts/' : 'dist/fonts/') +'*.*'<% } %> + '<% if (!noAppFramework) { %>app/<% } %>stylesheets/fonts/{,*/}*.*'<% if (includeBootstrap) { %>, + '<% if (!noAppFramework) { %>app/<% } %>bower_components/' + (this.includeCompass ? 'sass-' : '') + 'bootstrap/' + (this.includeCompass ? 'fonts/' : 'dist/fonts/') +'*.*'<% } %> ] }] }, styles: { expand: true, dot: true, - cwd: '<%%= yeoman.app %>/styles', - dest: '.tmp/styles/', + cwd: '<%%= yeoman.app %>/<% if (!noAppFramework) { %>app/<% } %>stylesheets', + dest: '.tmp/<% if (!noAppFramework) { %>app/<% } %>stylesheets/', src: '{,*/}*.css' } }, @@ -438,4 +450,4 @@ module.exports = function (grunt) { 'test', 'build' ]); -}; \ No newline at end of file +}; diff --git a/app/templates/af/app/init.coffee b/app/templates/af/app/init.coffee new file mode 100644 index 0000000..67224ea --- /dev/null +++ b/app/templates/af/app/init.coffee @@ -0,0 +1,10 @@ +onStart = -> + # TODO : Add your Initialize code here + # NOTE : In order to start your app, call "sf.start()" at the end of this function!! + sf.scene.show "Main" + sf.scene.focus "Main" + +onDestroy = -> + #stop your XHR or Ajax operation and put codes to destroy your application here + +alert "init.js loaded." \ No newline at end of file diff --git a/app/templates/bowerrc b/app/templates/bowerrc index d0f0b6f..93753bf 100644 --- a/app/templates/bowerrc +++ b/app/templates/bowerrc @@ -1,3 +1,3 @@ { - "directory": "app/bower_components" -} \ No newline at end of file + "directory": "src/<% if (!noAppFramework) { %>app/<% } %>bower_components" +} diff --git a/package.json b/package.json index 7e117a3..4d2211e 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "generator-smarttv", - "version": "0.0.4", + "version": "0.0.5", "description": "Scaffold out a Samsung SmartTV app", "keywords": [ "yeoman-generator", "samsung", "smarttv", "smart", - "tv" + "tv", + "television" ], "homepage": "https://github.com/eddiemoore/generator-smarttv", "bugs": "https://github.com/eddiemoore/generator-smarttv/issues", diff --git a/test/test-creation.js b/test/test-creation.js index 23a29ef..2416ef6 100644 --- a/test/test-creation.js +++ b/test/test-creation.js @@ -27,20 +27,23 @@ describe('smarttv generator', function () { this.app = require('../app'); }); - + /** ============================================================================== + Non App Framework + ============================================================================*/ it('creates expected files in non app framework mode', function (done) { var expected = [ ['bower.json', /"name": "temp"/], ['package.json', /"name": "temp"/], ['Gruntfile.js', /coffee:/], - 'app/index.html', - 'app/config.xml', - 'app/scripts/main.coffee', - 'app/stylesheets/main.scss' + 'src/index.html', + 'src/config.xml', + 'src/scripts/main.coffee', + 'src/stylesheets/main.scss' ]; helpers.mockPrompt(this.app, { - features: ['includeCompass'] + features: ['includeCompass'], + apptype: 'Video' }); this.app.coffee = true; @@ -57,14 +60,15 @@ describe('smarttv generator', function () { ['bower.json', /"name": "temp"/], ['package.json', /"name": "temp"/], 'Gruntfile.js', - 'app/index.html', - 'app/config.xml', - 'app/scripts/main.js', - 'app/stylesheets/main.scss' + 'src/index.html', + 'src/config.xml', + 'src/scripts/main.js', + 'src/stylesheets/main.scss' ]; helpers.mockPrompt(this.app, { - features: ['includeCompass'] + features: ['includeCompass'], + apptype: 'Video' }); this.app.coffee = false; @@ -81,18 +85,107 @@ describe('smarttv generator', function () { ['bower.json', /"name": "temp"/], ['package.json', /"name": "temp"/], 'Gruntfile.js', - 'app/index.html', - 'app/config.xml', - 'app/scripts/main.js', - 'app/stylesheets/main.scss' + 'src/index.html', + 'src/config.xml', + 'src/scripts/main.js', + 'src/stylesheets/main.scss' ]; helpers.mockPrompt(this.app, { - features: ['includeCompass'] + features: ['includeCompass'], + apptype: 'Video' }); - this.app.options['skip-install'] = true; this.app.noAppFramework = true; + this.app.options['skip-install'] = true; + this.app.run({}, function () { + helpers.assertFiles(expected); + done(); + }); + }); + + + /** ============================================================================== + App Framework + ============================================================================*/ + + it('creates expected files in app framework mode', function (done) { + var expected = [ + ['bower.json', /"name": "temp"/], + ['package.json', /"name": "temp"/], + ['Gruntfile.js', /coffee:/], + 'src/index.html', + 'src/config.xml', + 'src/app.json', + 'src/widget.info', + 'src/app/init.coffee', + 'src/app/scenes/Main.coffee', + 'src/app/stylesheets/Main.scss', + 'src/app/htmls/Main.html' + ]; + + helpers.mockPrompt(this.app, { + features: ['includeCompass'], + apptype: 'Video' + }); + + this.app.coffee = true; + this.app.options['skip-install'] = true; + this.app.run({}, function () { + helpers.assertFiles(expected); + done(); + }); + }); + + it('creates expected files in non-AMD non-coffee mode in app framework mode', function (done) { + var expected = [ + ['bower.json', /"name": "temp"/], + ['package.json', /"name": "temp"/], + 'Gruntfile.js', + 'src/index.html', + 'src/config.xml', + 'src/app.json', + 'src/widget.info', + 'src/app/init.js', + 'src/app/scenes/Main.js', + 'src/app/stylesheets/Main.scss', + 'src/app/htmls/Main.html' + ]; + + helpers.mockPrompt(this.app, { + features: ['includeCompass'], + apptype: 'Video' + }); + + this.app.coffee = false; + this.app.options['skip-install'] = true; + this.app.run({}, function () { + helpers.assertFiles(expected); + done(); + }); + }); + + it('creates expected files in AMD mode in app framework mode', function (done) { + var expected= [ + ['bower.json', /"name": "temp"/], + ['package.json', /"name": "temp"/], + 'Gruntfile.js', + 'src/index.html', + 'src/config.xml', + 'src/app.json', + 'src/widget.info', + 'src/app/init.js', + 'src/app/scenes/Main.js', + 'src/app/stylesheets/Main.scss', + 'src/app/htmls/Main.html' + ]; + + helpers.mockPrompt(this.app, { + features: ['includeCompass'], + apptype: 'Video' + }); + + this.app.options['skip-install'] = true; this.app.run({}, function () { helpers.assertFiles(expected); done();