Remove gulp with simpler npm tasks

This removes `gulp` and provides a simpler `karma` and `webpack`,
`webpack-watch` npm scripts.

For actual development, users will need the Rails stack anyway, so it
won't make sense to keep a separate set of dependencies up to date.

* Instead of `gulp webpack`, use `npm run webpack`.
* Instead of `gulp watch`, use `npm run webpack-watch`, which is *drastically* faster than gulp watch-polling.
* Instead of `gulp tests:karma` use `npm run karma`, or just `npm test`.

This also removes all traces of express and restores the Rails
styleguide. It is not whitelisted for precompilation and is only
available in the context of the development mode.

To access the styleguide, use `/assets/styleguide.html`.
pull/4356/head
Oliver Günther 9 years ago
parent 3848c8aef0
commit e49c163d00
  1. 3
      .gitignore
  2. 2
      Gemfile
  3. 13
      Gemfile.lock
  4. 4
      Procfile.dev
  5. 1
      app/assets/stylesheets/styleguide.html.lsg
  6. 16
      app/assets/stylesheets/styleguide.js
  7. 33
      config/initializers/non_digest_assets.rb
  8. 3
      doc/RUNNING_TESTS.md
  9. 4
      frontend/Gemfile
  10. 21
      frontend/Gemfile.lock
  11. 60
      frontend/app/assets/styleguide.jade
  12. 2
      frontend/app/global.js
  13. 2
      frontend/app/openproject-app.js
  14. 18
      frontend/doc/BUILD.md
  15. 2
      frontend/doc/OVERVIEW.md
  16. 10
      frontend/doc/README.md
  17. 46
      frontend/doc/STYLING.md
  18. 201
      frontend/gulpfile.js
  19. 19
      frontend/package.json
  20. 84
      frontend/scripts/karma-runner.js
  21. 4
      package.json

3
.gitignore vendored

@ -81,6 +81,7 @@
.rspec
# coverage in plugins
/lib/plugins/*/coverage
# asset cache
/.sass-cache/
# Frontend debug log
/frontend/npm-debug.log*

@ -112,7 +112,6 @@ group :production do
end
gem 'sprockets', '~> 2.12.3'
gem 'non-stupid-digest-assets'
gem 'sass-rails', '~> 5.0.3'
gem 'sass', '~> 3.4.12'
gem 'autoprefixer-rails'
@ -186,6 +185,7 @@ group :development do
gem 'thin'
gem 'faker'
gem 'quiet_assets'
gem 'livingstyleguide', '~> 2.0.0.alpha.6'
end
group :development, :test do

@ -309,6 +309,12 @@ GEM
addressable (~> 2.3)
letter_opener (1.3.0)
launchy (~> 2.2)
livingstyleguide (2.0.0.alpha.6)
minisyntax (>= 0.2.5)
redcarpet (~> 3.0.0)
sass
thor
tilt
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.3)
@ -316,6 +322,7 @@ GEM
method_source (0.8.2)
mime-types (2.99.1)
mini_portile2 (2.0.0)
minisyntax (0.2.5)
minitest (5.8.0)
mixlib-shellout (2.1.0)
multi_json (1.11.3)
@ -330,7 +337,6 @@ GEM
newrelic_rpm (3.14.1.311)
nokogiri (1.6.7.1)
mini_portile2 (~> 2.0.0.rc2)
non-stupid-digest-assets (1.0.4)
oj (2.14.6)
parallel (1.6.1)
parallel_tests (2.1.2)
@ -420,6 +426,7 @@ GEM
rb-readline (0.5.2)
rdoc (4.2.0)
json (~> 1.4)
redcarpet (3.0.0)
reform (1.2.6)
activemodel
disposable (~> 0.0.5)
@ -601,13 +608,13 @@ DEPENDENCIES
jruby-openssl
json_spec
launchy (~> 2.3.0)
letter_opener
letter_opener (~> 1.3.0)
livingstyleguide (~> 2.0.0.alpha.6)
multi_json (~> 1.11.0)
mysql2 (~> 0.3.20)
net-ldap (~> 0.8.0)
newrelic_rpm
nokogiri (~> 1.6.7)
non-stupid-digest-assets
oj (~> 2.14.6)
omniauth!
openproject-translations!

@ -1,3 +1,3 @@
web: bundle exec unicorn --config-file config/unicorn.rb --host ${HOST:="127.0.0.1"} --port ${PORT:="8080"} --env ${RAILS_ENV:="development"}
assets: cd frontend && $(npm bin)/webpack --colors --watch --progress
web: bundle exec rails server -p ${PORT:="8080"} -b ${HOST:="127.0.0.1"} --env ${RAILS_ENV:="development"}
assets: cd frontend && npm run webpack-watch
worker: bundle exec rake jobs:work

@ -64,7 +64,6 @@
<div class="styleguide-banner">
<h1 class="styleguide-banner--text">Living Style Guide</h1>
</div>
<link rel="stylesheet" type="text/css" href="jstoolbar.css">
</header>
<nav class="styleguide-nav">

@ -28,3 +28,19 @@
//= require ../javascripts/bundles/openproject-global
//= require ../javascripts/tooltips
angular.module('openproject-style-guide', ['ui.select', 'ngSanitize']);
// Add uiComponents to the styleguide.
// In order to be able to do that, we have to mock some
// services that directives in uiComponents rely on.
angular.module('openproject-style-guide')
.service('ActivityService', function() {} )
.service('ConfigurationService', function() {} )
.service('AutoCompleteHelper', function() {} )
.service('NotificationsService', function() {
return {
addError: function() {},
addSuccess: function() {}
};
}).requires.push('openproject.uiComponents');

@ -1,33 +0,0 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
NonStupidDigestAssets.whitelist = [
'styleguide.html',
'styleguide.css',
'styleguide.js'
]

@ -225,6 +225,3 @@ on a machine with 8 parallel instances.
* Sometimes you want to test things manually. Always remember: If you test something more than once, write an automated test for it.
* Assuming you do not have a version of Internet Explorer already installed on your computer, you can grab a VM with preinstalled IE's directly from Microsoft: http://www.modern.ie/en-us/virtualization-tools#downloads
[gulp]:http://gulpjs.com/
[express]:http://expressjs.com/

@ -1,4 +0,0 @@
source 'https://rubygems.org'
gem 'livingstyleguide', '~> 2.0.0.alpha.6'
gem 'sass', '~> 3.4.12'

@ -1,21 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
livingstyleguide (2.0.0.alpha.6)
minisyntax (>= 0.2.5)
redcarpet (~> 3.0.0)
sass
thor
tilt
minisyntax (0.2.5)
redcarpet (3.0.0)
sass (3.4.13)
thor (0.19.1)
tilt (2.0.1)
PLATFORMS
ruby
DEPENDENCIES
livingstyleguide (~> 2.0.0.alpha.6)
sass (~> 3.4.12)

@ -1,60 +0,0 @@
doctype html
html(id="STYLEGUIDE_HTML_ID")
head
meta(charset="utf-8")
meta(content="IE=edge,chrome=1", http-equiv="X-UA-Compatible")
meta(content="The LivingStyleGuide Gem – http://livingstyleguide.org", name="generator")
meta(name="description", content=title)
title= title
link(rel='stylesheet', type='text/css', href='/assets/bundles/openproject-global.css')
!= stylesheet
script(src='/assets/bundles/openproject-global.js')
script(src='/assets/tooltips.js')
script.
angular.module('openproject-style-guide', ['ui.select', 'ngSanitize'])
// Add uiComponents to the styleguide.
// In order to be able to do that, we have to mock some
// services that directives in uiComponents rely on.
angular.module('openproject-style-guide')
.service('ActivityService', function() {} )
.service('ConfigurationService', function() {} )
.service('AutoCompleteHelper', function() {} )
.service('NotificationsService', function() {
return {
addError: function() {},
addSuccess: function() {}
};
})
.requires.push('openproject.uiComponents');
// get all of angular to be known
script(src='/assets/bundles/openproject-core-app.js')
// avoid errors of undefined jsToolBar
script(src='/assets/jstoolbar/jstoolbar.js')
body.livingstyleguide(ng-app='openproject-style-guide', ng-strict-di=true)
header.livingstyleguide--header
.styleguide-banner
h1.styleguide-banner--text= title
nav.styleguide-nav
ul.styleguide-nav--menu-items
li: a(href="#color-variables") Colors
li: a(href="#typography") Typography
li: a(href="#forms") Forms
li: a(href="#flash-messages") Flash Messages
li: a(href="#notifications") Notifications
li: a(href="#buttons") Buttons
li: a(href="#boxes") Boxes
li: a(href="#pagination") Pagination
section.livingstyleguide--intro
p &nbsp;
.livingstyleguide--container
!= content
footer.livingstyleguide--footer
Copyright © 2015 OpenProject - All rights reserved.

@ -34,6 +34,8 @@
// See: https://github.com/webpack/style-loader/issues/31
require('polyfill-function-prototype-bind');
require('i18n');
require('jquery');
require('jquery-migrate/jquery-migrate');
require('jquery-ujs');

@ -26,8 +26,6 @@
// See doc/COPYRIGHT.rdoc for more details.
//++
var I18n = require('./vendor/i18n');
// standard locales
I18n.translations.en = require("locales/js-en.yml").en;

@ -1,11 +1,9 @@
Building
========
__Note__: All tasks involved are found in `./frontend/gulpfile.js`
All builds are put into Rails' asset pipeline. The actual build, i.e. merging all components together is done via [`webpack`](https://github.com/webpack/webpack).
All builds are put into Rails' asset pipeline. Builds are run via [`gulp`](http://gulpjs.com/). The actual build, i.e. merging all components together is done via [`webpack`](https://github.com/webpack/webpack).
It __is important to note__ that OpenProject currently still relies on the asset pipeline to serve the assets. Minification is done via `rake assets:precompile` and does __not__ happen in the `gulp` based pipeline.
It __is important to note__ that OpenProject currently still relies on the asset pipeline to serve the assets. Minification is __not__ done as part of webpack.
Two types of builds are performed, the first one is the OpenProject Standalone JS, which is not required by the Rails views per se. The second one is a bundle of global dependencies, which are necessary for the Rails views to run properly.
@ -15,7 +13,7 @@ The configuration for building both global and standalone JS is found in `./fron
The resulting output of this buildstep can be found in `./app/assets/javascripts/bundles/openproject-core-app.js`
This is done via `gulp webpack` (see `gulpfile.js`, Line 63 ff.). The actual entrypoint for this is `./frontend/app/openproject-app.js`.
This is done via `npm run webpack` (see `frontend/package.json`). The actual entrypoint for this is `./frontend/app/openproject-app.js`.
It contains only the the JavaScript needed for the AngularJS based part of the codebase (and `lodash`).
@ -23,24 +21,20 @@ It contains only the the JavaScript needed for the AngularJS based part of the c
The resulting output of this buildstep can be found in `./app/assets/javascripts/bundles/openproject-global.js`.
This is done via `gulp webpack` (see `gulpfile.js`, Line 63 ff.). The actual entrypoint for this is `./frontend/app/global.js`
This is also built with `npm run webpack`. The actual entrypoint for this is `./frontend/app/global.js`
It contains all of the JavaScript necessary for the rails based views, like parts of `jQuery.ui`, but also `angular` itself.
## Building Sass
Sass files are built via `gulp sass`, which handles the main Sass file from the Rails stack at `./app/assets/stylesheets/defaults.css.sass`, performs transformations on it and outputs the result to `./frontend/public/assets`. It __is important__ to note, that this serves __not__ the compilation of Sass for production purposes but is mostly for the availability of the CSS for the Living Styleguide.
The Sass files in the rails stack are handled as one would expect: They are precompiled into one `default-*.css` for production and are reloaded on demand during development. The manifest for this can be found in `./app/assets/stylesheets/defaults.css.sass`.
### Important note on Frameworks:
OpenProject relies on the [Foundation for Apps Framework](http://foundation.zurb.com/apps), as well as one the [Bourbon Mixin Library](http://bourbon.io/).
They are provided via LoadPath manipulation in the `gulp` based pipeline.The two frameworks are included as `bower` components (see `./frontend/bower.json`).
On the Rails side, both frameworks are included as gems - see the `./Gemfile` - and plugged directly into Rails' asset pipeline.
## Misc Tasks
## Living Styleguide
The build pipeline is also responsible for building the [Living Styleguide](https://github.com/livingstyleguide/livingstyleguide), relying heavily on the duplicated functionality of the `gulp` tasks revolving around Sass compilation
The styleguide is rendered as part of the Rails stack at `/assets/styleguide.html`. Please see [their GitHub](https://github.com/livingstyleguide/livingstyleguide) for more information.

@ -116,5 +116,5 @@ In this example, what would usually happen during compilation is the asynchronou
As there are quite a few directives, the OpenProject frontend prevents the request to the server by using `angular.$templateCache`.
Using a buildstep in the `gulp` process (via `webpack` actually): templates are compiled as JS and put alongside the rest of the code in `openproject-core-app.js`. The `loader` for the templates can be found in `./frontend/webpack.config.js` which is dependent on [`ngtemplate-loader`](https://github.com/WearyMonkey/ngtemplate-loader).
As part of the webpack step (`npm run webpack`), templates are compiled as JS and put alongside the rest of the code in `openproject-core-app.js`. The `loader` for the templates can be found in `./frontend/webpack.config.js` which is dependent on [`ngtemplate-loader`](https://github.com/WearyMonkey/ngtemplate-loader).

@ -1,14 +1,14 @@
# Developing OpenProject Frontend
## Development server
To keep watching the files in the frontend and process them on demand, use `npm run webpack`.
It will keep running a webpack instance with the `--watch` flag set.
To start the development server:
gulp dev
Assets will be automatically loaded as part of the asset pipeline of Rails when you reload the server,
once webpack has completed.
## Living Style Guide
The style guide is available at: <http://localhost:8080/assets/css/styleguide.html>.
The style guide is available as part of the Rails development server at: <http://localhost:5000/assets/styleguide.html>.
## Changing or updating Dependencies

@ -5,29 +5,9 @@ Frontend styling is coupled to the Living Styleguide. The guide implements the s
All styles for OpenProject are found in `./app/assets/stylesheets`. The frontend folder contains no styling, besides rendered files and some styling for the styleguide itself.
## Building
The guide is built via the the `gulp` stack.
The task involved is `gulp styleguide`, which is also part of `gulp watch` and can therefore be executed during `gulp dev`.
`gulp dev` will also start a static server delivering the assets for the styleguide (in contrast to `gulp styleguide`). As long as `gulp dev` runs, the styleguide will be available here:
```
http://localhost:8080/assets/css/styleguide.html
```
The static server will serve the whole `./frontend/public` folder, however, `styleguide.html` is the index for the styleguide.
### A note on the legacy styleguide
In the past, the Styleguide was built using the Rails stack - this was later changed to the `gulp` pipeline. The original version, at the time of writing, is still in the sources - it can be found here: `./app/assets/stylesheets/styleguide.html.lsg`.
This does no longer work, as the main rails stack had the dependency removed, there is no need to update both dependencies.
## Using the styleguide
The styleguide itself is just a long html page demonstrating the components. It can be modified by altering its base file `styleguide.jade` (see `./frontend/app/assets/styleguide.jade`).
The styleguide itself is just a long html page demonstrating the components. It can be modified by altering its base file `styleguide.html` (see `./app/assets/styleguide.html`).
The general approach here is that for every partial of sass there is a Markdown file (`*.lsg`) describing it:
@ -42,30 +22,6 @@ The `lsg` is simple markdown containing information on how to use the component
Ideally, this should be only one component per Sass partial, but this is not always possible, as seen in the case of `./app/assets/stylesheets/content/_work_packages.sass` which describes an area of the application instead of a single component.
### Getting JavaScript to work with the Styleguide
In an ideal world, the styleguide would convey only styling-related information. Unfortunately, for practical purposes such as styling `ui.select` which requires some JavaScript to be active, the styleguide introduces some custom JavaScript:
```jade
//from styleguide.jade
script(src='/assets/bundles/openproject-global.js')
script.
angular.module('openproject-style-guide', ['ui.select', 'ngSanitize'])
```
The styleguide defines and initializes its own `angular.module`, which can be injected with various dependencies. The `ng-app` is present for all of the styleguide (attached to `body`).
__Note on magic__: The static server can actually serve `/assets/bundles/openproject-global.js` because of a line in `./frontend/server.js`:
```javascript
app.use('/assets', express.static(railsRoot + '/app/assets/javascripts'));
app.use('/assets', express.static(railsRoot + '/app/assets/images'));
```
This enables asset serving from the respective Rails directories.
If you want to add more JavaScript to it, you can directly include it in the `styleguide.jade`, _but_ it is ill-advised. The styleguide should be used for the styling of the rendered output and not necessarily display functionality, mostly to avoid duplication of code (use a test to demonstrate functionality!).
## A note on the css style used
Originally introduced by `@myabc`, Sass-Code should ideally follow a convention as described in [Simple naming for CSS class names](http://www.hagenburger.net/BLOG/Modular-CSS-Class-Names.html).

@ -1,201 +0,0 @@
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
var path = require('path');
var gulp = require('gulp');
var jshint = require('gulp-jshint');
var gulpWebpack = require('gulp-webpack');
var webpack = require('webpack');
var config = require('./webpack.config.js');
var sass = require('gulp-ruby-sass');
var watch = require('gulp-watch');
var autoprefixer = require('gulp-autoprefixer');
var livingstyleguide = require('gulp-livingstyleguide');
var gulpFilter = require('gulp-filter');
var replace = require('gulp-replace');
var tsproject = require('tsproject');
var karma = require('karma');
var fs = require('fs');
var server;
var paths = {
scripts: [
'app/**/*.js',
'!app/vendor/**/*.js'
],
fonts: '../app/assets/fonts/**/*',
styleguide: '../app/assets/stylesheets/styleguide.html.lsg'
};
var deleteFolderRecursive = function(path) {
if( fs.existsSync(path) ) {
fs.readdirSync(path).forEach(function(file){
var curPath = path + "/" + file;
if(fs.lstatSync(curPath).isDirectory()) {
deleteFolderRecursive(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
};
gulp.task('lint', function() {
return gulp.src(paths.scripts)
.pipe(jshint('.jshintrc'))
.pipe(jshint.reporter('jshint-stylish'));
});
gulp.task('webpack', function() {
return gulp.src('app/openproject-app.js')
.pipe(gulpWebpack(config))
.pipe(gulp.dest('../app/assets/javascripts/bundles'));
});
gulp.task('fonts', function() {
return gulp.src(paths.fonts).pipe(gulp.dest('./public/assets/css'));
});
gulp.task('sass', function() {
return gulp.src('../app/assets/stylesheets/default.css.sass')
.pipe(sass({
'sourcemap=none': true,
bundleExec: true,
loadPath: [
'./bower_components/foundation-apps/scss',
'./bower_components/bourbon/app/assets/stylesheets'
]
}))
// HACK: remove asset helper that is only available with asset pipeline
.pipe(replace(/image\-url\(\"/g, 'url("/assets/'))
.pipe(autoprefixer({
cascade: false
}))
.on('error', function(err) {
console.log(err.message);
})
.pipe(gulp.dest('public/assets/css'));
});
gulp.task('styleguide', function () {
process.env.SASS_PATH = [
'../app/assets/stylesheets',
'./bower_components/foundation-apps/scss',
'./bower_components/bourbon/app/assets/stylesheets'
].join(':');
var cssFilter = gulpFilter('**/*.css'),
htmlFilter = gulpFilter('**/*.html');
gulp.src(paths.styleguide)
.pipe(livingstyleguide({template: 'app/assets/styleguide.jade'}))
.pipe(cssFilter)
.pipe(replace(/image\-url\(\"/g, 'url("/assets/'))
.pipe(autoprefixer({
cascade: false
}))
.pipe(cssFilter.restore())
.pipe(htmlFilter)
.pipe(replace(/STYLEGUIDE_HTML_ID/,
path.dirname(path.resolve(paths.styleguide)) + '/styleguide')
)
.pipe(htmlFilter.restore())
.pipe(gulp.dest('public/assets/css'));
});
gulp.task('express', function(done) {
var expressApp = require('./server');
var port = process.env.PORT || 8080;
(function startServer(port) {
server = expressApp.listen(port, function() {
console.log('Starting express server at localhost:%d', port);
done();
});
server.on('error', function(err) {
if (err.code === 'EADDRINUSE') {
console.warn('Port %d already in use.', port);
startServer(++port);
}
});
})(port);
});
gulp.task('default', ['webpack', 'fonts', 'styleguide', 'sass', 'express']);
gulp.task('dev', ['default', 'watch']);
gulp.task('watch', function() {
gulp.watch('app/**/*.js', ['webpack']);
gulp.watch('app/**/*.html', ['webpack']);
gulp.watch('config/locales/js-*.yml', ['webpack']);
gulp.watch('app/templates/**/*.html', ['webpack']);
gulp.watch('../app/assets/stylesheets/**/*.scss', ['sass', 'styleguide']);
gulp.watch('../app/assets/stylesheets/**/*.sass', ['sass', 'styleguide']);
gulp.watch('../app/assets/stylesheets/**/*.lsg', ['styleguide']);
});
var tsOutDir = __dirname + '/tests/unit/tests/typescript';
gulp.task('typescript-tests', function () {
deleteFolderRecursive(tsOutDir);
return tsproject.src('./tsconfig.test.json', {
compilerOptions: {
outDir: tsOutDir
}
}).pipe(gulp.dest('.'));
});
gulp.task('tests:karma', ['typescript-tests'], function () {
karma.server.start(
{
configFile: __dirname + '/karma.conf.js',
singleRun: true
},
function (exitCode) {
if(exitCode === 0) {
console.info('No tests have failed');
console.info('Files generated by tsc were deleted.');
deleteFolderRecursive(tsOutDir);
}
else {
console.warn('Tests have failed');
console.info('Files generated by tsc can be found in: ' + tsOutDir);
}
process.exit(exitCode);
}
);
});

@ -5,20 +5,7 @@
"body-parser": "^1.2.0",
"chai": "~1.9.1",
"chai-as-promised": "^4.1.1",
"coffee-script": "^1.9.2",
"exec": "0.0.6",
"express": "^4.9.7",
"gulp": "^3.8.11",
"gulp-autoprefixer": "^2.1.0",
"gulp-filter": "^2.0.2",
"gulp-jshint": "^1.8.5",
"gulp-livingstyleguide": "0.1.5",
"gulp-replace": "^0.5.3",
"gulp-ruby-sass": "^0.7.1",
"gulp-util": "^3.0.4",
"gulp-watch": "^1.1.0",
"gulp-webpack": "^1.0.0",
"jshint-stylish": "^1.0.0",
"json2htmlcov": "~0.1.1",
"karma": "~0.12.3",
"karma-chai": "~0.1.0",
@ -70,7 +57,9 @@
},
"scripts": {
"test": "npm run karma",
"karma": "./node_modules/.bin/gulp tests:karma",
"postinstall": "./node_modules/.bin/bower install --config.interactive=false"
"karma": "./scripts/karma-runner.js",
"postinstall": "./node_modules/.bin/bower install --config.interactive=false",
"webpack": "./node_modules/.bin/webpack --colors --progress",
"webpack-watch": "npm run webpack -- --watch --cache"
}
}

@ -0,0 +1,84 @@
#!/usr/bin/env node
//-- copyright
// OpenProject is a project management system.
// Copyright (C) 2012-2015 the OpenProject Foundation (OPF)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License version 3.
//
// OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
// Copyright (C) 2006-2013 Jean-Philippe Lang
// Copyright (C) 2010-2013 the ChiliProject Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// See doc/COPYRIGHT.rdoc for more details.
//++
var path = require('path');
var tsproject = require('tsproject');
var karma = require('karma');
var fs = require('fs');
function deleteFolderRecursive(path) {
if( fs.existsSync(path) ) {
fs.readdirSync(path).forEach(function(file){
var curPath = path + "/" + file;
if(fs.lstatSync(curPath).isDirectory()) {
deleteFolderRecursive(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
}
// Clean old TS build dir
var frontend_path = path.resolve(__dirname, '..');
var tsOutDir = path.resolve(frontend_path, 'tests/unit/tests/typescript');
deleteFolderRecursive(tsOutDir);
// Compile TS
tsproject.src(path.resolve(frontend_path, 'tsconfig.test.json'), {
compilerOptions: {
outDir: tsOutDir
}
});
// Run karma
karma.server.start(
{
configFile: path.resolve(frontend_path, 'karma.conf.js'),
singleRun: true
},
function (exitCode) {
if(exitCode === 0) {
console.info('No tests have failed');
console.info('Files generated by tsc were deleted.');
deleteFolderRecursive(tsOutDir);
}
else {
console.warn('Tests have failed');
console.info('Files generated by tsc can be found in: ' + tsOutDir);
}
process.exit(exitCode);
}
);

@ -4,7 +4,9 @@
"scripts": {
"postinstall": "cd frontend && npm install",
"test": "cd frontend && npm test && cd ..",
"karma": "cd frontend && npm run karma && cd .."
"karma": "cd frontend && npm run karma && cd ..",
"webpack": "cd frontend && npm run webpack && cd ..",
"webpack-watch": "cd frontend && npm run webpack-watch"
},
"private": true
}

Loading…
Cancel
Save