Commit 33ee6d0a9d1dfc968dcc7d318daa210c0cf8ead8
0 parents
Exists in
master
and in
38 other branches
Initial commit
Showing
57 changed files
with
1599 additions
and
0 deletions
Show diff stats
1 | +++ a/.editorconfig | |
... | ... | @@ -0,0 +1,13 @@ |
1 | +# http://editorconfig.org | |
2 | +root = true | |
3 | + | |
4 | +[*] | |
5 | +indent_style = space | |
6 | +indent_size = 2 | |
7 | +end_of_line = lf | |
8 | +charset = utf-8 | |
9 | +trim_trailing_whitespace = true | |
10 | +insert_final_newline = true | |
11 | + | |
12 | +[*.md] | |
13 | +trim_trailing_whitespace = false | ... | ... |
1 | +++ a/.yo-rc.json | |
... | ... | @@ -0,0 +1,78 @@ |
1 | +{ | |
2 | + "generator-gulp-angular": { | |
3 | + "version": "1.0.2", | |
4 | + "props": { | |
5 | + "angularVersion": "~1.4.2", | |
6 | + "angularModules": [ | |
7 | + { | |
8 | + "key": "animate", | |
9 | + "module": "ngAnimate" | |
10 | + }, | |
11 | + { | |
12 | + "key": "cookies", | |
13 | + "module": "ngCookies" | |
14 | + }, | |
15 | + { | |
16 | + "key": "touch", | |
17 | + "module": "ngTouch" | |
18 | + }, | |
19 | + { | |
20 | + "key": "sanitize", | |
21 | + "module": "ngSanitize" | |
22 | + }, | |
23 | + { | |
24 | + "key": "messages", | |
25 | + "module": "ngMessages" | |
26 | + }, | |
27 | + { | |
28 | + "key": "aria", | |
29 | + "module": "ngAria" | |
30 | + } | |
31 | + ], | |
32 | + "jQuery": { | |
33 | + "key": "jqLite" | |
34 | + }, | |
35 | + "resource": { | |
36 | + "key": "angular-resource", | |
37 | + "module": "ngResource" | |
38 | + }, | |
39 | + "router": { | |
40 | + "key": "angular-route", | |
41 | + "module": "ngRoute" | |
42 | + }, | |
43 | + "ui": { | |
44 | + "key": "bootstrap", | |
45 | + "module": null | |
46 | + }, | |
47 | + "bootstrapComponents": { | |
48 | + "key": "ui-bootstrap", | |
49 | + "module": "ui.bootstrap" | |
50 | + }, | |
51 | + "cssPreprocessor": { | |
52 | + "key": "node-sass", | |
53 | + "extension": "scss" | |
54 | + }, | |
55 | + "jsPreprocessor": { | |
56 | + "key": "noJsPrepro", | |
57 | + "extension": "js", | |
58 | + "srcExtension": "js" | |
59 | + }, | |
60 | + "htmlPreprocessor": { | |
61 | + "key": "noHtmlPrepro", | |
62 | + "extension": "html" | |
63 | + }, | |
64 | + "foundationComponents": { | |
65 | + "name": null, | |
66 | + "version": null, | |
67 | + "key": null, | |
68 | + "module": null | |
69 | + }, | |
70 | + "paths": { | |
71 | + "src": "src", | |
72 | + "dist": "dist", | |
73 | + "e2e": "e2e", | |
74 | + "tmp": ".tmp" | |
75 | + } | |
76 | + } | |
77 | + } | |
78 | +} | |
0 | 79 | \ No newline at end of file | ... | ... |
1 | +++ a/bower.json | |
... | ... | @@ -0,0 +1,39 @@ |
1 | +{ | |
2 | + "name": "angular", | |
3 | + "version": "0.0.0", | |
4 | + "dependencies": { | |
5 | + "angular-animate": "~1.4.2", | |
6 | + "angular-cookies": "~1.4.2", | |
7 | + "angular-touch": "~1.4.2", | |
8 | + "angular-sanitize": "~1.4.2", | |
9 | + "angular-messages": "~1.4.2", | |
10 | + "angular-aria": "~1.4.2", | |
11 | + "angular-resource": "~1.4.2", | |
12 | + "angular-route": "~1.4.2", | |
13 | + "bootstrap-sass": "~3.3.5", | |
14 | + "angular-bootstrap": "~0.13.4", | |
15 | + "malarkey": "yuanqing/malarkey#~1.3.1", | |
16 | + "angular-toastr": "~1.5.0", | |
17 | + "moment": "~2.10.6", | |
18 | + "animate.css": "~3.4.0", | |
19 | + "angular": "~1.4.2" | |
20 | + }, | |
21 | + "devDependencies": { | |
22 | + "angular-mocks": "~1.4.2" | |
23 | + }, | |
24 | + "overrides": { | |
25 | + "bootstrap-sass": { | |
26 | + "main": [ | |
27 | + "assets/stylesheets/_bootstrap.scss", | |
28 | + "assets/fonts/bootstrap/glyphicons-halflings-regular.eot", | |
29 | + "assets/fonts/bootstrap/glyphicons-halflings-regular.svg", | |
30 | + "assets/fonts/bootstrap/glyphicons-halflings-regular.ttf", | |
31 | + "assets/fonts/bootstrap/glyphicons-halflings-regular.woff", | |
32 | + "assets/fonts/bootstrap/glyphicons-halflings-regular.woff2" | |
33 | + ] | |
34 | + } | |
35 | + }, | |
36 | + "resolutions": { | |
37 | + "angular": "~1.4.2" | |
38 | + } | |
39 | +} | ... | ... |
1 | +++ a/e2e/main.po.js | |
... | ... | @@ -0,0 +1,15 @@ |
1 | +/** | |
2 | + * This file uses the Page Object pattern to define the main page for tests | |
3 | + * https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ | |
4 | + */ | |
5 | + | |
6 | +'use strict'; | |
7 | + | |
8 | +var MainPage = function() { | |
9 | + this.jumbEl = element(by.css('.jumbotron')); | |
10 | + this.h1El = this.jumbEl.element(by.css('h1')); | |
11 | + this.imgEl = this.jumbEl.element(by.css('img')); | |
12 | + this.thumbnailEls = element(by.css('body')).all(by.repeater('awesomeThing in main.awesomeThings')); | |
13 | +}; | |
14 | + | |
15 | +module.exports = new MainPage(); | ... | ... |
1 | +++ a/e2e/main.spec.js | |
... | ... | @@ -0,0 +1,21 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +describe('The main view', function () { | |
4 | + var page; | |
5 | + | |
6 | + beforeEach(function () { | |
7 | + browser.get('/index.html'); | |
8 | + page = require('./main.po'); | |
9 | + }); | |
10 | + | |
11 | + it('should include jumbotron with correct data', function() { | |
12 | + expect(page.h1El.getText()).toBe('\'Allo, \'Allo!'); | |
13 | + expect(page.imgEl.getAttribute('src')).toMatch(/assets\/images\/yeoman.png$/); | |
14 | + expect(page.imgEl.getAttribute('alt')).toBe('I\'m Yeoman'); | |
15 | + }); | |
16 | + | |
17 | + it('should list more than 5 awesome things', function () { | |
18 | + expect(page.thumbnailEls.count()).toBeGreaterThan(5); | |
19 | + }); | |
20 | + | |
21 | +}); | ... | ... |
1 | +++ a/gulp/build.js | |
... | ... | @@ -0,0 +1,98 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var gulp = require('gulp'); | |
5 | +var conf = require('./conf'); | |
6 | + | |
7 | +var $ = require('gulp-load-plugins')({ | |
8 | + pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del'] | |
9 | +}); | |
10 | + | |
11 | +gulp.task('partials', function () { | |
12 | + return gulp.src([ | |
13 | + path.join(conf.paths.src, '/app/**/*.html'), | |
14 | + path.join(conf.paths.tmp, '/serve/app/**/*.html') | |
15 | + ]) | |
16 | + .pipe($.minifyHtml({ | |
17 | + empty: true, | |
18 | + spare: true, | |
19 | + quotes: true | |
20 | + })) | |
21 | + .pipe($.angularTemplatecache('templateCacheHtml.js', { | |
22 | + module: 'angular', | |
23 | + root: 'app' | |
24 | + })) | |
25 | + .pipe(gulp.dest(conf.paths.tmp + '/partials/')); | |
26 | +}); | |
27 | + | |
28 | +gulp.task('html', ['inject', 'partials'], function () { | |
29 | + var partialsInjectFile = gulp.src(path.join(conf.paths.tmp, '/partials/templateCacheHtml.js'), { read: false }); | |
30 | + var partialsInjectOptions = { | |
31 | + starttag: '<!-- inject:partials -->', | |
32 | + ignorePath: path.join(conf.paths.tmp, '/partials'), | |
33 | + addRootSlash: false | |
34 | + }; | |
35 | + | |
36 | + var htmlFilter = $.filter('*.html', { restore: true }); | |
37 | + var jsFilter = $.filter('**/*.js', { restore: true }); | |
38 | + var cssFilter = $.filter('**/*.css', { restore: true }); | |
39 | + var assets; | |
40 | + | |
41 | + return gulp.src(path.join(conf.paths.tmp, '/serve/*.html')) | |
42 | + .pipe($.inject(partialsInjectFile, partialsInjectOptions)) | |
43 | + .pipe(assets = $.useref.assets()) | |
44 | + .pipe($.rev()) | |
45 | + .pipe(jsFilter) | |
46 | + .pipe($.sourcemaps.init()) | |
47 | + .pipe($.ngAnnotate()) | |
48 | + .pipe($.uglify({ preserveComments: $.uglifySaveLicense })).on('error', conf.errorHandler('Uglify')) | |
49 | + .pipe($.sourcemaps.write('maps')) | |
50 | + .pipe(jsFilter.restore) | |
51 | + .pipe(cssFilter) | |
52 | + .pipe($.sourcemaps.init()) | |
53 | + .pipe($.replace('../../bower_components/bootstrap-sass/assets/fonts/bootstrap/', '../fonts/')) | |
54 | + .pipe($.minifyCss({ processImport: false })) | |
55 | + .pipe($.sourcemaps.write('maps')) | |
56 | + .pipe(cssFilter.restore) | |
57 | + .pipe(assets.restore()) | |
58 | + .pipe($.useref()) | |
59 | + .pipe($.revReplace()) | |
60 | + .pipe(htmlFilter) | |
61 | + .pipe($.minifyHtml({ | |
62 | + empty: true, | |
63 | + spare: true, | |
64 | + quotes: true, | |
65 | + conditionals: true | |
66 | + })) | |
67 | + .pipe(htmlFilter.restore) | |
68 | + .pipe(gulp.dest(path.join(conf.paths.dist, '/'))) | |
69 | + .pipe($.size({ title: path.join(conf.paths.dist, '/'), showFiles: true })); | |
70 | + }); | |
71 | + | |
72 | +// Only applies for fonts from bower dependencies | |
73 | +// Custom fonts are handled by the "other" task | |
74 | +gulp.task('fonts', function () { | |
75 | + return gulp.src($.mainBowerFiles()) | |
76 | + .pipe($.filter('**/*.{eot,svg,ttf,woff,woff2}')) | |
77 | + .pipe($.flatten()) | |
78 | + .pipe(gulp.dest(path.join(conf.paths.dist, '/fonts/'))); | |
79 | +}); | |
80 | + | |
81 | +gulp.task('other', function () { | |
82 | + var fileFilter = $.filter(function (file) { | |
83 | + return file.stat.isFile(); | |
84 | + }); | |
85 | + | |
86 | + return gulp.src([ | |
87 | + path.join(conf.paths.src, '/**/*'), | |
88 | + path.join('!' + conf.paths.src, '/**/*.{html,css,js,scss}') | |
89 | + ]) | |
90 | + .pipe(fileFilter) | |
91 | + .pipe(gulp.dest(path.join(conf.paths.dist, '/'))); | |
92 | +}); | |
93 | + | |
94 | +gulp.task('clean', function () { | |
95 | + return $.del([path.join(conf.paths.dist, '/'), path.join(conf.paths.tmp, '/')]); | |
96 | +}); | |
97 | + | |
98 | +gulp.task('build', ['html', 'fonts', 'other']); | ... | ... |
1 | +++ a/gulp/conf.js | |
... | ... | @@ -0,0 +1,41 @@ |
1 | +/** | |
2 | + * This file contains the variables used in other gulp files | |
3 | + * which defines tasks | |
4 | + * By design, we only put there very generic config values | |
5 | + * which are used in several places to keep good readability | |
6 | + * of the tasks | |
7 | + */ | |
8 | + | |
9 | +var gutil = require('gulp-util'); | |
10 | + | |
11 | +/** | |
12 | + * The main paths of your project handle these with care | |
13 | + */ | |
14 | +exports.paths = { | |
15 | + src: 'src', | |
16 | + dist: 'dist', | |
17 | + tmp: '.tmp', | |
18 | + e2e: 'e2e' | |
19 | +}; | |
20 | + | |
21 | +/** | |
22 | + * Wiredep is the lib which inject bower dependencies in your project | |
23 | + * Mainly used to inject script tags in the index.html but also used | |
24 | + * to inject css preprocessor deps and js files in karma | |
25 | + */ | |
26 | +exports.wiredep = { | |
27 | + exclude: [/jquery/, /\/bootstrap\.js$/, /\/bootstrap-sass\/.*\.js/, /\/bootstrap\.css/], | |
28 | + directory: 'bower_components' | |
29 | +}; | |
30 | + | |
31 | +/** | |
32 | + * Common implementation for an error handler of a Gulp plugin | |
33 | + */ | |
34 | +exports.errorHandler = function(title) { | |
35 | + 'use strict'; | |
36 | + | |
37 | + return function(err) { | |
38 | + gutil.log(gutil.colors.red('[' + title + ']'), err.toString()); | |
39 | + this.emit('end'); | |
40 | + }; | |
41 | +}; | ... | ... |
1 | +++ a/gulp/e2e-tests.js | |
... | ... | @@ -0,0 +1,38 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var gulp = require('gulp'); | |
5 | +var conf = require('./conf'); | |
6 | + | |
7 | +var browserSync = require('browser-sync'); | |
8 | + | |
9 | +var $ = require('gulp-load-plugins')(); | |
10 | + | |
11 | +// Downloads the selenium webdriver | |
12 | +gulp.task('webdriver-update', $.protractor.webdriver_update); | |
13 | + | |
14 | +gulp.task('webdriver-standalone', $.protractor.webdriver_standalone); | |
15 | + | |
16 | +function runProtractor (done) { | |
17 | + var params = process.argv; | |
18 | + var args = params.length > 3 ? [params[3], params[4]] : []; | |
19 | + | |
20 | + gulp.src(path.join(conf.paths.e2e, '/**/*.js')) | |
21 | + .pipe($.protractor.protractor({ | |
22 | + configFile: 'protractor.conf.js', | |
23 | + args: args | |
24 | + })) | |
25 | + .on('error', function (err) { | |
26 | + // Make sure failed tests cause gulp to exit non-zero | |
27 | + throw err; | |
28 | + }) | |
29 | + .on('end', function () { | |
30 | + // Close browser sync server | |
31 | + browserSync.exit(); | |
32 | + done(); | |
33 | + }); | |
34 | +} | |
35 | + | |
36 | +gulp.task('protractor', ['protractor:src']); | |
37 | +gulp.task('protractor:src', ['serve:e2e', 'webdriver-update'], runProtractor); | |
38 | +gulp.task('protractor:dist', ['serve:e2e-dist', 'webdriver-update'], runProtractor); | ... | ... |
1 | +++ a/gulp/inject.js | |
... | ... | @@ -0,0 +1,42 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var gulp = require('gulp'); | |
5 | +var conf = require('./conf'); | |
6 | + | |
7 | +var $ = require('gulp-load-plugins')(); | |
8 | + | |
9 | +var wiredep = require('wiredep').stream; | |
10 | +var _ = require('lodash'); | |
11 | + | |
12 | +var browserSync = require('browser-sync'); | |
13 | + | |
14 | +gulp.task('inject-reload', ['inject'], function() { | |
15 | + browserSync.reload(); | |
16 | +}); | |
17 | + | |
18 | +gulp.task('inject', ['scripts', 'styles'], function () { | |
19 | + var injectStyles = gulp.src([ | |
20 | + path.join(conf.paths.tmp, '/serve/app/**/*.css'), | |
21 | + path.join('!' + conf.paths.tmp, '/serve/app/vendor.css') | |
22 | + ], { read: false }); | |
23 | + | |
24 | + var injectScripts = gulp.src([ | |
25 | + path.join(conf.paths.src, '/app/**/*.module.js'), | |
26 | + path.join(conf.paths.src, '/app/**/*.js'), | |
27 | + path.join('!' + conf.paths.src, '/app/**/*.spec.js'), | |
28 | + path.join('!' + conf.paths.src, '/app/**/*.mock.js'), | |
29 | + ]) | |
30 | + .pipe($.angularFilesort()).on('error', conf.errorHandler('AngularFilesort')); | |
31 | + | |
32 | + var injectOptions = { | |
33 | + ignorePath: [conf.paths.src, path.join(conf.paths.tmp, '/serve')], | |
34 | + addRootSlash: false | |
35 | + }; | |
36 | + | |
37 | + return gulp.src(path.join(conf.paths.src, '/*.html')) | |
38 | + .pipe($.inject(injectStyles, injectOptions)) | |
39 | + .pipe($.inject(injectScripts, injectOptions)) | |
40 | + .pipe(wiredep(_.extend({}, conf.wiredep))) | |
41 | + .pipe(gulp.dest(path.join(conf.paths.tmp, '/serve'))); | |
42 | +}); | ... | ... |
1 | +++ a/gulp/scripts.js | |
... | ... | @@ -0,0 +1,26 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var gulp = require('gulp'); | |
5 | +var conf = require('./conf'); | |
6 | + | |
7 | +var browserSync = require('browser-sync'); | |
8 | + | |
9 | +var $ = require('gulp-load-plugins')(); | |
10 | + | |
11 | + | |
12 | +gulp.task('scripts-reload', function() { | |
13 | + return buildScripts() | |
14 | + .pipe(browserSync.stream()); | |
15 | +}); | |
16 | + | |
17 | +gulp.task('scripts', function() { | |
18 | + return buildScripts(); | |
19 | +}); | |
20 | + | |
21 | +function buildScripts() { | |
22 | + return gulp.src(path.join(conf.paths.src, '/app/**/*.js')) | |
23 | + .pipe($.eslint()) | |
24 | + .pipe($.eslint.format()) | |
25 | + .pipe($.size()) | |
26 | +}; | ... | ... |
1 | +++ a/gulp/server.js | |
... | ... | @@ -0,0 +1,63 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var gulp = require('gulp'); | |
5 | +var conf = require('./conf'); | |
6 | + | |
7 | +var browserSync = require('browser-sync'); | |
8 | +var browserSyncSpa = require('browser-sync-spa'); | |
9 | + | |
10 | +var util = require('util'); | |
11 | + | |
12 | +var proxyMiddleware = require('http-proxy-middleware'); | |
13 | + | |
14 | +function browserSyncInit(baseDir, browser) { | |
15 | + browser = browser === undefined ? 'default' : browser; | |
16 | + | |
17 | + var routes = null; | |
18 | + if(baseDir === conf.paths.src || (util.isArray(baseDir) && baseDir.indexOf(conf.paths.src) !== -1)) { | |
19 | + routes = { | |
20 | + '/bower_components': 'bower_components' | |
21 | + }; | |
22 | + } | |
23 | + | |
24 | + var server = { | |
25 | + baseDir: baseDir, | |
26 | + routes: routes | |
27 | + }; | |
28 | + | |
29 | + /* | |
30 | + * You can add a proxy to your backend by uncommenting the line below. | |
31 | + * You just have to configure a context which will we redirected and the target url. | |
32 | + * Example: $http.get('/users') requests will be automatically proxified. | |
33 | + * | |
34 | + * For more details and option, https://github.com/chimurai/http-proxy-middleware/blob/v0.9.0/README.md | |
35 | + */ | |
36 | + // server.middleware = proxyMiddleware('/users', {target: 'http://jsonplaceholder.typicode.com', changeOrigin: true}); | |
37 | + | |
38 | + browserSync.instance = browserSync.init({ | |
39 | + startPath: '/', | |
40 | + server: server, | |
41 | + browser: browser | |
42 | + }); | |
43 | +} | |
44 | + | |
45 | +browserSync.use(browserSyncSpa({ | |
46 | + selector: '[ng-app]'// Only needed for angular apps | |
47 | +})); | |
48 | + | |
49 | +gulp.task('serve', ['watch'], function () { | |
50 | + browserSyncInit([path.join(conf.paths.tmp, '/serve'), conf.paths.src]); | |
51 | +}); | |
52 | + | |
53 | +gulp.task('serve:dist', ['build'], function () { | |
54 | + browserSyncInit(conf.paths.dist); | |
55 | +}); | |
56 | + | |
57 | +gulp.task('serve:e2e', ['inject'], function () { | |
58 | + browserSyncInit([conf.paths.tmp + '/serve', conf.paths.src], []); | |
59 | +}); | |
60 | + | |
61 | +gulp.task('serve:e2e-dist', ['build'], function () { | |
62 | + browserSyncInit(conf.paths.dist, []); | |
63 | +}); | ... | ... |
1 | +++ a/gulp/styles.js | |
... | ... | @@ -0,0 +1,54 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var gulp = require('gulp'); | |
5 | +var conf = require('./conf'); | |
6 | + | |
7 | +var browserSync = require('browser-sync'); | |
8 | + | |
9 | +var $ = require('gulp-load-plugins')(); | |
10 | + | |
11 | +var wiredep = require('wiredep').stream; | |
12 | +var _ = require('lodash'); | |
13 | + | |
14 | +gulp.task('styles-reload', ['styles'], function() { | |
15 | + return buildStyles() | |
16 | + .pipe(browserSync.stream()); | |
17 | +}); | |
18 | + | |
19 | +gulp.task('styles', function() { | |
20 | + return buildStyles(); | |
21 | +}); | |
22 | + | |
23 | +var buildStyles = function() { | |
24 | + var sassOptions = { | |
25 | + style: 'expanded' | |
26 | + }; | |
27 | + | |
28 | + var injectFiles = gulp.src([ | |
29 | + path.join(conf.paths.src, '/app/**/*.scss'), | |
30 | + path.join('!' + conf.paths.src, '/app/index.scss') | |
31 | + ], { read: false }); | |
32 | + | |
33 | + var injectOptions = { | |
34 | + transform: function(filePath) { | |
35 | + filePath = filePath.replace(conf.paths.src + '/app/', ''); | |
36 | + return '@import "' + filePath + '";'; | |
37 | + }, | |
38 | + starttag: '// injector', | |
39 | + endtag: '// endinjector', | |
40 | + addRootSlash: false | |
41 | + }; | |
42 | + | |
43 | + | |
44 | + return gulp.src([ | |
45 | + path.join(conf.paths.src, '/app/index.scss') | |
46 | + ]) | |
47 | + .pipe($.inject(injectFiles, injectOptions)) | |
48 | + .pipe(wiredep(_.extend({}, conf.wiredep))) | |
49 | + .pipe($.sourcemaps.init()) | |
50 | + .pipe($.sass(sassOptions)).on('error', conf.errorHandler('Sass')) | |
51 | + .pipe($.autoprefixer()).on('error', conf.errorHandler('Autoprefixer')) | |
52 | + .pipe($.sourcemaps.write()) | |
53 | + .pipe(gulp.dest(path.join(conf.paths.tmp, '/serve/app/'))); | |
54 | +}; | ... | ... |
1 | +++ a/gulp/unit-tests.js | |
... | ... | @@ -0,0 +1,52 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var gulp = require('gulp'); | |
5 | +var conf = require('./conf'); | |
6 | + | |
7 | +var karma = require('karma'); | |
8 | + | |
9 | +var pathSrcHtml = [ | |
10 | + path.join(conf.paths.src, '/**/*.html') | |
11 | +]; | |
12 | + | |
13 | +var pathSrcJs = [ | |
14 | + path.join(conf.paths.src, '/**/!(*.spec).js') | |
15 | +]; | |
16 | + | |
17 | +function runTests (singleRun, done) { | |
18 | + var reporters = ['progress']; | |
19 | + var preprocessors = {}; | |
20 | + | |
21 | + pathSrcHtml.forEach(function(path) { | |
22 | + preprocessors[path] = ['ng-html2js']; | |
23 | + }); | |
24 | + | |
25 | + if (singleRun) { | |
26 | + pathSrcJs.forEach(function(path) { | |
27 | + preprocessors[path] = ['coverage']; | |
28 | + }); | |
29 | + reporters.push('coverage') | |
30 | + } | |
31 | + | |
32 | + var localConfig = { | |
33 | + configFile: path.join(__dirname, '/../karma.conf.js'), | |
34 | + singleRun: singleRun, | |
35 | + autoWatch: !singleRun, | |
36 | + reporters: reporters, | |
37 | + preprocessors: preprocessors | |
38 | + }; | |
39 | + | |
40 | + var server = new karma.Server(localConfig, function(failCount) { | |
41 | + done(failCount ? new Error("Failed " + failCount + " tests.") : null); | |
42 | + }) | |
43 | + server.start(); | |
44 | +} | |
45 | + | |
46 | +gulp.task('test', ['scripts'], function(done) { | |
47 | + runTests(true, done); | |
48 | +}); | |
49 | + | |
50 | +gulp.task('test:auto', ['watch'], function(done) { | |
51 | + runTests(false, done); | |
52 | +}); | ... | ... |
1 | +++ a/gulp/watch.js | |
... | ... | @@ -0,0 +1,39 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var gulp = require('gulp'); | |
5 | +var conf = require('./conf'); | |
6 | + | |
7 | +var browserSync = require('browser-sync'); | |
8 | + | |
9 | +function isOnlyChange(event) { | |
10 | + return event.type === 'changed'; | |
11 | +} | |
12 | + | |
13 | +gulp.task('watch', ['inject'], function () { | |
14 | + | |
15 | + gulp.watch([path.join(conf.paths.src, '/*.html'), 'bower.json'], ['inject-reload']); | |
16 | + | |
17 | + gulp.watch([ | |
18 | + path.join(conf.paths.src, '/app/**/*.css'), | |
19 | + path.join(conf.paths.src, '/app/**/*.scss') | |
20 | + ], function(event) { | |
21 | + if(isOnlyChange(event)) { | |
22 | + gulp.start('styles-reload'); | |
23 | + } else { | |
24 | + gulp.start('inject-reload'); | |
25 | + } | |
26 | + }); | |
27 | + | |
28 | + gulp.watch(path.join(conf.paths.src, '/app/**/*.js'), function(event) { | |
29 | + if(isOnlyChange(event)) { | |
30 | + gulp.start('scripts-reload'); | |
31 | + } else { | |
32 | + gulp.start('inject-reload'); | |
33 | + } | |
34 | + }); | |
35 | + | |
36 | + gulp.watch(path.join(conf.paths.src, '/app/**/*.html'), function(event) { | |
37 | + browserSync.reload(event.path); | |
38 | + }); | |
39 | +}); | ... | ... |
1 | +++ a/gulpfile.js | |
... | ... | @@ -0,0 +1,29 @@ |
1 | +/** | |
2 | + * Welcome to your gulpfile! | |
3 | + * The gulp tasks are splitted in several files in the gulp directory | |
4 | + * because putting all here was really too long | |
5 | + */ | |
6 | + | |
7 | +'use strict'; | |
8 | + | |
9 | +var gulp = require('gulp'); | |
10 | +var wrench = require('wrench'); | |
11 | + | |
12 | +/** | |
13 | + * This will load all js or coffee files in the gulp directory | |
14 | + * in order to load all gulp tasks | |
15 | + */ | |
16 | +wrench.readdirSyncRecursive('./gulp').filter(function(file) { | |
17 | + return (/\.(js|coffee)$/i).test(file); | |
18 | +}).map(function(file) { | |
19 | + require('./gulp/' + file); | |
20 | +}); | |
21 | + | |
22 | + | |
23 | +/** | |
24 | + * Default task clean temporaries directories and launch the | |
25 | + * main optimization build task | |
26 | + */ | |
27 | +gulp.task('default', ['clean'], function () { | |
28 | + gulp.start('build'); | |
29 | +}); | ... | ... |
1 | +++ a/karma.conf.js | |
... | ... | @@ -0,0 +1,110 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var path = require('path'); | |
4 | +var conf = require('./gulp/conf'); | |
5 | + | |
6 | +var _ = require('lodash'); | |
7 | +var wiredep = require('wiredep'); | |
8 | + | |
9 | +var pathSrcHtml = [ | |
10 | + path.join(conf.paths.src, '/**/*.html') | |
11 | +]; | |
12 | + | |
13 | +function listFiles() { | |
14 | + var wiredepOptions = _.extend({}, conf.wiredep, { | |
15 | + dependencies: true, | |
16 | + devDependencies: true | |
17 | + }); | |
18 | + | |
19 | + var patterns = wiredep(wiredepOptions).js | |
20 | + .concat([ | |
21 | + path.join(conf.paths.src, '/app/**/*.module.js'), | |
22 | + path.join(conf.paths.src, '/app/**/*.js'), | |
23 | + path.join(conf.paths.src, '/**/*.spec.js'), | |
24 | + path.join(conf.paths.src, '/**/*.mock.js'), | |
25 | + ]) | |
26 | + .concat(pathSrcHtml); | |
27 | + | |
28 | + var files = patterns.map(function(pattern) { | |
29 | + return { | |
30 | + pattern: pattern | |
31 | + }; | |
32 | + }); | |
33 | + files.push({ | |
34 | + pattern: path.join(conf.paths.src, '/assets/**/*'), | |
35 | + included: false, | |
36 | + served: true, | |
37 | + watched: false | |
38 | + }); | |
39 | + return files; | |
40 | +} | |
41 | + | |
42 | +module.exports = function(config) { | |
43 | + | |
44 | + var configuration = { | |
45 | + files: listFiles(), | |
46 | + | |
47 | + singleRun: true, | |
48 | + | |
49 | + autoWatch: false, | |
50 | + | |
51 | + ngHtml2JsPreprocessor: { | |
52 | + stripPrefix: conf.paths.src + '/', | |
53 | + moduleName: 'angular' | |
54 | + }, | |
55 | + | |
56 | + logLevel: 'WARN', | |
57 | + | |
58 | + frameworks: ['jasmine', 'angular-filesort'], | |
59 | + | |
60 | + angularFilesort: { | |
61 | + whitelist: [path.join(conf.paths.src, '/**/!(*.html|*.spec|*.mock).js')] | |
62 | + }, | |
63 | + | |
64 | + browsers : ['PhantomJS'], | |
65 | + | |
66 | + plugins : [ | |
67 | + 'karma-phantomjs-launcher', | |
68 | + 'karma-angular-filesort', | |
69 | + 'karma-coverage', | |
70 | + 'karma-jasmine', | |
71 | + 'karma-ng-html2js-preprocessor' | |
72 | + ], | |
73 | + | |
74 | + coverageReporter: { | |
75 | + type : 'html', | |
76 | + dir : 'coverage/' | |
77 | + }, | |
78 | + | |
79 | + reporters: ['progress'], | |
80 | + | |
81 | + proxies: { | |
82 | + '/assets/': path.join('/base/', conf.paths.src, '/assets/') | |
83 | + } | |
84 | + }; | |
85 | + | |
86 | + // This is the default preprocessors configuration for a usage with Karma cli | |
87 | + // The coverage preprocessor is added in gulp/unit-test.js only for single tests | |
88 | + // It was not possible to do it there because karma doesn't let us now if we are | |
89 | + // running a single test or not | |
90 | + configuration.preprocessors = {}; | |
91 | + pathSrcHtml.forEach(function(path) { | |
92 | + configuration.preprocessors[path] = ['ng-html2js']; | |
93 | + }); | |
94 | + | |
95 | + // This block is needed to execute Chrome on Travis | |
96 | + // If you ever plan to use Chrome and Travis, you can keep it | |
97 | + // If not, you can safely remove it | |
98 | + // https://github.com/karma-runner/karma/issues/1144#issuecomment-53633076 | |
99 | + if(configuration.browsers[0] === 'Chrome' && process.env.TRAVIS) { | |
100 | + configuration.customLaunchers = { | |
101 | + 'chrome-travis-ci': { | |
102 | + base: 'Chrome', | |
103 | + flags: ['--no-sandbox'] | |
104 | + } | |
105 | + }; | |
106 | + configuration.browsers = ['chrome-travis-ci']; | |
107 | + } | |
108 | + | |
109 | + config.set(configuration); | |
110 | +}; | ... | ... |
1 | +++ a/package.json | |
... | ... | @@ -0,0 +1,55 @@ |
1 | +{ | |
2 | + "name": "angular", | |
3 | + "version": "0.0.0", | |
4 | + "dependencies": {}, | |
5 | + "scripts": { | |
6 | + "test": "gulp test" | |
7 | + }, | |
8 | + "devDependencies": { | |
9 | + "estraverse": "~4.1.0", | |
10 | + "gulp": "~3.9.0", | |
11 | + "gulp-autoprefixer": "~3.0.2", | |
12 | + "gulp-angular-templatecache": "~1.8.0", | |
13 | + "del": "~2.0.2", | |
14 | + "lodash": "~3.10.1", | |
15 | + "gulp-minify-css": "~1.2.1", | |
16 | + "gulp-filter": "~3.0.1", | |
17 | + "gulp-flatten": "~0.2.0", | |
18 | + "gulp-eslint": "~1.0.0", | |
19 | + "eslint-plugin-angular": "~0.12.0", | |
20 | + "gulp-load-plugins": "~0.10.0", | |
21 | + "gulp-size": "~2.0.0", | |
22 | + "gulp-uglify": "~1.4.1", | |
23 | + "gulp-useref": "~1.3.0", | |
24 | + "gulp-util": "~3.0.6", | |
25 | + "gulp-ng-annotate": "~1.1.0", | |
26 | + "gulp-replace": "~0.5.4", | |
27 | + "gulp-rename": "~1.2.2", | |
28 | + "gulp-rev": "~6.0.1", | |
29 | + "gulp-rev-replace": "~0.4.2", | |
30 | + "gulp-minify-html": "~1.0.4", | |
31 | + "gulp-inject": "~3.0.0", | |
32 | + "gulp-protractor": "~1.0.0", | |
33 | + "gulp-sourcemaps": "~1.6.0", | |
34 | + "gulp-sass": "~2.0.4", | |
35 | + "gulp-angular-filesort": "~1.1.1", | |
36 | + "main-bower-files": "~2.9.0", | |
37 | + "wiredep": "~2.2.2", | |
38 | + "karma": "~0.13.10", | |
39 | + "karma-jasmine": "~0.3.6", | |
40 | + "karma-phantomjs-launcher": "~0.2.1", | |
41 | + "phantomjs": "~1.9.18", | |
42 | + "karma-angular-filesort": "~1.0.0", | |
43 | + "karma-coverage": "~0.5.2", | |
44 | + "karma-ng-html2js-preprocessor": "~0.2.0", | |
45 | + "browser-sync": "~2.9.11", | |
46 | + "browser-sync-spa": "~1.0.3", | |
47 | + "http-proxy-middleware": "~0.9.0", | |
48 | + "chalk": "~1.1.1", | |
49 | + "uglify-save-license": "~0.4.1", | |
50 | + "wrench": "~1.5.8" | |
51 | + }, | |
52 | + "engines": { | |
53 | + "node": ">=0.10.0" | |
54 | + } | |
55 | +} | ... | ... |
1 | +++ a/protractor.conf.js | |
... | ... | @@ -0,0 +1,27 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +var paths = require('./.yo-rc.json')['generator-gulp-angular'].props.paths; | |
4 | + | |
5 | +// An example configuration file. | |
6 | +exports.config = { | |
7 | + // The address of a running selenium server. | |
8 | + //seleniumAddress: 'http://localhost:4444/wd/hub', | |
9 | + //seleniumServerJar: deprecated, this should be set on node_modules/protractor/config.json | |
10 | + | |
11 | + // Capabilities to be passed to the webdriver instance. | |
12 | + capabilities: { | |
13 | + 'browserName': 'chrome' | |
14 | + }, | |
15 | + | |
16 | + baseUrl: 'http://localhost:3000', | |
17 | + | |
18 | + // Spec patterns are relative to the current working directory when | |
19 | + // protractor is called. | |
20 | + specs: [paths.e2e + '/**/*.js'], | |
21 | + | |
22 | + // Options to be passed to Jasmine-node. | |
23 | + jasmineNodeOpts: { | |
24 | + showColors: true, | |
25 | + defaultTimeoutInterval: 30000 | |
26 | + } | |
27 | +}; | ... | ... |
src/app/components/githubContributor/githubContributor.service.js
0 → 100644
1 | +++ a/src/app/components/githubContributor/githubContributor.service.js | |
... | ... | @@ -0,0 +1,37 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + angular | |
5 | + .module('angular') | |
6 | + .factory('githubContributor', githubContributor); | |
7 | + | |
8 | + /** @ngInject */ | |
9 | + function githubContributor($log, $http) { | |
10 | + var apiHost = 'https://api.github.com/repos/Swiip/generator-gulp-angular'; | |
11 | + | |
12 | + var service = { | |
13 | + apiHost: apiHost, | |
14 | + getContributors: getContributors | |
15 | + }; | |
16 | + | |
17 | + return service; | |
18 | + | |
19 | + function getContributors(limit) { | |
20 | + if (!limit) { | |
21 | + limit = 30; | |
22 | + } | |
23 | + | |
24 | + return $http.get(apiHost + '/contributors?per_page=' + limit) | |
25 | + .then(getContributorsComplete) | |
26 | + .catch(getContributorsFailed); | |
27 | + | |
28 | + function getContributorsComplete(response) { | |
29 | + return response.data; | |
30 | + } | |
31 | + | |
32 | + function getContributorsFailed(error) { | |
33 | + $log.error('XHR Failed for getContributors.\n' + angular.toJson(error.data, true)); | |
34 | + } | |
35 | + } | |
36 | + } | |
37 | +})(); | ... | ... |
src/app/components/githubContributor/githubContributor.service.spec.js
0 → 100644
1 | +++ a/src/app/components/githubContributor/githubContributor.service.spec.js | |
... | ... | @@ -0,0 +1,62 @@ |
1 | +(function() { | |
2 | + 'use strict'; | |
3 | + | |
4 | + describe('service githubContributor', function() { | |
5 | + var githubContributor; | |
6 | + var $httpBackend; | |
7 | + var $log; | |
8 | + | |
9 | + beforeEach(module('angular')); | |
10 | + beforeEach(inject(function(_githubContributor_, _$httpBackend_, _$log_) { | |
11 | + githubContributor = _githubContributor_; | |
12 | + $httpBackend = _$httpBackend_; | |
13 | + $log = _$log_; | |
14 | + })); | |
15 | + | |
16 | + it('should be registered', function() { | |
17 | + expect(githubContributor).not.toEqual(null); | |
18 | + }); | |
19 | + | |
20 | + describe('apiHost variable', function() { | |
21 | + it('should exist', function() { | |
22 | + expect(githubContributor.apiHost).not.toEqual(null); | |
23 | + }); | |
24 | + }); | |
25 | + | |
26 | + describe('getContributors function', function() { | |
27 | + it('should exist', function() { | |
28 | + expect(githubContributor.getContributors).not.toEqual(null); | |
29 | + }); | |
30 | + | |
31 | + it('should return data', function() { | |
32 | + $httpBackend.when('GET', githubContributor.apiHost + '/contributors?per_page=1').respond(200, [{pprt: 'value'}]); | |
33 | + var data; | |
34 | + githubContributor.getContributors(1).then(function(fetchedData) { | |
35 | + data = fetchedData; | |
36 | + }); | |
37 | + $httpBackend.flush(); | |
38 | + expect(data).toEqual(jasmine.any(Array)); | |
39 | + expect(data.length === 1).toBeTruthy(); | |
40 | + expect(data[0]).toEqual(jasmine.any(Object)); | |
41 | + }); | |
42 | + | |
43 | + it('should define a limit per page as default value', function() { | |
44 | + $httpBackend.when('GET', githubContributor.apiHost + '/contributors?per_page=30').respond(200, new Array(30)); | |
45 | + var data; | |
46 | + githubContributor.getContributors().then(function(fetchedData) { | |
47 | + data = fetchedData; | |
48 | + }); | |