And we are looking for more!
This is frontend only
Ideal: backend & frontend in one CD pipeline
concat: { options: { separator: '\n;' }, app: { src: [ '<%= jsSrcDir %>/js/**/*.js', ], dest: '<%= jsTargetDir %>/app.js' } }
uglify: { app: { files: { '<%= jsTargetDir %>/app.min.js': [ '<%= jsTargetDir %>/app.js' ], } } }
.img-foo { background-image: inline-image("foo.png"); }
sass: { app: { options: { compass: true, }, files: { '<%= cssTargetDir %>/master.css': '<%= cssSrcDir %>/master.scss', } } },
.img-foo { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAA...'); }
versioning: { options: { grepFiles: [ '<%= appTargetDir %>/**/*.html', ] }, css: { src: [ '<%= cssTargetDir %>/app.min.css', ] }, js: { src: [ '<%= jsTargetDir %>/app.min.js', '<%= jsTargetDir %>/vendor.min.js', ] }, },
<!DOCTYPE html> <html lang="en"> <head> ... <link href="css/app.min.css" rel="stylesheet"> ... </head> <body> ... <script src="js/vendor.min.js" type="text/javascript"></script> <script src="js/app.min.js" type="text/javascript"></script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> ... <link href="css/app.min.b678e30139fc04.css" rel="stylesheet"> ... </head> <body> ... <script src="js/vendor.min.dda09628f6e1da.js" type="text/javascript"></script> <script src="js/app.min.8e46534a4f66158.js" type="text/javascript"></script> </body> </html>
Production | Development | |
JS | concatenated, minified | source files, not minified |
CSS | compiled (SASS), concatenated, minified | only compiled (SASS) |
Images | Embedded into CSS | Embedded into CSS (by Sass/Compass) |
HTML | references optimized assets | references source assets |
<!DOCTYPE html> <html lang="en"> <head> ... <!-- build:css css/app.min.css --> <link rel="stylesheet" href="css/master.css"> <link rel="stylesheet" href="css/dashboard.css"> ... <!-- /build --> </head> <body> <!-- build:js js/app.min.js --> <script src="js/app.js" type="text/javascript"></script> <script src="js/routes.js" type="text/javascript"></script> ... <!-- /build --> </body> </html>
processhtml: { dist: { files: { '<%= appTargetDir %>/index.html': ['<%= appSrcDir %>/index.html'] } } },Alternative: grunt-usemin to concat, minify & replace in one step
watch: { files: [ '<%= jsSrcDir %>/**/*.js', '<%= cssSrcDir %>/**/*.scss', '<%= htmlSrcDir %>/**/*.html', ], tasks: [ 'dev-build', ], options: { livereload: true, } }
grunt.registerTask('dev-build', [ 'copy:cssThirdParty', 'sass', ]);
var expect = chai.expect; beforeEach(module('project-staffing')); describe('UpperCase Test', function() { it('should convert first charactor to UpperCase', inject(function(uppercaseFilter) { expect(uppercaseFilter('a')).to.equal('A'); expect(uppercaseFilter('hello world')).to.equal('Hello World'); })); });
npm install -g karma-cli karma start karma.conf.js // or grunt karma
var ActivityService; var $http; beforeEach(inject(function(_ActivityService_, _$http_) { ActivityService = _ActivityService_; $http = _$http_; sinon.stub($http, 'post', function(){}); })); describe('Activity Service', function() { it('should have send http POST to backend after saving one activity', inject(function(ActivityService) { ActivityService.saveActivity('user', 'action', 'object'); expect($http.post.callCount).to.equal(1); })); });
Should
chai.should(); foo.should.be.a('string'); foo.should.equal('bar');
Expect
var expect = chai.expect; expect(foo).to.be.a('string'); expect(foo).to.equal('bar');
Assert
var assert = chai.assert; assert.typeOf(foo, 'string'); assert.equal(foo, 'bar');
describe('Manage customer', function() { var ptor; beforeEach(function() { browser.get('/'); ptor = protractor.getInstance(); element(by.id('navEmployees')).click(); element(by.id('navListEmployees')).click(); }); it('should navigate to list employees page', function() { expect(ptor.getCurrentUrl()).toMatch(/#\/list-employees/); }); });
it('should find employee Maria on list search page', function() { createMultipleEmployees(); // Creates employees: Max, Maria, Daniel, John ... element(by.id('searchText')).sendKeys('Ma'); expect(element.all(by.id('employee')).count()).toBe(2); element(by.id('searchText')).sendKeys('ria'); expect(element.all(by.id('employee')).count()).toBe(1); });
npm install -g protractor webdriver-manager start protractor test/client/e2e/conf.js
http://54.75.209.193/jenkins/view/EnterJS-Pipeline/
Info: Server will be shutdown after talk
project-staffing git:(master) ✗ docker-compose Commands: build Build or rebuild services help Get help on a command kill Kill containers logs View output from containers port Print the public port for a port binding ps List containers pull Pulls service images rm Remove stopped containers run Run a one-off command scale Set number of containers for a service start Start services stop Stop services restart Restart services up Create and start containers
➜ project-staffing git:(master) ✗ docker-compose up Recreating projectstaffing_mongodb_1... Creating projectstaffing_nodejsserver_1... Building nodejsserver... Step 0 : FROM tcnksm/centos-ruby ---> 255207061af8 Step 1 : RUN yum install -y npm ---> Using cache ---> c8ca0ad1bec0 Step 2 : COPY . /opt/project-staffing/ ---> dc70b159f357 ... Step 5 : CMD node /opt/project-staffing/server.js ---> Running in 78d831b9f0f0 ---> 88b07ba248a0 Successfully built 88b07ba248a0 ...
Updated Slides
Project Documentation
Source Code @ Github
Do you have comments or questions?