├── .babelrc ├── .gitignore ├── .travis.yml ├── .wallaby-client.js ├── .wallaby-server.js ├── README.md ├── circle.yml ├── config ├── chimp.domain.options.js ├── chimp.e2e.options.js ├── karma.config.js ├── karma.options.js ├── mocha.bootstrap.js └── mocha.server.options.js ├── gulpfile.js ├── package.json ├── process-manager.js ├── scripts ├── deploy.sh ├── download-chimp-dependencies.sh ├── download-karma-dependencies.sh ├── install-meteor.sh └── start-xvfb.sh ├── src ├── .gitignore ├── .meteor │ ├── .gitignore │ ├── .id │ ├── packages │ ├── platforms │ ├── release │ └── versions ├── client │ └── index.html ├── imports │ ├── application │ │ └── services │ │ │ └── my-spec.js │ ├── domain │ │ ├── model │ │ │ └── my-spec.js │ │ └── services │ │ │ └── my-spec.js │ └── ui │ │ ├── components │ │ └── my-spec.js │ │ └── pages │ │ └── my-spec.js ├── package.json └── settings.json └── tests ├── specifications └── my.feature └── step_definitions ├── domain └── my-feature-steps.js └── end-to-end └── my-feature-steps.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react", "stage-1"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | *.log 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | 4 | env: 5 | global: 6 | - DEPLOY_SITE=qualityfaster 7 | - BROWSER=chrome 8 | - DISPLAY=:99.0 9 | 10 | language: node_js 11 | node_js: "stable" 12 | 13 | addons: 14 | apt: 15 | sources: 16 | - google-chrome 17 | packages: 18 | - google-chrome-stable 19 | firefox: "latest" 20 | 21 | cache: 22 | directories: 23 | - "node_modules" 24 | - "~/.npm" 25 | - "~/.meteor" 26 | - "src/node_modules" 27 | - "src/.meteor/local/build" 28 | - "src/.meteor/local/bundler-cache" 29 | - "src/.meteor/local/db" 30 | - "src/.meteor/local/isopacks" 31 | - "src/.meteor/local/plugin-cache" 32 | 33 | before_cache: 34 | # Remove any log files before caching 35 | - find . -name "*.log" -type f -delete 36 | 37 | before_install: 38 | # Start X Virtual Frame Buffer for headless testing with real browsers 39 | - scripts/start-xvfb.sh 40 | 41 | install: 42 | # Install & cache Meteor 43 | - scripts/install-meteor.sh 44 | 45 | # Install NPM dependencies 46 | - npm install 47 | 48 | # Download & cache Chimp's dependencies 49 | - scripts/download-chimp-dependencies.sh 50 | 51 | # Download & cache Karma's dependencies 52 | - scripts/download-karma-dependencies.sh 53 | 54 | script: 55 | - npm test 56 | 57 | # For the deployment code below to work, you need to first carry out the following steps on your local machine: 58 | # 1. Create a Meteor developer account and sign-up for Galaxy 59 | # 2a. Login with Meteor and save the session to file 60 | # METEOR_SESSION_FILE=meteor-session-file.json meteor login 61 | # 2b. Use Node.js to encode and output the file as a Base64 string 62 | # FILE_CONTENT=`cat meteor-session-file.json` node -e "console.log(new Buffer(process.env.FILE_CONTENT).toString('base64'))" 63 | # 3. Copy & paste the output in an environment variable called METEOR_SESSION_FILE_CONTENT in the project settings on TravisCI 64 | 65 | # NOTE Deployment is being handled by CircleCI. Simply uncomment these below if you prefer to use TravisCI. 66 | 67 | #deploy: 68 | # # We deploy to production any time the previous test step passed AND... 69 | # provider: script 70 | # # We use the script to deploy 71 | # script: scripts/deploy.sh 72 | # skip_cleanup: true 73 | # on: 74 | # # ...when the commit is made to this branch 75 | # branch: dev 76 | -------------------------------------------------------------------------------- /.wallaby-client.js: -------------------------------------------------------------------------------- 1 | module.exports = function (wallaby) { 2 | const wallabify = require('wallabify'); 3 | const postprocessor = wallabify({ 4 | entryPatterns: [ 5 | 'config/mocha.bootstrap.js', 6 | 'src/imports/ui/**/*spec.js' 7 | ] 8 | }); 9 | return { 10 | debug: false, 11 | testFramework: 'mocha', 12 | files: [ 13 | {pattern: 'config/mocha.bootstrap.js', load: false, instrument: false}, 14 | {pattern: 'src/imports/ui/**/*.js', load: false}, 15 | {pattern: 'src/imports/ui/**/*spec.js', ignore: true}, 16 | ], 17 | tests: [ 18 | {pattern: 'src/imports/ui/**/*spec.js', load: false}, 19 | ], 20 | compilers: { 21 | '**/*.js': wallaby.compilers.babel() 22 | }, 23 | env: { 24 | kind: 'electron' 25 | }, 26 | postprocessor: postprocessor, 27 | setup: () => { 28 | window.__moduleBundler.loadTests(); 29 | } 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /.wallaby-server.js: -------------------------------------------------------------------------------- 1 | module.exports = (wallaby) => { 2 | const path = require('path'); 3 | return { 4 | debug: false, 5 | testFramework: 'mocha', 6 | files: [ 7 | 'src/imports/**/*.js', 8 | {pattern: 'src/imports/**/*spec.js', ignore: true}, 9 | {pattern: 'src/imports/*(browser|ui)*', ignore: true}, 10 | {pattern: 'src/imports/@(browser|ui)/**/*.js', ignore: true}, 11 | ], 12 | tests: [ 13 | 'src/imports/**/*spec.js', 14 | {pattern: 'src/imports/*(browser|ui)*', ignore: true}, 15 | {pattern: 'src/imports/@(browser|ui)/**/*.js', ignore: true}, 16 | ], 17 | compilers: {'**/*.js': wallaby.compilers.babel()}, 18 | env: {type: 'node'}, 19 | workers: {initial: 1, regular: 1, recycle: true}, 20 | setup: () => { 21 | wallaby.testFramework.addFile(`${wallaby.localProjectDir}/config/mocha.bootstrap.js`); 22 | }, 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [](https://travis-ci.org/xolvio/qualityfaster) [](https://circleci.com/gh/xolvio/qualityfaster/tree/dev) 2 | 3 | Quality, Faster. 4 | ================ 5 | The companion code repository for Xolv.io's ["Quality Faster"](http://quality.xolv.io) knowledge base and guide. 6 | 7 | ## The Tech Stack 8 | The following tools and technologies are used in this repository: 9 | 10 | ## Build & Test 11 | * [Gulp.js](http://gulpjs.com/) for orchestration. 12 | * [Mocha](http://mochajs.org) to test server-side Node.js code. 13 | * [Karma](https://karma-runner.github.io/) to test client-side browser code. 14 | * [Chimp.js](http://chimpjs.com) to run acceptance and end-to-end tests. 15 | * [Wallaby.js](http://wallabyjs.com) to run in-IDE unit tests in real time. (Optional but HIGHLY recommended) 16 | 17 | ## Application 18 | * [Meteor.js](http://meteor.com) is the application framework 19 | * [React.js](https://facebook.github.io/react) for the view layer 20 | 21 | ## Installation 22 | ```bash 23 | git clone https://github.com/xolvio/quality-faster.git 24 | cd quality-faster 25 | npm install 26 | ``` 27 | 28 | ## Usage 29 | 30 | ### Development Mode 31 | When you are developing, you want the fastest possible feedback to let you know if you've broken any tests. To do that, this code repository allows you to run client, server, acceptance and end-to-end tests at hyper speeds. 32 | 33 | #### Option A: Paid (Recommended) 34 | Wallaby.js provides you with real-time feedback in your IDE. This feature is completely inline with the "Quality Faster" ethos and therefore it is highly recommended. The tool saves you a lot of time which means money, and so it pays back for itself in no time. 35 | 36 | You'll need to first install Wallaby.js for your IDE. You can find [a list of supported IDEs here](https://wallabyjs.com/docs/intro/install.html) and instructions on how to install and run the plugin. 37 | 38 | Once you've installed the plugin, you just need to create two run configurations for the client and server using the `.wallaby-client.js` and `.wallaby-server.js` files. 39 | 40 | At the time of writing this, Wallaby only supports running one mode at a time, so you'll need to switch between the server and client modes as you work on the respective files. 41 | 42 | In addition to running Wallaby.js server/client tests, you'll also need to run acceptance and end-to-end tests using Chimp's watch mode as follows: 43 | 44 | ```bash 45 | npm run watch:domain 46 | npm run watch:end-to-end 47 | ``` 48 | 49 | #### Option B: Free 50 | You also have the option of using the watch modes we have provided using Gulp and Karma. 51 | 52 | Start each commands below in a separate terminal window, and to make that sure you can see all of them with the IDE. 53 | ```bash 54 | npm run watch:client-unit 55 | npm run watch:server-unit 56 | npm run watch:domain 57 | npm run watch:end-to-end 58 | ``` 59 | 60 | You can also start all the modes in one terminal, but be warned that the terminal output can get noisy: 61 | ```bash 62 | npm run watch 63 | ``` 64 | 65 | ### Build / CI Mode 66 | Using the command below, you can run all the tests in the following sequence: client > server > e2e 67 | ```bash 68 | npm test 69 | ``` 70 | 71 | And if you want to run single test modes individually, you can do so like this: 72 | ```bash 73 | npm run test:client-unit 74 | npm run test:server-unit 75 | npm run test:domain 76 | npm run test:end-to-end 77 | ``` 78 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | node: 3 | version: 6.5.0 4 | java: 5 | # This is needed by Chimp to run Selenium so we can start Chrome and Firefox 6 | version: oraclejdk8 7 | environment: 8 | # Circle runs each command in a separate shell. This mechanism allows us to centralize variables in this file 9 | DEPLOY_SITE: qualityfaster 10 | BROWSER: chrome 11 | 12 | dependencies: 13 | cache_directories: 14 | - "node_modules" 15 | - "~/.npm" 16 | - "~/.meteor" 17 | 18 | override: 19 | # Install & cache Meteor 20 | - scripts/install-meteor.sh 21 | 22 | # Install and cache NPM dependencies 23 | - npm install 24 | 25 | # Download & cache Chimp's dependencies 26 | - scripts/download-chimp-dependencies.sh 27 | 28 | # Download & cache Karma's dependencies 29 | - scripts/download-karma-dependencies.sh 30 | 31 | test: 32 | override: 33 | # The build & test lifecycle is orchestrated by Gulp, which is wired up through npm's test script 34 | - npm test 35 | 36 | # For the deployment code below to work, you need to first carry out the following steps on your local machine: 37 | # 1. Create a Meteor developer account and sign-up for Galaxy 38 | # 2a. Login with Meteor and save the session to file 39 | # METEOR_SESSION_FILE=meteor-session-file.json meteor login 40 | # 2b. Use Node.js to encode and output the file as a Base64 string 41 | # FILE_CONTENT=`cat meteor-session-file.json` node -e "console.log(new Buffer(process.env.FILE_CONTENT).toString('base64'))" 42 | # 3. Copy & paste the output in an environment variable called METEOR_SESSION_FILE_CONTENT in the project settings on CircleCI 43 | 44 | deployment: 45 | # We deploy to production any time the previous test step passed AND... 46 | production: 47 | # ...when the commit is made to this branch 48 | branch: master 49 | commands: 50 | # We use the script to deploy 51 | - scripts/deploy.sh 52 | -------------------------------------------------------------------------------- /config/chimp.domain.options.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | path: 'tests/specifications', 3 | browser: process.env.BROWSER ? process.env.BROWSER : 'chrome', 4 | chai: true, 5 | timeout: 5000, 6 | port: 4455, 7 | domainSteps: 'tests/step_definitions/domain', 8 | fullDomain: true, 9 | domainOnly: true, 10 | watchSource: 'src/imports', 11 | // format: 'progress' 12 | }; 13 | -------------------------------------------------------------------------------- /config/chimp.e2e.options.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | path: 'tests/specifications', 3 | browser: process.env.BROWSER ? process.env.BROWSER : 'chrome', 4 | chai: true, 5 | timeout: 5000, 6 | port: 4444, 7 | e2eTags: '@e2e', 8 | e2eSteps: 'tests/step_definitions/end-to-end', 9 | ddp: 'http://localhost:3000', 10 | // format: 'progress' 11 | }; 12 | -------------------------------------------------------------------------------- /config/karma.config.js: -------------------------------------------------------------------------------- 1 | // This file is only used for caching Karma dependencies on CI servers 2 | module.exports = function (config) { 3 | config.set(require('./karma.options')) 4 | }; 5 | -------------------------------------------------------------------------------- /config/karma.options.js: -------------------------------------------------------------------------------- 1 | const DEBUG = process.env.DEBUG === 'true' || process.env.DEBUG === '1', 2 | CI = process.env.CI === 'true' || process.env.CI === '1'; 3 | 4 | module.exports = { 5 | basePath: '.', // the directory from which to resolve other paths in this config file 6 | frameworks: [ 7 | 'mocha', // We use Mocha as our test framework 8 | 'chai', // makes the assertion library present in tests without needing to require it 9 | 'browserify', // allows us to use require/import in the browser 10 | 'source-map-support' // allows us to see which source lines are cause failures when they occur 11 | ], 12 | files: [ // the order in which to load the source and test files 13 | 'src/imports/ui/**/*.js' 14 | ], 15 | exclude: [ // since karma is a front-end only testing framework, we ignore server directories 16 | 'src/**/server/**', 17 | '**/*.html', 18 | '**/*.md', 19 | 'src/node_modules/**' 20 | ], 21 | client: { 22 | useIframe: false 23 | }, 24 | preprocessors: { // uses browserify to transform files before the browser loads them 25 | 'src/**/*.js': ['browserify'], 26 | }, 27 | browserify: { 28 | debug: true, // needed for the source-map-support plugin to work 29 | transform: ['babelify'] // allows us to use ES6 30 | }, 31 | port: 9876, // tells karma the port to use for its server, which is used to manage the browsers 32 | logLevel: DEBUG ? 'DEBUG' : 'ERROR', 33 | autoWatch: !CI, 34 | 35 | singleRun: true, // tells karma to either watch the file system or run a single test run 36 | concurrency: Infinity, // The number of browsers Karma is allows to open for parallelism 37 | 38 | // When running locally we want a low-noise reporter in watch mode, but on CI we want to see the full report 39 | reporters: CI ? 'mocha' : 'dots', 40 | // the browser to run the test in. We can add many here, and on CI we are adding Firefox 41 | browsers: CI ? ['Chrome', 'Firefox'] : ['Chrome'] 42 | }; 43 | -------------------------------------------------------------------------------- /config/mocha.bootstrap.js: -------------------------------------------------------------------------------- 1 | const main = require('require-main-filename')(); 2 | 3 | const chai = require('chai'); 4 | chai.should(); 5 | global.expect = chai.expect; 6 | global.assert = chai.assert; 7 | 8 | const td = require('testdouble'); 9 | const quibble = require('quibble'); 10 | global.td = td; 11 | 12 | beforeEach(() => { 13 | td.reset(); 14 | quibble.ignoreCallsFromThisFile(main); 15 | global.Meteor = { 16 | call: function empty() {} 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /config/mocha.server.options.js: -------------------------------------------------------------------------------- 1 | const DEBUG = process.env.DEBUG === 'true' || process.env.DEBUG === '1', 2 | CI = process.env.CI === 'true' || process.env.CI === '1'; 3 | 4 | module.exports = { 5 | files: [ 6 | 'config/mocha.bootstrap.js', 7 | '!src/imports/{browser,ui,web}{,/**}', 8 | '!src/imports/**/*{browser,ui,web}*spec.js', 9 | 'src/imports/**/*spec.js' 10 | ], 11 | compilers: 'babel-core/register', 12 | reporter: CI ? 'spec' : 'dot', 13 | ui: 'bdd', 14 | watchDir: 'src/imports/**/*.js' 15 | }; 16 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'), 2 | path = require('path'), 3 | mocha = require('gulp-spawn-mocha'), 4 | karmaServer = require('karma').Server, 5 | Chimp = require('chimp'), 6 | ProcessManager = require('./process-manager'), 7 | processManager = new ProcessManager(), 8 | extend = require('util')._extend, 9 | runSequence = require('run-sequence'), 10 | karmaOptions = require('./config/karma.options'), 11 | mochaServerOptions = require('./config/mocha.server.options'), 12 | chimpDomainOptions = require('./config/chimp.domain.options'), 13 | chimpE2EOptions = require('./config/chimp.e2e.options'); 14 | 15 | // TODO remove this smelly code. The real issue is that Chimp should exit without hogging the process 16 | let finishShouldWaitForParam = false; 17 | function finish(done, exitParam) { 18 | return function (error) { 19 | if (error) { 20 | console.error(error); 21 | } 22 | if (!finishShouldWaitForParam || (finishShouldWaitForParam && exitParam)) { 23 | processManager.killAll(); 24 | process.exit(!!error) 25 | } 26 | done(error); 27 | } 28 | } 29 | 30 | gulp.task('clientUnit', function (done) { 31 | new karmaServer(karmaOptions, done).start(); 32 | }); 33 | 34 | gulp.task('watchClientUnit', function () { 35 | console.log('Karma is running in watch mode'.white); 36 | karmaOptions.singleRun = false; 37 | gulp.start('clientUnit'); 38 | }); 39 | 40 | gulp.task('serverUnit', function () { 41 | return gulp.src(mochaServerOptions.files, {read: false}) 42 | .pipe(mocha(mochaServerOptions)); 43 | }); 44 | 45 | gulp.task('watchServerUnit', function () { 46 | console.log('Mocha is running in watch mode'.white); 47 | gulp.start('serverUnit'); 48 | gulp.watch(mochaServerOptions.watchDir, function (event) { 49 | if (!event.path.match(/browser|ui|web/)) { 50 | gulp.start('serverUnit'); 51 | } 52 | }); 53 | }); 54 | 55 | gulp.task('domain', function (done) { 56 | const chimpDefaultOptions = require(path.resolve(process.cwd() + '/node_modules/chimp/dist/bin/default.js')); 57 | chimpDomainOptions._ = []; 58 | const options = Object.assign({}, chimpDefaultOptions, chimpDomainOptions); 59 | const chimp = new Chimp(options); 60 | chimp.init(finish(done)); 61 | }); 62 | 63 | gulp.task('watchDomain', function () { 64 | chimpDomainOptions.watch = true; 65 | gulp.start('domain'); 66 | }); 67 | 68 | gulp.task('endToEnd', ['startApplicationServer'], function (done) { 69 | const chimpDefaultOptions = require(path.resolve(process.cwd() + '/node_modules/chimp/dist/bin/default.js')); 70 | chimpE2EOptions._ = []; 71 | const options = Object.assign({}, chimpDefaultOptions, chimpE2EOptions); 72 | process.env.DEBUG = 'true'; 73 | const chimp = new Chimp(options); 74 | chimp.init(finish(done)); 75 | }); 76 | 77 | gulp.task('watchEndToEnd', function () { 78 | chimpE2EOptions.watch = true; 79 | gulp.start('endToEnd'); 80 | }); 81 | 82 | gulp.task('default', ['watchServerUnit', 'watchClientUnit', 'watchDomain', 'watchEndToEnd']); 83 | 84 | gulp.task('test', function (done) { 85 | finishShouldWaitForParam = true; 86 | runSequence('serverUnit', 'clientUnit', 'domain', 'endToEnd', finish(done, true)); 87 | }); 88 | 89 | gulp.task('startApplicationServer', function (done) { 90 | const srcDir = path.resolve(__dirname, 'src'); 91 | processManager.startProcess({ 92 | name: 'Meteor App', 93 | command: `meteor --settings ${srcDir}/settings.json --port 3000`, 94 | waitForMessage: 'App running at', 95 | options: { 96 | cwd: srcDir, 97 | env: extend({ 98 | ROOT_URL: 'http://localhost:3000' 99 | }, process.env) 100 | } 101 | }, done); 102 | }); 103 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qualityfaster", 3 | "author": "Sam Hatoum", 4 | "version": "1.0.0", 5 | "description": "", 6 | "repository": "https://github.com/xolvio/qualityfaster", 7 | "scripts": { 8 | "install": "meteor npm install --prefix src", 9 | "watch": "gulp -S", 10 | "watch:client-unit": "gulp -S watchClientUnit", 11 | "watch:server-unit": "gulp -S watchServerUnit", 12 | "watch:domain": "gulp -S watchDomain", 13 | "watch:endToEnd": "gulp -S watchEndToEnd", 14 | "test": "gulp -S test", 15 | "test:client-unit": "gulp -S clientUnit", 16 | "test:server-unit": "gulp -S serverUnit", 17 | "test:domain": "gulp -S domain", 18 | "test:endToEnd": "gulp -S endToEnd", 19 | "start": "gulp -S startApplicationServer" 20 | }, 21 | "license": "ISC", 22 | "devDependencies": { 23 | "babel-cli": "^6.14.0", 24 | "babel-core": "^6.14.0", 25 | "babel-loader": "^6.2.5", 26 | "babel-plugin-transform-runtime": "^6.15.0", 27 | "babel-preset-es2015": "^6.6.0", 28 | "babel-preset-react": "^6.5.0", 29 | "babel-preset-stage-1": "^6.22.0", 30 | "babel-preset-stage-2": "^6.13.0", 31 | "babelify": "^7.3.0", 32 | "browserify": "^13.1.0", 33 | "chai": "^3.5.0", 34 | "chimp": "^0.47.2", 35 | "cross-env": "^2.0.1", 36 | "electron": "^1.6.2", 37 | "enzyme": "^2.7.1", 38 | "gulp": "^3.9.1", 39 | "gulp-cli": "^1.2.2", 40 | "gulp-spawn-mocha": "^3.1.0", 41 | "gulp-util": "^3.0.7", 42 | "istanbul": "^0.4.5", 43 | "karma": "^1.2.0", 44 | "karma-babel-preprocessor": "^6.0.1", 45 | "karma-browserify": "^5.1.0", 46 | "karma-chai": "^0.1.0", 47 | "karma-chrome-launcher": "^2.0.0", 48 | "karma-firefox-launcher": "^1.0.0", 49 | "karma-mocha": "^1.1.1", 50 | "karma-mocha-reporter": "^2.1.0", 51 | "karma-quiet-reporter": "^0.1.2", 52 | "karma-source-map-support": "^1.2.0", 53 | "lodash": "^4.17.4", 54 | "mocha": "^3.2.0", 55 | "react": "^15.4.2", 56 | "react-addons-test-utils": "^15.4.2", 57 | "react-dom": "^15.4.2", 58 | "require-main-filename": "^1.0.1", 59 | "run-sequence": "^1.2.2", 60 | "shelljs": "^0.7.4", 61 | "testdouble": "2.0.1", 62 | "underscore": "^1.8.3", 63 | "wallabify": "0.0.15", 64 | "watchify": "^3.7.0", 65 | "webpack": "^2.2.1" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /process-manager.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const exec = require('child_process').exec; 3 | 4 | class ProcessManager { 5 | constructor() { 6 | this.processes = []; 7 | } 8 | startProcess(opts, callback) { 9 | const proc = exec( 10 | opts.command, 11 | opts.options 12 | ); 13 | if (opts.waitForMessage) { 14 | proc.stdout.on('data', function waitForMessage(data) { 15 | if (data.toString().match(opts.waitForMessage)) { 16 | if (callback) { 17 | callback(); 18 | } 19 | } 20 | }); 21 | } 22 | if (!opts.silent) { 23 | proc.stdout.pipe(process.stdout); 24 | proc.stderr.pipe(process.stderr); 25 | } 26 | if (opts.logFile) { 27 | const logStream = fs.createWriteStream(opts.logFile, {flags: 'a'}); 28 | proc.stdout.pipe(logStream); 29 | proc.stderr.pipe(logStream); 30 | } 31 | proc.on('close', function (code) { 32 | console.log(opts.name, 'exited with code ' + code); 33 | this.killAll(); 34 | this.process.exit(code); 35 | }); 36 | this.processes.push(proc); 37 | } 38 | killAll() { 39 | for (let i = 0; i < this.processes.length; i += 1) { 40 | this.processes[i].kill(); 41 | } 42 | } 43 | } 44 | 45 | module.exports = ProcessManager; 46 | -------------------------------------------------------------------------------- /scripts/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Go into the directory where the Meteor app resides 4 | cd src 5 | 6 | # Use Node.js to decode the Base64 environment variable called METEOR_SESSION_FILE and write it to a file called meteor-session-file.json 7 | echo Writing Meteor session file 8 | node -e "console.log(new Buffer(process.env.METEOR_SESSION_FILE_CONTENT, 'Base64').toString('utf-8'))" > meteor-session-file.json 9 | 10 | # Disable the pretty format to reduce the noise on the CI logs 11 | export METEOR_PRETTY_OUTPUT=0 12 | 13 | # Let Meteor know we are dploying to Galaxy 14 | export DEPLOY_HOSTNAME=galaxy.meteor.com 15 | 16 | # Log in to Galaxy on CI without user input 17 | export METEOR_SESSION_FILE=meteor-session-file.json 18 | 19 | echo Deploying to $DEPLOY_SITE on Galaxy 20 | #meteor deploy $DEPLOY_SITE 21 | -------------------------------------------------------------------------------- /scripts/download-chimp-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Guarantee a directory that contains no tests 4 | mkdir ./tmp 5 | 6 | echo Starting Chimp without any tests to download dependencies 7 | ./node_modules/.bin/chimp --path=./tmp 8 | 9 | # Clean up 10 | rm -rf ./tmp 11 | -------------------------------------------------------------------------------- /scripts/download-karma-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo Starting Karma without any tests to download dependencies 4 | ./node_modules/.bin/karma start ./config/karma.config.js --no-fail-on-empty-test-suite --reporters=quiet 5 | -------------------------------------------------------------------------------- /scripts/install-meteor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -f ~/.meteor/meteor ] 4 | then 5 | echo `~/.meteor/meteor --version` found, restoring symlink 6 | sudo ln -s ~/.meteor/meteor /usr/local/bin/meteor 7 | else 8 | echo Installing Meteor 9 | curl https://install.meteor.com | sh 10 | fi 11 | -------------------------------------------------------------------------------- /scripts/start-xvfb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 4 | sh -e /etc/init.d/xvfb start 5 | sleep 3 6 | fi 7 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /src/.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /src/.meteor/.id: -------------------------------------------------------------------------------- 1 | # This file contains a token that is unique to your project. 2 | # Check it into your repository along with the rest of this directory. 3 | # It can be used for purposes such as: 4 | # - ensuring you don't accidentally deploy one app on top of another 5 | # - providing package authors with aggregated statistics 6 | 7 | 15hlnmhpe7puk92spet 8 | -------------------------------------------------------------------------------- /src/.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # Check this file (and the other files in this directory) into your repository. 3 | # 4 | # 'meteor add' and 'meteor remove' will edit this file for you, 5 | # but you can also edit it by hand. 6 | 7 | meteor-base@1.0.4 # Packages every Meteor app needs to have 8 | mobile-experience@1.0.4 # Packages for a great mobile UX 9 | mongo@1.1.16 # The database Meteor supports right now 10 | blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views 11 | reactive-var@1.0.11 # Reactive variable for tracker 12 | jquery@1.11.10 # Helpful client-side library 13 | tracker@1.1.2 # Meteor's client-side reactive programming library 14 | 15 | standard-minifier-css@1.3.4 # CSS minifier run for production mode 16 | standard-minifier-js@1.2.3 # JS minifier run for production mode 17 | es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers. 18 | ecmascript@0.6.3 # Enable ECMAScript2015+ syntax in app code 19 | shell-server@0.2.3 # Server-side component of the `meteor shell` command 20 | 21 | autopublish@1.0.7 # Publish all data to the clients (for prototyping) 22 | insecure@1.0.7 # Allow all DB writes from clients (for prototyping) 23 | -------------------------------------------------------------------------------- /src/.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | 4 | -------------------------------------------------------------------------------- /src/.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.4.3.2 2 | -------------------------------------------------------------------------------- /src/.meteor/versions: -------------------------------------------------------------------------------- 1 | allow-deny@1.0.5 2 | autopublish@1.0.7 3 | autoupdate@1.3.12 4 | babel-compiler@6.14.1 5 | babel-runtime@1.0.1 6 | base64@1.0.10 7 | binary-heap@1.0.10 8 | blaze@2.3.0 9 | blaze-html-templates@1.1.0 10 | blaze-tools@1.0.10 11 | boilerplate-generator@1.0.11 12 | caching-compiler@1.1.9 13 | caching-html-compiler@1.1.0 14 | callback-hook@1.0.10 15 | check@1.2.5 16 | ddp@1.2.5 17 | ddp-client@1.3.3 18 | ddp-common@1.2.8 19 | ddp-server@1.3.13 20 | deps@1.0.12 21 | diff-sequence@1.0.7 22 | ecmascript@0.6.3 23 | ecmascript-runtime@0.3.15 24 | ejson@1.0.13 25 | es5-shim@4.6.15 26 | fastclick@1.0.13 27 | geojson-utils@1.0.10 28 | hot-code-push@1.0.4 29 | html-tools@1.0.11 30 | htmljs@1.0.11 31 | http@1.2.12 32 | id-map@1.0.9 33 | insecure@1.0.7 34 | jquery@1.11.10 35 | launch-screen@1.1.1 36 | livedata@1.0.18 37 | logging@1.1.17 38 | meteor@1.6.1 39 | meteor-base@1.0.4 40 | minifier-css@1.2.16 41 | minifier-js@1.2.18 42 | minimongo@1.0.21 43 | mobile-experience@1.0.4 44 | mobile-status-bar@1.0.14 45 | modules@0.7.9 46 | modules-runtime@0.7.9 47 | mongo@1.1.16 48 | mongo-id@1.0.6 49 | npm-mongo@2.2.24 50 | observe-sequence@1.0.16 51 | ordered-dict@1.0.9 52 | promise@0.8.8 53 | random@1.0.10 54 | reactive-var@1.0.11 55 | reload@1.1.11 56 | retry@1.0.9 57 | routepolicy@1.0.12 58 | shell-server@0.2.3 59 | spacebars@1.0.13 60 | spacebars-compiler@1.1.0 61 | standard-minifier-css@1.3.4 62 | standard-minifier-js@1.2.3 63 | templating@1.3.0 64 | templating-compiler@1.3.0 65 | templating-runtime@1.3.0 66 | templating-tools@1.1.0 67 | tracker@1.1.2 68 | ui@1.0.12 69 | underscore@1.0.10 70 | url@1.1.0 71 | webapp@1.3.14 72 | webapp-hashing@1.0.9 73 | -------------------------------------------------------------------------------- /src/client/index.html: -------------------------------------------------------------------------------- 1 |
2 |