├── .gitignore ├── .gitmodules ├── .npmignore ├── .travis.yml ├── .travis.yml.mac ├── .travis.yml.ubuntu ├── CHANGELOG.md ├── Cakefile ├── LICENSE.txt ├── README.md ├── bin ├── help.txt ├── mdeploy ├── menv.rc ├── meteor-mocha ├── meteor-tag.sh ├── mmpublish ├── mongo-connect ├── mongo-reset ├── mongo-reset.js ├── mpublish ├── mrun ├── mtp ├── npm-publish ├── npm-test.sh ├── set-meteor-env ├── sjtp ├── spacejam ├── spacejam-init-bashrc ├── spacejam-mocha ├── spacejam-test.sh ├── spacejam.coffee ├── spacejam.rc └── unset-meteor-env ├── lib ├── CLI.coffee ├── ChildProcess.coffee ├── Meteor.coffee ├── MeteorMongodb.coffee ├── PackageJSStubs.coffee ├── Phantomjs.coffee ├── Pipe.coffee ├── Spacejam.coffee ├── XunitFilePipe.coffee ├── log.coffee ├── main.coffee ├── phantomjs-test-in-console.js └── phantomjs-test-in-velocity.js ├── package.json ├── packages.json └── tests ├── apps ├── failing-app-tests │ ├── .meteor │ │ ├── .finished-upgraders │ │ ├── .gitignore │ │ ├── .id │ │ ├── packages │ │ ├── platforms │ │ ├── release │ │ └── versions │ ├── app.app-tests.js │ ├── app.tests.js │ ├── client │ │ ├── main.css │ │ ├── main.html │ │ └── main.js │ ├── package.json │ └── server │ │ └── main.js ├── leaderboard │ ├── .meteor │ │ ├── .finished-upgraders │ │ ├── .gitignore │ │ ├── .id │ │ ├── packages │ │ ├── platforms │ │ └── release │ ├── leaderboard.css │ ├── leaderboard.html │ ├── leaderboard.js │ ├── packages │ │ ├── failure │ │ │ ├── .gitignore │ │ │ ├── failure-test.coffee │ │ │ ├── failure.coffee │ │ │ ├── package.js │ │ │ └── versions.json │ │ ├── settings │ │ │ ├── .gitignore │ │ │ ├── package.js │ │ │ ├── settings-test.coffee │ │ │ ├── settings.coffee │ │ │ └── versions.json │ │ ├── success │ │ │ ├── .gitignore │ │ │ ├── package.js │ │ │ ├── success-test.coffee │ │ │ ├── success.coffee │ │ │ └── versions.json │ │ └── timeout │ │ │ ├── .gitignore │ │ │ ├── package.js │ │ │ ├── timeout-test.coffee │ │ │ ├── timeout.coffee │ │ │ └── versions.json │ └── settings.json ├── passing-app-tests │ ├── .meteor │ │ ├── .finished-upgraders │ │ ├── .gitignore │ │ ├── .id │ │ ├── packages │ │ ├── platforms │ │ ├── release │ │ └── versions │ ├── app.app-tests.js │ ├── app.tests.js │ ├── client │ │ ├── main.css │ │ ├── main.html │ │ └── main.js │ ├── package.json │ └── server │ │ └── main.js └── todos │ ├── .meteor │ ├── .finished-upgraders │ ├── .gitignore │ ├── .id │ ├── packages │ ├── platforms │ └── release │ ├── client │ ├── todos.css │ ├── todos.html │ └── todos.js │ ├── packages │ ├── appclientsideerror │ │ ├── .gitignore │ │ ├── appfails-test.js │ │ ├── appfails.js │ │ └── package.js │ └── appfails │ │ ├── .gitignore │ │ ├── appfails-test.coffee │ │ ├── appfails.coffee │ │ ├── package.js │ │ └── versions.json │ ├── public │ ├── close_16.png │ └── destroy.png │ └── server │ ├── bootstrap.js │ └── publish.js ├── bin └── meteor ├── lib ├── CLITest.coffee ├── FunctionalTests.coffee ├── MeteorTest.coffee ├── NpmExportsTest.coffee ├── ScriptsTests.coffee └── SpacejamTest.coffee └── packages ├── standalone-package-dep ├── .gitignore ├── package.js ├── success-test.coffee └── success.coffee └── standalone-package ├── .gitignore ├── package.js ├── success-test.coffee └── success.coffee /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ 3 | .meteor/local 4 | *.log 5 | *.pid 6 | versions.json 7 | .meteor/versions 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/practicalmeteor/spacejam/a3dc79b6bfce70e696f490edf626e1b24948d518/.gitmodules -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.coffee 2 | /packages 3 | /tests 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Use the new docker based infrastructure 2 | sudo: false 3 | 4 | language: node_js 5 | node_js: 6 | - 0.10.40 7 | 8 | notifications: 9 | slack: 10 | secure: Sp0XScJQvQJmAD842c3+NRfcz/kmY3t01vyqcqywGBp+AtpYrTCT8ZXWzxSsS5+0Zyxbw5qHo+cApjvaP3pWKRYYoCz8OQ41cJ5m7CauvRXhLNlGph9fzSk5f1s6Ut1efXlFRY/DQhFPuHw8OdsrahIrgoLSYoJvPU3oc2aBszo= 11 | 12 | git: 13 | submodules: false 14 | 15 | # On travis's new docker based sudoless infastructure, meteor can't be linked to /usr/local/bin, 16 | # so we have to add meteor to the PATH 17 | before_install: 18 | - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules 19 | - git submodule update --init --recursive 20 | - curl https://install.meteor.com | /bin/sh 21 | - export PATH="$HOME/.meteor:$PATH" 22 | - meteor --version 23 | - npm install -g coffee-script@1.8.0 24 | - phantomjs -v 25 | -------------------------------------------------------------------------------- /.travis.yml.mac: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | 3 | #git: 4 | # submodules: false 5 | 6 | before_install: 7 | # - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules 8 | # - git submodule update --init --recursive 9 | - curl https://raw.githubusercontent.com/creationix/nvm/v0.20.0/install.sh | bash 10 | - source $HOME/.bashrc 11 | - nvm install 0.10.36 12 | - nvm use 0.10.36 13 | - "curl https://install.meteor.com | /bin/sh" 14 | - "meteor --version" 15 | - "npm install -g coffee-script@1.8.0" 16 | 17 | install: 18 | - npm install 19 | 20 | script: 21 | - npm test 22 | -------------------------------------------------------------------------------- /.travis.yml.ubuntu: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "0.10.36" 4 | 5 | git: 6 | submodules: false 7 | 8 | before_install: 9 | - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules 10 | - git submodule update --init --recursive 11 | - "curl https://install.meteor.com | /bin/sh" 12 | - "meteor --version" 13 | - "npm install -g coffee-script@1.8.0" 14 | - "phantomjs -v" 15 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.5.2 2 | 3 | - Add meteor-mocha wrapper script to npm bin scripts 4 | 5 | ## 1.5.1 6 | 7 | - Add meteor-mocha wrapper script 8 | 9 | ## 1.5.0 10 | 11 | - Add spacejam-mocha 12 | 13 | - Document mocha support in package desc, readme and help 14 | 15 | - Let mocha report uncaught client side exceptions during tests, instead of exiting. 16 | 17 | ## 1.4.1 18 | 19 | - Add set-meteor-env and unset-meteor-env to package.json bin so other scripts can find them. 20 | 21 | ## 1.4.0 22 | 23 | - Add multi-env support to mrun and sjtp scripts using set-meteor-env and unset-meteor-env scripts 24 | 25 | - Add spacejam.rc script that adds the following aliases to the user's shell 26 | 27 | menv XXX (i.e. menv STAGE) - switches between envs 28 | 29 | msetenv - regenerates the meteor env 30 | 31 | - Add spacejam-init-bashrc script that adds to user's .bashrc the menv and msetenv aliases by sourcing spacejam.rc 32 | 33 | - Add mdeploy script to login and publish an app to meteor, with multi-env support 34 | 35 | - Add mongo-connect and mongo-reset scripts to reset an external mongodb 36 | 37 | - Add mmpublish script to publish packages with practicalmeteor:mocha tests 38 | 39 | - TODO: Documentation of all of the above in README 40 | 41 | ## 1.3.0 42 | 43 | - Exit with exit code 6 in case of an uncaught client side error before or during tests. 44 | 45 | ## 1.2.2 46 | 47 | - Add support for METEOR_APP_HOME in mrun 48 | 49 | - Always export METEOR_TEST_PACKAGES='1' in both spacejam and mtp before running meteor test-packages 50 | 51 | ## 1.2.1 52 | 53 | * Add --use-system-phantomjs flag. 54 | 55 | ## 1.2.0 56 | 57 | * Add support for saving xunit output generated by meteor's test-in-console to a file using --xunit-out 58 | 59 | ## 1.1.4 60 | 61 | * Add --phantomjs-options 62 | 63 | ## 1.1.3 64 | 65 | * Remove requirement to be in a meteor app or package folder 66 | 67 | ## 1.1.2 68 | 69 | * Mac / OS X support 70 | 71 | ## 1.1.1 72 | 73 | * Update README.md 74 | 75 | ## 1.1.0 76 | 77 | * coffee-script installation perquisite removed. 78 | * Add --dir option to specify current working directory. 79 | * Unless you explicitly specify --mongo-url, mongodb will default to internal meteor mongodb, and not MONGO_URL. 80 | * Unless you explicitly specify --root-url, ROOT_URL will default to localost:--port (default 4096), and not ROOT_URL. 81 | * Add mrun and mtp scripts 82 | * Internal: Update tests to meteor 1.0 83 | * Internal: Compile and run tests in js, not coffee. 84 | 85 | ## 1.0.0 86 | 87 | * Remove support for the --app option. spacejam needs to be run from within a meteor app or package folder. 88 | * Remove support for the --once option, since we need the meteor proxy to start and launch a mongodb, if needed. With --once, the meteor proxy will not launch a mongodb. 89 | * Remove support for the --driver-package option. It will always be test-in-console, since spacejam should only be used to test your packages from the command line or in ci environments. 90 | * Internal: Update tests to meteor 0.9.2.2 91 | 92 | ## 0.2.10 93 | 94 | * Internal: Fix npm-publish script so it stops in case of errors. 95 | 96 | ## 0.2.9 97 | 98 | * Add support for running spacejam without packages specified, so it will do the same as meteor test-packages without arguments. 99 | * Add support for running tests for standalone packages, without a meteor app. 100 | * spacejam now kills meteor's internal mongodb cleanly. See #3 101 | 102 | ## 0.2.8 103 | 104 | * Updated documentation to reflect that spacejam_ environment variables need to be lower case. 105 | 106 | ## 0.2.7 107 | 108 | * `--driver-package` option has been removed. It will always use `test-in-console`. 109 | * Updated documentation to include prerequisites (coffee-script) and quick start. 110 | 111 | ## 0.2.6 112 | 113 | * `--app` is no longer required. spacejam will use the current working directory, if no --app folder is specified. 114 | * Added spacejam ([bin/run-tests.sh](bin/run-tests.sh)) and meteor ([bin/run-app.sh](bin/run-app.sh)) wrapper scripts in order to easily specify different environments for meteor and spacejam. 115 | * Added a script ([bin/unset-meteor-env.sh](bin/unset-meteor-env.sh)) to easily unset meteor related environment variables. 116 | 117 | ## 0.2.5 118 | 119 | * Add support for the `--release` meteor flag. 120 | -------------------------------------------------------------------------------- /Cakefile: -------------------------------------------------------------------------------- 1 | ChildProcess = require './lib/ChildProcess' 2 | 3 | mochaCmdLine = "mocha --colors --compilers coffee:coffee-script/register --reporter spec tests/lib/*Test.coffee" 4 | 5 | task "compile", "Compile coffee-script library sources", -> 6 | child = new ChildProcess() 7 | child.exec "coffee -o lib -c lib" 8 | child = new ChildProcess() 9 | child.exec "coffee -o tests/lib -c tests/lib" 10 | 11 | 12 | task "test", "Run tests", -> 13 | child = new ChildProcess() 14 | child.exec mochaCmdLine 15 | 16 | 17 | task "test-wait", "Run tests and wait for file changes", -> 18 | invoke 'compile' 19 | child = new ChildProcess() 20 | child.exec mochaCmdLine + " -w" 21 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013-2014 LaVaina Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | # This project is no longer maintained 6 | 7 | Due to leaving the meteor community, this project and all of it's related projects are no longer maintained by it's owners and contributors and has been taken out of [meteor's official guide](https://guide.meteor.com/testing.html#ci). 8 | 9 | 10 | ## Overview 11 | 12 | An npm package to run your meteor package tinytests and mocha tests from the command line with phantomjs. Can be used in continuous integration environments, such as Travis CI. 13 | 14 | ## Quickstart 15 | 16 | ### Installation 17 | 18 | ``` 19 | npm install -g spacejam 20 | ``` 21 | 22 | ### Running 23 | 24 | spacejam works the same as meteor tests commands i.e.: 25 | 26 | For apps: 27 | ``` 28 | # For apps 29 | spacejam test --driver-package my:driver-package 30 | # For packages 31 | spacejam test-packages 32 | 33 | 34 | ``` 35 | 36 | ### Running package tinytests 37 | 38 | Assuming you use [tinytest](https://atmospherejs.com/meteor/tinytest) for your package tests: 39 | 40 | ``` 41 | # Inside a meteor package folder 42 | spacejam test-packages ./ 43 | # Inside a meteor app folder 44 | spacejam test-packages myaccount:mypkg1 myaccount:mypkg2 45 | ``` 46 | 47 | ### Running package mocha tests 48 | 49 | Assuming you use [practicalmeteor:mocha](https://atmospherejs.com/practicalmeteor/mocha) for your package tests: 50 | 51 | ``` 52 | # Inside a meteor package folder 53 | spacejam test-packages --driver-package=practicalmeteor:mocha-console-runner ./ 54 | # Inside a meteor app folder 55 | spacejam test-packages --driver-package=practicalmeteor:mocha-console-runner myaccount:mypkg1 myaccount:mypkg2 56 | ``` 57 | 58 | Alternatively, just use the spacejam-mocha wrapper script to avoid specifying the driver-package on the command line: 59 | 60 | ``` 61 | spacejam-mocha ./ 62 | spacejam-mocha myaccount:mypkg1 myaccount:mypkg2 63 | ``` 64 | 65 | ## Table of Contents 66 | 67 | - [Installation](#installation) 68 | - [spacejam test-packages](#spacejam-test-packages) 69 | - [Running your package tests standalone](#running-your-package-tests-standalone) 70 | - [Exit codes](#exit-codes) 71 | - [spacjam package-version](#spacjam-package-version) 72 | - [spacejam-mocha wrapper script](#spacejam-mocha-wrapper-script) 73 | - [meteor-mocha wrapper script](#meteor-mocha-wrapper-script) 74 | - [mrun (meteor run)](#mrun-meteor-run) 75 | - [METEOR_SETTINGS_PATH](#meteor_settings_path) 76 | - [mtp (meteor test-packages)](#mtp-meteor-test-packages) 77 | - [TEST_PORT](#test_port) 78 | - [TEST_ROOT_URL](#test_root_url) 79 | - [TEST_MONGO_URL](#test_mongo_url) 80 | - [TEST_METEOR_SETTINGS_PATH](#test_meteor_settings_path) 81 | - [METEOR_SETTINGS_PATH](#meteor_settings_path-1) 82 | - [Contributing](#contributing) 83 | - [Changelog](#changelog) 84 | - [License](#license) 85 | 86 | ## Installation 87 | 88 | For current user: 89 | 90 | ```bash 91 | npm install -g spacejam 92 | ``` 93 | 94 | For all users: 95 | 96 | ```bash 97 | # The -H is required 98 | sudo -H npm install -g spacejam 99 | ``` 100 | 101 | This will automatically add spacejam, mrun and mtp to your path. 102 | 103 | ## spacejam test-packages 104 | 105 | `spacejam test-packages [options] [package...]` 106 | 107 | `package...` can be a list of packages with [tinytests](https://atmospherejs.com/meteor/tinytest) or [mocha](https://atmospherejs.com/practicalmeteor/mocha) tests. 108 | 109 | If not specified, will call meteor test-packages without arguments which will result in meteor testing all of the following packages: 110 | 111 | 1. All of your app's packages, if run from within a meteor app folder. 112 | 113 | 2. All of the packages meteor will find in all the folders specified in the PACKAGE_DIRS environment variable. 114 | 115 | spacejam test-packages also sets process.env.METEOR_TEST_PACKAGES to '1', so packages can know they are running in the context of meteor test-packages. Not really a good practice, but sometimes just unavoidable. 116 | 117 | The following options are specific to spacejam: 118 | 119 | `--loglevel ` 120 | 121 | spacejam log level. One of trace|debug|info|warn|error. Defaults to info. 122 | 123 | `--root-url ` 124 | 125 | The meteor ROOT_URL. Defaults to http://localhost:--port/, and not ROOT_URL, to avoid conflicts with your meteor app ROOT_URL. 126 | 127 | `--mongo-url ` 128 | 129 | The meteor MONGO_URL. Defaults to none, and not MONGO_URL, to avoid conflicts with your meteor app MONGO_URL. 130 | 131 | `--phantomjs-options ""` 132 | 133 | The [command line options](http://phantomjs.org/api/command-line.html) to pass to phantomjs. The default is `--load-images=no --ssl-protocol=TLSv1`. 134 | 135 | `--xunit-out ` 136 | 137 | If specified, saves results as xunit output to file. 138 | 139 | `--timeout ` 140 | 141 | Total timeout for all tests. Defaults to no timeout. 142 | 143 | The following options are meteor options and are passed through to meteor (all are optional): 144 | 145 | `--driver-package=` 146 | 147 | For running your [practicalmeteor:mocha](https://atmospherejs.com/practicalmeteor/mocha) tests, use [practicalmeteor:mocha-console-runner](https://atmospherejs.com/practicalmeteor/mocha-console-runner) 148 | 149 | `--port ` 150 | 151 | The meteor port. Defaults to 4096, and not PORT, to avoid conflicts with your meteor app PORT. 152 | 153 | `--settings ` 154 | 155 | Path to a meteor settings file. 156 | 157 | `--production` 158 | 159 | Simulate meteor production mode. Minify and bundle CSS and JS files. 160 | 161 | `--release ` 162 | 163 | Specify the release of Meteor to use. 164 | 165 | `--use-system-phantomjs` 166 | 167 | Use the installed version of PhantomJS instead of the one from the 168 | [PhantomJS NPM package](https://www.npmjs.com/package/phantomjs) 169 | 170 | To get help, just: 171 | 172 | ``` 173 | spacejam help 174 | ``` 175 | 176 | ### Running your package tests standalone 177 | 178 | to run your package tests without a meteor app, from within your package folder, run: 179 | 180 | ```` 181 | spacejam test-packages ./ 182 | OR 183 | spacejam-mocha test-packages ./ 184 | ``` 185 | 186 | ### Exit codes 187 | 188 | ```spacejam``` will return the following exit codes: 189 | 190 | * ```0``` All the tests have passed in all packages. 191 | * ```1``` ```spacejam``` usage or internal error. 192 | * ```2``` At least one test has failed. 193 | * ```3``` The meteor app has errors. 194 | * ```4``` The tests have timed out. 195 | * ```6``` An uncaught error happened client side before or during tests. 196 | 197 | ## spacejam package-version 198 | 199 | Prints the package version in the current working directory's package.js 200 | 201 | ## spacejam-mocha wrapper script 202 | 203 | A wrapper script so you don't have to specify --driver-package=practicalmeteor:mocha-console-runner on the command line every time, i.e.: 204 | 205 | ``` 206 | spacejam-mocha --production ./ 207 | ``` 208 | 209 | ## meteor-mocha wrapper script 210 | 211 | A wrapper script so you don't have to specify --driver-package=practicalmeteor:mocha on the command line every time, i.e.: 212 | 213 | ``` 214 | meteor-mocha --port 4000 pkg1 pkg2 215 | ``` 216 | 217 | ## mrun (meteor run) 218 | 219 | Runs `meteor run` with the provided options. Supports the following additional environment variables: 220 | 221 | ### METEOR_APP_HOME 222 | 223 | If set, will cd $METEOR_APP_HOME && meteor run, so you can run your app from any folder, without leaving that folder. 224 | 225 | ### METEOR_SETTINGS_PATH 226 | 227 | If set, runs meteor with --settings $METEOR_SETTINGS_PATH 228 | 229 | ## mtp (meteor test-packages) 230 | 231 | Runs `meteor test-packages` with the provided options on port 3100 and with MONGO_URL unset so you can run your app and your package tests in parallel, without port or mongodb conflicts, if you use an external mongodb for your app. 232 | 233 | It also always sets METEOR_TEST_PACKAGES to '1', so packages can know they run in the context of meteor test-packages. Not really a good practice, but sometimes just unavoidable. 234 | 235 | Supports the following additional environment variables: 236 | 237 | ### TEST_PORT 238 | 239 | Runs meteor with --port $TEST_PORT and sets PORT to TEST_PORT. Defaults to 3100. 240 | 241 | ### TEST_ROOT_URL 242 | 243 | If set, sets ROOT_URL to TEST_ROOT_URL. If not set, sets ROOT_URL to http://localhost:$TEST_PORT/ 244 | 245 | ### TEST_MONGO_URL 246 | 247 | If set, sets MONGO_URL to TEST_MONGO_URL. If not set, unsets MONGO_URL. 248 | 249 | ### TEST_METEOR_SETTINGS_PATH 250 | 251 | If set, runs meteor with --settings $TEST_METEOR_SETTINGS_PATH. Useful if you use different settings for your app and your package tests. 252 | 253 | ### METEOR_SETTINGS_PATH 254 | 255 | If set, runs meteor with --settings $METEOR_SETTINGS_PATH. Useful if you use the same settings for your app and your package tests. 256 | 257 | ## Changelog 258 | 259 | See [CHANGELOG.md](CHANGELOG.md) 260 | 261 | ## Contributing 262 | 263 | Contributions are more than welcome. Just create pull requests and make sure to include proper test coverage. We use mocha.js for tests and run our tests using CoffeScript's cake, so `npm test` will run `cake test`. 264 | 265 | Note that we plan to include support for running tests in any browser and in sauce from the command line so if you plan to add this, check with us if we already started working on it. 266 | 267 | ## License 268 | 269 | [MIT](LICENSE.txt) 270 | -------------------------------------------------------------------------------- /bin/help.txt: -------------------------------------------------------------------------------- 1 | 2 | Usage 3 | ----- 4 | 5 | spacejam test [options] 6 | spacejam test-packages [options] [package...] 7 | spacejam package-version 8 | spacejam help 9 | 10 | spacejam test-packages [options] [package...] 11 | --------------------------------------------- 12 | 13 | [package...] can be a list of packages with tinytests or munit tests. 14 | 15 | 16 | If not specified, acts the same as meteor test-packages without arguments. 17 | 18 | The following options are specific to spacejam: 19 | 20 | --loglevel 21 | 22 | spacejam log level. One of trace|debug|info|warn|error. Defaults to info. 23 | 24 | --root-url 25 | 26 | The meteor ROOT_URL. Defaults to http://localhost:--port/, and not ROOT_URL, 27 | to avoid conflicts with your app's ROOT_URL. 28 | 29 | --mongo-url 30 | 31 | The meteor MONGO_URL. Defaults to none, and not MONGO_URL, 32 | to avoid conflicts with your app's MONGO_URL. 33 | 34 | --phantomjs-options "" 35 | 36 | The command line options to pass to phantomjs. 37 | The default is: "--load-images=no --ssl-protocol=TLSv1". 38 | 39 | --xunit-out 40 | 41 | If specified, saves results as xunit output to file. 42 | 43 | --timeout 44 | 45 | Total timeout for all tests. Defaults to no timeout. 46 | 47 | The following options are meteor options and are passed through to meteor (all are optional): 48 | 49 | `--driver-package=` 50 | 51 | For running your practicalmeteor:mocha tests, use practicalmeteor:mocha-console-runner 52 | 53 | --port 54 | 55 | The meteor port. Defaults to 4096, and not PORT, to avoid conflicts with your meteor app PORT. 56 | 57 | --release 58 | 59 | The release of Meteor to use. 60 | 61 | --settings 62 | 63 | Path to a meteor settings file. 64 | 65 | --production 66 | 67 | Simulate meteor production mode. Minify and bundle CSS and JS files. 68 | 69 | --use-system-phantomjs 70 | 71 | Use the installed version of PhantomJS instead of the one from the PhantomJS NPM package. 72 | 73 | Running your package tests without a meteor app 74 | ----------------------------------------------- 75 | 76 | From within your package folder, run: 77 | 78 | spacejam test-packages ./ 79 | 80 | Exit codes 81 | ---------- 82 | 83 | 0 - All the tests have passed in all packages. 84 | 1 - spacejam usage or internal error. 85 | 2 - At least one test has failed. 86 | 3 - The meteor app exited with an error or is crashing. 87 | 4 - The tests have timed out. 88 | 6 - An uncaught error happened client side before or during tests. 89 | 90 | spacejam package-version 91 | ------------------------ 92 | 93 | Prints the package version in the current working directory's package.js 94 | 95 | For additional usage info, please visit https://github.com/spacejamio/spacejam 96 | -------------------------------------------------------------------------------- /bin/mdeploy: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | export SPACEJAM_BIN="$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)" 4 | source $SPACEJAM_BIN/set-meteor-env 5 | 6 | if [ -z "$METEOR_USERNAME" ]; then 7 | echo "ERROR: METEOR_USERNAME is not defined. Exiting." 8 | exit 1 9 | fi 10 | 11 | if [ -z "$METEOR_PASSWORD" ]; then 12 | echo "ERROR: METEOR_PASSWORD is not defined. Exiting." 13 | exit 1 14 | fi 15 | 16 | if [ -z "$METEOR_SITE" ]; then 17 | if [ -z "$METEOR_ENV" ]; then 18 | echo "ERROR: METEOR_SITE is not defined and METEOR_ENV is not set. Exiting." 19 | exit 1 20 | fi 21 | if [ -z "$METEOR_APP_NAME" ]; then 22 | echo "ERROR: METEOR_SITE is not defined and METEOR_APP_NAME is not set. Exiting." 23 | exit 1 24 | fi 25 | export METEOR_SITE="$METEOR_ENV-$METEOR_APP_NAME" 26 | fi 27 | 28 | meteor login <&2 echo "ERROR: A new METEOR_ENV has not been specified. Exiting." 7 | return 8 | else 9 | export METEOR_ENV="$1" 10 | source $SPACEJAM_BIN/set-meteor-env 11 | fi 12 | -------------------------------------------------------------------------------- /bin/meteor-mocha: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # A wrapper script to avoid specifying the lengthy --driver-package=... on the command line. 4 | meteor test-packages --driver-package=practicalmeteor:mocha "$@" 5 | -------------------------------------------------------------------------------- /bin/meteor-tag.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | usage="Usage: mtag package-build" 4 | 5 | if [ -z "$1" ]; then 6 | >&2 echo "Error: Missing argument." 7 | >&2 echo $usage 8 | exit 1 9 | fi 10 | 11 | if [ "$1" != "package-build" ]; then 12 | >&2 echo "Error: Invalid argument." 13 | >&2 echo $usage 14 | exit 1 15 | fi 16 | 17 | if [ -z "$TRAVIS_BUILD_NUMBER" ] 18 | then 19 | >&2 echo "Error: TRAVIS_BUILD_NUMBER is not set." 20 | exit 1 21 | fi 22 | 23 | package_version=$(spacejam package-version) 24 | 25 | # Need to enclose $package_version in quotes, otherwise semver will exit with 0, since it found at least one valid version. 26 | semver "$package_version" 27 | 28 | tag_name="build/v$package_version+$TRAVIS_BUILD_NUMBER" 29 | 30 | git tag $tag_name 31 | git push origin $tag_name 32 | -------------------------------------------------------------------------------- /bin/mmpublish: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | # mmpublish - meteor mocha publish, i.e. 4 | # Same script as mpublish, but for packages that use our practicalmeteor:mocha package for testing. 5 | 6 | if [ -n "$(git status --porcelain)" ]; then 7 | echo "The git working directory is not clean. Exiting." 8 | exit 1 9 | fi 10 | 11 | spacejam test-packages --driver-package=practicalmeteor:mocha-console-runner ./ 12 | version=$(spacejam package-version) 13 | tag_name="v${version}" 14 | meteor publish $@ 15 | git tag $tag_name 16 | git push origin $tag_name 17 | -------------------------------------------------------------------------------- /bin/mongo-connect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mongo -u $MONGO_USERNAME -p $MONGO_PASSWORD $MONGO_HOST:$MONGO_PORT/$MONGO_DB "$@" 4 | -------------------------------------------------------------------------------- /bin/mongo-reset: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | SCRIPT_DIR="$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)" 4 | 5 | mongo-connect $SCRIPT_DIR/mongo-reset.js 6 | -------------------------------------------------------------------------------- /bin/mongo-reset.js: -------------------------------------------------------------------------------- 1 | var collectionNames = db.getCollectionNames(); 2 | for(var i = 0, len = collectionNames.length; i < len ; i++){ 3 | var collectionName = collectionNames[i]; 4 | if(collectionName != "system.users" && collectionName != "system.indexes" && db[collectionName]){ 5 | db[collectionName].drop(); 6 | } 7 | } -------------------------------------------------------------------------------- /bin/mpublish: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | if [ -n "$(git status --porcelain)" ]; then 4 | echo "The git working directory is not clean. Exiting." 5 | exit 1 6 | fi 7 | 8 | spacejam test-packages ./ 9 | version=$(spacejam package-version) 10 | tag_name="v${version}" 11 | meteor publish $@ 12 | git tag $tag_name 13 | git push origin $tag_name 14 | -------------------------------------------------------------------------------- /bin/mrun: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export SPACEJAM_BIN="$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)" 4 | source $SPACEJAM_BIN/set-meteor-env 5 | 6 | unset METEOR_TEST_PACKAGES 7 | 8 | # For sure can do a better DRY job here, but no time right now 9 | if [ -n "$METEOR_APP_HOME" ]; then 10 | if [ -n "$METEOR_SETTINGS_PATH" ]; then 11 | cd $METEOR_APP_HOME && meteor --settings $METEOR_SETTINGS_PATH $@ 12 | else 13 | cd $METEOR_APP_HOME && meteor $@ 14 | fi 15 | else 16 | if [ -n "$METEOR_SETTINGS_PATH" ]; then 17 | meteor --settings $METEOR_SETTINGS_PATH $@ 18 | else 19 | meteor $@ 20 | fi 21 | fi 22 | -------------------------------------------------------------------------------- /bin/mtp: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -n "$TEST_PORT" ]; then 4 | export PORT="$TEST_PORT" 5 | else 6 | export PORT="3100" 7 | fi 8 | 9 | if [ -n "$TEST_ROOT_URL" ]; then 10 | export ROOT_URL="$TEST_ROOT_URL" 11 | else 12 | export ROOT_URL="http://localhost:$PORT/" 13 | fi 14 | 15 | if [ -n "$TEST_MONGO_URL" ]; then 16 | export MONGO_URL="$TEST_MONGO_URL" 17 | else 18 | unset MONGO_URL 19 | fi 20 | 21 | if [ -n "$TEST_METEOR_SETTINGS_PATH" ]; then 22 | METEOR_SETTINGS_PATH="$TEST_METEOR_SETTINGS_PATH" 23 | fi 24 | 25 | if [ -n "$METEOR_SETTINGS_PATH" ]; then 26 | # The space at the end is to put a space before --port 27 | METEOR_SETTINGS_ARGS="--settings $METEOR_SETTINGS_PATH" 28 | fi 29 | 30 | export METEOR_TEST_PACKAGES=1 31 | 32 | if [ -n "$METEOR_APP_HOME" ]; then 33 | set -e 34 | cd $METEOR_APP_HOME && meteor test-packages --port $PORT ${METEOR_SETTINGS_ARGS} $@ 35 | else 36 | set -e 37 | meteor test-packages --port $PORT ${METEOR_SETTINGS_ARGS} $@ 38 | fi 39 | -------------------------------------------------------------------------------- /bin/npm-publish: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | if [ -n "$(git status --porcelain)" ]; then 4 | echo "The git working directory is not clean. Exiting." 5 | exit 1 6 | fi 7 | 8 | unset METEOR_ENV 9 | npm test 10 | version=$(jq -r .version < package.json) 11 | tag_name="v${version}" 12 | echo "Publishing $tag_name" 13 | npm publish "$@" 14 | git tag $tag_name 15 | git push origin $tag_name 16 | -------------------------------------------------------------------------------- /bin/npm-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | mocha --colors --compilers coffee:coffee-script/register --reporter spec tests/lib/*Test*.coffee 4 | -------------------------------------------------------------------------------- /bin/set-meteor-env: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | 3 | if [ -z "$METEOR_ENV" ]; then 4 | return 5 | fi 6 | 7 | export SPACEJAM_BIN="$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)" 8 | source $SPACEJAM_BIN/unset-meteor-env 9 | 10 | export REPO_HOME=$(git rev-parse --show-toplevel) 11 | 12 | if [ -e "$PWD/$METEOR_ENV.meteor.env" ]; then 13 | export METEOR_ENV_FILE="$PWD/$METEOR_ENV.meteor.env" 14 | elif [ -e "$PWD/app/$METEOR_ENV.meteor.env" ]; then 15 | export METEOR_ENV_FILE="$PWD/app/$METEOR_ENV.meteor.env" 16 | elif [ -e "$PWD/bin/$METEOR_ENV.meteor.env" ]; then 17 | export METEOR_ENV_FILE="$PWD/bin/$METEOR_ENV.meteor.env" 18 | else 19 | parent_dir=$(dirname $PWD) 20 | # In case we're in the cli folder of a standard repo structure 21 | if [ -e "$parent_dir/app/$METEOR_ENV.meteor.env" ]; then 22 | export METEOR_ENV_FILE="$parent_dir/app/$METEOR_ENV.meteor.env" 23 | elif [ -e "$parent_dir/bin/$METEOR_ENV.meteor.env" ]; then 24 | export METEOR_ENV_FILE="$parent_dir/bin/$METEOR_ENV.meteor.env" 25 | fi 26 | fi 27 | 28 | if [ -z "$METEOR_ENV_FILE" ]; then 29 | >&2 echo "ERROR: METEOR_ENV=$METEOR_ENV, but $METEOR_ENV.meteor.env not found. Exiting." 30 | return 1 31 | fi 32 | 33 | if [ -e "$HOME/.meteor.env" ]; then 34 | source $HOME/.meteor.env 35 | fi 36 | 37 | meteor_env_file_dir=$(dirname $METEOR_ENV_FILE) 38 | if [ -e "$meteor_env_file_dir/default.meteor.env" ]; then 39 | source $meteor_env_file_dir/default.meteor.env 40 | fi 41 | source $METEOR_ENV_FILE 42 | 43 | if [ -z "$METEOR_APP_HOME" ]; then 44 | if [ -e "$REPO_HOME/.meteor" ]; then 45 | export METEOR_APP_HOME="$REPO_HOME" 46 | elif [ -e "$REPO_HOME/app/.meteor" ]; then 47 | export METEOR_APP_HOME="$REPO_HOME/app" 48 | else 49 | >&2 echo "ERROR: METEOR_APP_HOME is not set and cannot find a meteor app in $REPO_HOME or $REPO_HOME/app. Exiting." 50 | return 1 51 | fi 52 | fi 53 | 54 | if [ -z "$METEOR_CLI_HOME" ]; then 55 | if [ -e "$REPO_HOME/cli" ]; then 56 | export METEOR_CLI_HOME="$REPO_HOME/cli" 57 | fi 58 | fi 59 | 60 | if [ -z "$METEOR_APP_NAME" ]; then 61 | export METEOR_APP_NAME=$(basename $REPO_HOME) 62 | fi 63 | 64 | #if [ -z "$PACKAGE_DIRS" ]; then 65 | # #TODO Add app/packages to PACKAGE_DIRS so cli app can find those packages 66 | #fi 67 | 68 | if [ -z "$MONGO_URL" ] && [ -n "$MONGO_DB" ]; then 69 | if [ -z "$MONGO_USERNAME" ]; then 70 | >&2 echo "ERROR: MONGO_DB is set but MONGO_USERNAME isn't. Exiting." 71 | return 1 72 | fi 73 | if [ -z "$MONGO_PASSWORD" ]; then 74 | >&2 echo "ERROR: MONGO_DB is set but MONGO_PASSWORD isn't. Exiting." 75 | return 1 76 | fi 77 | if [ -z "$MONGO_HOST" ]; then 78 | >&2 echo "ERROR: MONGO_DB is set but MONGO_HOST isn't. Exiting." 79 | return 1 80 | fi 81 | export MONGO_URL="mongodb://$MONGO_USERNAME:$MONGO_PASSWORD@$MONGO_HOST:$MONGO_PORT/$MONGO_DB" 82 | if [ "$MONGO_SSL" == "true" ]; then 83 | export MONGO_URL="${MONGO_URL}?ssl=true" 84 | fi 85 | fi 86 | 87 | export METEOR_SETTINGS_PATH=$METEOR_APP_HOME/settings.json 88 | 89 | if [ -z "$DOCKER_HTTP_PORT" ]; then 90 | DOCKER_HTTP_PORT="80" 91 | fi 92 | 93 | if [ -z "$DOCKER_HTTPS_PORT" ]; then 94 | DOCKER_HTTPS_PORT="443" 95 | fi 96 | 97 | set -e 98 | # Let's create a meteor meteor settings file that merges the default settings and env specific settings 99 | deep-extend $HOME/.meteor.settings.json $METEOR_APP_HOME/default.settings.json $METEOR_APP_HOME/$METEOR_ENV.settings.json > $METEOR_SETTINGS_PATH 100 | set +e 101 | 102 | #if [ -z "$USE_METEOR_SUBMODULE" ]; then 103 | # meteor_path=$HOME/.meteor 104 | #else 105 | # meteor_path=$SHOPIFY_LAVAINA_HOME/submodules/meteor 106 | #fi 107 | -------------------------------------------------------------------------------- /bin/sjtp: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | 3 | export SPACEJAM_BIN="$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)" 4 | source $SPACEJAM_BIN/set-meteor-env 5 | 6 | export METEOR_TEST_PACKAGES=1 7 | 8 | # For sure can do a better DRY job here, but no time right now 9 | if [ -n "$METEOR_APP_HOME" ]; then 10 | if [ -n "$METEOR_SETTINGS_PATH" ]; then 11 | cd $METEOR_APP_HOME && spacejam test-packages --settings $METEOR_SETTINGS_PATH $@ 12 | else 13 | cd $METEOR_APP_HOME && spacejam test-packages $@ 14 | fi 15 | else 16 | if [ -n "$METEOR_SETTINGS_PATH" ]; then 17 | spacejam test-packages --settings $METEOR_SETTINGS_PATH $@ 18 | else 19 | spacejam test-packages $@ 20 | fi 21 | fi 22 | -------------------------------------------------------------------------------- /bin/spacejam: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../lib/log'); 4 | 5 | require('../lib/CLI').get().exec(); 6 | -------------------------------------------------------------------------------- /bin/spacejam-init-bashrc: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | SPACEJAM_BIN="$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)" 4 | 5 | echo "" >> $HOME/.bashrc 6 | echo "# Added by spacejam npm package" >> $HOME/.bashrc 7 | echo "[ -f $SPACEJAM_BIN/spacejam.rc ] && source $SPACEJAM_BIN/spacejam.rc" >> $HOME/.bashrc 8 | -------------------------------------------------------------------------------- /bin/spacejam-mocha: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # A wrapper script to avoid specifying the lengthy --driver-package=... on the command line. 4 | spacejam test-packages --driver-package=practicalmeteor:mocha-console-runner "$@" 5 | -------------------------------------------------------------------------------- /bin/spacejam-test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | coffee -o lib -c src 4 | coffee -o tests/lib -c tests/src 5 | mocha --colors --compilers coffee:coffee-script/register --reporter spec tests/src/*Test*.coffee 6 | -------------------------------------------------------------------------------- /bin/spacejam.coffee: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env coffee 2 | 3 | require('../lib/log') 4 | 5 | require('../lib/CLI').get().exec() 6 | -------------------------------------------------------------------------------- /bin/spacejam.rc: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | export SPACEJAM_BIN="$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)" 4 | alias menv="source $SPACEJAM_BIN/menv.rc" 5 | alias msetenv="source $SPACEJAM_BIN/set-meteor-env" 6 | -------------------------------------------------------------------------------- /bin/unset-meteor-env: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Unset all meteor related environment variables. Run: 4 | # source unset-meteor-env 5 | # This will unset the variables below in your current shell. 6 | unset PORT 7 | unset ROOT_URL 8 | unset MONGO_URL 9 | unset MONGO_OPLOG_URL 10 | 11 | # mongodb related extras 12 | unset MONGO_USERNAME 13 | unset MONGO_PASSWORD 14 | unset MONGO_HOST 15 | unset MONGO_PORT 16 | unset MONGO_DB 17 | 18 | # meteor development related extras 19 | unset REPO_HOME 20 | unset METEOR_APP_HOME 21 | unset METEOR_APP_NAME 22 | unset METEOR_CLI_HOME 23 | unset ROOT_HOST 24 | unset METEOR_PATH # In case you use a meteor checkout 25 | unset METEOR_SETTINGS_PATH 26 | 27 | # meteor testing related extras 28 | unset METEOR_TEST_PACKAGES 29 | unset TEST_PORT 30 | unset TEST_ROOT_URL 31 | unset TEST_MONGO_URL 32 | unset TEST_METEOR_SETTINGS_PATH 33 | 34 | # meteor deployment related extras 35 | unset METEOR_HOSTNAME 36 | unset NGINX_PROTOCOL 37 | 38 | # docker related config 39 | unset DOCKER_HTTP_PORT 40 | unset DOCKER_HTTPS_PORT 41 | unset DOCKER_CONTAINER_NAME 42 | unset DOCKER_HOSTNAME 43 | unset DOCKER_USE_RANDOM_PORT 44 | -------------------------------------------------------------------------------- /lib/CLI.coffee: -------------------------------------------------------------------------------- 1 | require './log' 2 | fs = require("fs") 3 | path = require("path") 4 | _ = require("underscore") 5 | expect = require("chai").expect 6 | Spacejam = require './Spacejam' 7 | Meteor = require './Meteor' 8 | 9 | require.extensions['.txt'] = (module, filename)-> 10 | module.exports = fs.readFileSync(filename, 'utf8') 11 | 12 | 13 | class CLI 14 | 15 | instance = null 16 | 17 | @get: -> 18 | instance ?= new CLI() 19 | 20 | commands: { 21 | "test" : "testApp" 22 | "test-packages" : "testPackages" 23 | } 24 | 25 | options: null 26 | 27 | spacejam: null 28 | 29 | pidPath: null 30 | 31 | constructor: -> 32 | @spacejam = new Spacejam() 33 | log.debug "CLI.constructor()" 34 | process.on 'SIGPIPE', (code)=> 35 | log.info "spacejam: Received a SIGPIPE signal. Killing all child processes..." 36 | @spacejam?.killChildren() 37 | # 38 | # process.on 'SIGINT', (code)=> 39 | # log.info "spacejam: exiting with code #{code}" 40 | # @spacejam?.killChildren() 41 | 42 | 43 | onProcessExit: (code)=> 44 | log.info "spacejam: spacejam is exiting with code #{code}, deleting pid file." 45 | try 46 | fs.unlinkSync(@pidPath) 47 | catch err 48 | log.trace err 49 | log.error("spacejam: Error deleting pid file #{@pidPath}", err) 50 | 51 | 52 | exec: -> 53 | log.debug "CLI.exec()" 54 | expect(@options, "You can only call CLI.exec() once").to.be.null 55 | 56 | @options = require("rc")("spacejam", {}) 57 | 58 | command = @options._[0] 59 | log.debug "command: #{command}" 60 | if command is 'help' 61 | @printHelp() 62 | process.exit(0) 63 | else if command is 'package-version' 64 | version = Meteor.getPackageVersion() 65 | console.log(version) 66 | process.exit(0) 67 | 68 | if not _.has(@commands, command) 69 | log.error "spacejam: Error: \n'#{command}' is not a recognized command\n" if command 70 | return @printHelp() 71 | 72 | @options.packages = @options._.slice(1) 73 | @options.command = command 74 | delete @options._ 75 | 76 | log.debug "CLI.exec() options:", @options 77 | 78 | @spacejam.on 'done', (code)=> 79 | if Spacejam.DONE_MESSAGE[code]? 80 | exitMsg = "spacejam: #{Spacejam.DONE_MESSAGE[code]}. Exiting." 81 | else 82 | exitMsg = "spacejam: Unknown error with exit code '#{code}'. Exiting." 83 | log.error exitMsg 84 | process.exit code 85 | 86 | try 87 | @spacejam.runTests(command, @options) 88 | catch err 89 | console.trace err 90 | log.error "spacejam: Usage or initialization error. Exiting." 91 | process.exit 1 92 | 93 | 94 | 95 | printHelp: -> 96 | log.debug "CLI.printHelp()" 97 | process.stdout.write require('../bin/help.txt') 98 | 99 | 100 | module.exports = CLI 101 | -------------------------------------------------------------------------------- /lib/ChildProcess.coffee: -------------------------------------------------------------------------------- 1 | require('./log') 2 | expect = require("chai").expect 3 | Pipe = require("./Pipe") 4 | path = require 'path' 5 | 6 | class ChildProcess 7 | 8 | # Design for testability - so we can spy on them / stub them in tests 9 | @_spawn: require("child_process").spawn 10 | @_exec: require("child_process").exec 11 | 12 | child: null 13 | 14 | descendants: [] 15 | 16 | pipe : null 17 | 18 | command: null 19 | 20 | killed: false 21 | 22 | constructor:-> 23 | log.debug "ChildProcess.constructor()" 24 | 25 | exec: (command, options, cb)-> 26 | log.debug "ChildProcess.exec()", arguments 27 | expect(@child).to.be.null 28 | expect(command).to.be.a('string').that.is.ok 29 | expect(options).to.be.an('object') if options? 30 | 31 | @command = command.split(' ', 1)[0] 32 | expect(@command).to.be.a('string').that.is.ok 33 | 34 | innerCB = (err, stdout, stderr) => 35 | @killed = true 36 | if err?.code? 37 | log.error "child_process.exec: Error: #{@command} exit code: #{err.code}" 38 | if err?.signal? 39 | log.error "child_process.exec: Error: #{@command} termination signal: #{err.signal}" 40 | cb(err, stdout, stderr) if cb? 41 | 42 | if options? 43 | @child = ChildProcess._exec command, options, innerCB 44 | else 45 | @child = ChildProcess._exec command, innerCB 46 | 47 | @child.stdout.pipe(process.stdout) 48 | @child.stderr.pipe(process.stderr) 49 | 50 | 51 | spawn: (command, args=[], options={}, pipeClass = undefined, pipeClassOptions = undefined)-> 52 | log.debug "ChildProcess.spawn()", command, args 53 | 54 | expect(@child,"ChildProcess is already running").to.be.null 55 | expect(command,"Invalid @command argument").to.be.a "string" 56 | expect(args,"Invalid @args argument").to.be.an "array" 57 | expect(options,"Invalid @options").to.be.an "object" 58 | expect(pipeClass, "Invalid pipeClass").to.be.a 'function' if pipeClass? 59 | expect(pipeClassOptions, "Invalid pipeClassOptions").to.be.an 'object' if pipeClassOptions? 60 | 61 | @command = path.basename command 62 | 63 | log.info("spacejam: spawning #{@command}") 64 | 65 | process.on 'exit', (code)=> 66 | log.debug "ChildProcess.process.on 'exit': @command=#{@command} @killed=#{@killed} code=#{code}" 67 | @kill() 68 | 69 | @child = ChildProcess._spawn(command, args, options) 70 | 71 | if pipeClass 72 | @pipe = new pipeClass(@child.stdout, @child.stderr, pipeClassOptions) 73 | else 74 | @pipe = new Pipe(@child.stdout, @child.stderr) 75 | 76 | @child.on "exit", (code, signal)=> 77 | log.debug "ChildProcess.process.on 'exit': @command=#{@command} @killed=#{@killed} code=#{code} signal=#{signal}" 78 | @killed = true 79 | if code? 80 | log.info "spacejam: #{command} exited with code: #{code}" 81 | else if signal? 82 | log.info "spacejam: #{command} killed with signal: #{signal}" 83 | else 84 | log.error "spacejam: #{command} exited with arguments: #{arguments}" 85 | 86 | 87 | kill: (signal = "SIGTERM")-> 88 | log.debug "ChildProcess.kill() signal=#{signal} @command=#{@command} @killed=#{@killed}" 89 | return if @killed 90 | log.info "spacejam: killing", @command 91 | @killed = true 92 | try 93 | # Providing a negative pid will kill the entire process group, 94 | # i.e. the process and all it's children 95 | # See man kill for more info 96 | #process.kill(-@child.pid, signal) 97 | @child?.kill(signal) 98 | 99 | catch err 100 | log.warn "spacejam: Error: While killing #{@command} with pid #{@child.pid}:\n", err 101 | 102 | 103 | module.exports = ChildProcess 104 | -------------------------------------------------------------------------------- /lib/Meteor.coffee: -------------------------------------------------------------------------------- 1 | require('./log') 2 | expect = require('chai').expect 3 | _ = require("underscore") 4 | ChildProcess = require './ChildProcess' 5 | EventEmitter = require('events').EventEmitter 6 | MeteorMongodb = require("./MeteorMongodb") 7 | glob = require("glob") 8 | fs = require("fs") 9 | path = require "path" 10 | 11 | class Meteor extends EventEmitter 12 | 13 | childProcess: null 14 | 15 | buffer:{ 16 | stdout:"" 17 | stderr:"" 18 | } 19 | 20 | options: null 21 | 22 | mongodb: null 23 | 24 | defaultOptions: -> 25 | { 26 | "dir": "." 27 | "port": 4096 28 | "packages": [] 29 | "driver-package": "test-in-console" 30 | "meteor-ready-text": "=> App running at:" 31 | "meteor-error-text": "Waiting for file change." 32 | } 33 | 34 | 35 | @getPackageVersion: -> 36 | log.debug "Meteor.getPackageVersion()" 37 | if not fs.existsSync('package.js') 38 | throw new Error("Missing package.js in current working directory.") 39 | require './PackageJSStubs' 40 | require "#{process.cwd()}/package.js" 41 | expect(Package.description?.version).to.be.a('string').that.is.ok 42 | return Package.description.version 43 | 44 | 45 | getTestArgs:(command, options)-> 46 | log.debug("Meteor.getTestArgs()", options) 47 | expect(+options.port, "options.port is not a number.").to.be.ok 48 | expect(options.packages, "options.packages is not an array of package names").to.be.an 'array' 49 | 50 | args = [ 51 | command 52 | '--driver-package' 53 | options['driver-package'] 54 | ] 55 | args.push(["--release", options.release]) if options.release 56 | args.push(["--port", options.port]) 57 | args.push(["--settings", options.settings]) if options.settings 58 | args.push("--production") if options.production 59 | 60 | if options.mocha? 61 | options["driver-package"] = "practicalmeteor:mocha-console-runner" 62 | 63 | 64 | options["root-url"] ?= "http://localhost:#{options.port}/" 65 | 66 | if command is 'test' 67 | args.push(['--test-app-path'], options["test-app-path"]) if options["test-app-path"] 68 | args.push(['--full-app']) if options["full-app"] 69 | else if command is 'test-packages' 70 | if options.packages.length > 0 71 | packagesToTest = @_globPackages(options.packages) 72 | expect(packagesToTest).to.have.length.above 0 73 | args.push(packagesToTest) 74 | 75 | # Flatten args because we are adding arrays to args 76 | return _.flatten(args) 77 | 78 | 79 | 80 | testPackages: (options = {})-> 81 | log.debug "Meteor.testPackages()", arguments 82 | @runTestCommand("test-packages", options) 83 | 84 | testApp: (options = {})-> 85 | log.debug "Meteor.testApp()", arguments 86 | @runTestCommand("test", options) 87 | 88 | # => Exited with code: 89 | # => Your application has errors. Waiting for file change. 90 | # => Your application is crashing. Waiting for file change. 91 | # => Modified -- restarting. 92 | # => App running at: http://ronenvm:3000/ 93 | # => Meteor server restarted 94 | # => Errors prevented startup: 95 | 96 | # @options 97 | # @parseCommandLine 98 | runTestCommand: (command, options = {})=> 99 | log.debug "Meteor.runTestCommand()", arguments 100 | expect(options, "options should be an object.").to.be.an "object" 101 | expect(@childProcess, "Meteor's child process is already running").to.be.null 102 | 103 | @options = _.extend(@defaultOptions(), options) 104 | 105 | log.debug 'meteor options:', @options 106 | 107 | cwd = path.resolve(@options.dir); 108 | 109 | log.debug "meteor cwd=#{cwd}" 110 | 111 | expect(@options['driver-package'], "options.driver-package is missing").to.be.ok 112 | 113 | args = @getTestArgs(command, @options) 114 | 115 | log.debug 'meteor args=', args 116 | 117 | env = _.clone(process.env) 118 | # So packages will know they're running in the context of test-packages. 119 | # Not really a good practice, but sometimes just unavoidable. 120 | env.METEOR_TEST_PACKAGES='1' 121 | env.ROOT_URL = @options["root-url"] 122 | if @options["mongo-url"] 123 | env.MONGO_URL = @options["mongo-url"] 124 | else 125 | delete env.MONGO_URL if env.MONGO_URL? 126 | 127 | options = { 128 | cwd: cwd, 129 | env: env, 130 | detached: false 131 | } 132 | 133 | @childProcess = new ChildProcess() 134 | 135 | @childProcess.spawn("meteor",args,options) 136 | 137 | @childProcess.child.on "exit", (code,signal) => 138 | @emit "exit",code,signal 139 | 140 | @childProcess.child.stdout.on "data", (data) => 141 | @buffer.stdout += data 142 | @hasStartedMongoDBText data 143 | @hasErrorText data 144 | @hasReadyText data 145 | 146 | @childProcess.child.stderr.on "data", (data) => 147 | @buffer.stderr += data 148 | @hasErrorText data 149 | 150 | 151 | # TODO: Test 152 | _globPackages: (packages)-> # Use glob to get packages that match the packages arg 153 | log.debug "Meteor._globPackages()",arguments 154 | expect(packages,"@packages should be and array").to.be.an "array" 155 | 156 | pkgsFolder = process.cwd() + '/packages' 157 | 158 | globOpts = { 159 | cwd: pkgsFolder 160 | } 161 | 162 | matchedPackages = [] 163 | 164 | packages.forEach (pkgArg)=> 165 | if pkgArg.indexOf(':') > 0 166 | # It's a package name in the new format, we'll add it as is 167 | # TODO: Support globs for this too, by looking up package names inside package.js 168 | matchedPackages.push(pkgArg) 169 | else if pkgArg.indexOf('/') >= 0 170 | # It's a path to a package, we'll add it as is too 171 | # TODO: Support globs for this too 172 | matchedPackages.push(pkgArg) 173 | else 174 | # It's a package name, let's find matching package names, if it includes wildcards 175 | globedPackages = glob.sync(pkgArg, globOpts) 176 | if globedPackages.length > 0 177 | globedPackages.forEach (pkg)-> 178 | matchedPackages.push(pkg) 179 | else 180 | log.warn "spacjam: Warning: No packages matching #{pkgArg} have been found. Will add it to the meteor command line anyway, in case it's in PACKAGE_DIRS." 181 | # TODO: Support globs in PACKAGE_DIRS too. 182 | matchedPackages.push(pkgArg) 183 | 184 | return matchedPackages 185 | 186 | 187 | hasStartedMongoDBText: (buffer)=> 188 | if buffer.lastIndexOf('Started MongoDB') isnt -1 189 | @mongodb = new MeteorMongodb(@childProcess.child.pid) 190 | @emit "mongodb ready" 191 | 192 | 193 | hasErrorText: (buffer)=> 194 | if buffer.lastIndexOf( @defaultOptions()["meteor-error-text"] ) isnt -1 195 | @emit "error" 196 | 197 | 198 | hasReadyText: (buffer)=> 199 | if buffer.lastIndexOf( @defaultOptions()["meteor-ready-text"] ) isnt -1 200 | @emit "ready" 201 | 202 | 203 | hasMongodb: -> 204 | log.debug "Meteor.hasMongodb()" 205 | return @mongodb.hasMongodb() if @mongodb 206 | return false 207 | 208 | 209 | # TODO: Test 210 | kill: (signal="SIGTERM")-> 211 | log.debug "Meteor.kill()", arguments, "@childProcess?=", @childProcess?, "@mongodb?=", @mongodb? 212 | @childProcess?.kill(signal) 213 | @mongodb?.kill() 214 | 215 | module.exports = Meteor 216 | -------------------------------------------------------------------------------- /lib/MeteorMongodb.coffee: -------------------------------------------------------------------------------- 1 | expect = require('chai').expect 2 | EventEmitter = require('events').EventEmitter 3 | ps = require('psext') 4 | 5 | class MeteorMongodb extends EventEmitter 6 | 7 | mongodChilds: [] 8 | 9 | killed: false 10 | 11 | constructor: (@meteorPid)-> 12 | log.debug "MeteorMongodb.constructor()", arguments 13 | process.on 'exit', (code)=> 14 | log.debug "MeteorMongodb.process.on 'exit': code=#{code}" 15 | @kill() 16 | @findAllChildren() 17 | 18 | 19 | hasMongodb: -> 20 | log.debug "MeteorMongodb.hasMongodb()" 21 | @mongodChilds.length > 0 22 | 23 | 24 | findAllChildren: -> 25 | log.debug "MeteorMongodb.findAllChildren()", arguments 26 | log.debug "@meteorPid", @meteorPid 27 | ps.lookup 28 | command: 'mongod' 29 | psargs: '-l' 30 | ppid: @meteorPid 31 | , (err, resultList )=> 32 | @mongodChilds = resultList 33 | if (err) 34 | log.warn "spacjam: Warning: Couldn't find any mongod children:\n", err 35 | else if resultList.length > 1 36 | log.warn "spacjam: Warning: Found more than one mongod child:\n", resultList 37 | else 38 | log.debug "Found meteor mongod child with pid: ", resultList[0].pid 39 | 40 | 41 | kill: -> 42 | log.debug "MeteorMongodb.kill() killed=", @killed 43 | 44 | return if @killed 45 | @killed = true 46 | 47 | attempts = 1 48 | 49 | interval = null 50 | 51 | onInterval = => 52 | if attempts <= 40 53 | signal = 0 54 | if attempts is 1 55 | signal = "SIGTERM" 56 | else if attempts is 20 #or attempts is 30 57 | signal = "SIGKILL" 58 | try 59 | for mongod in @mongodChilds 60 | if not mongod.dead? 61 | try 62 | process.kill mongod.pid, signal 63 | catch e 64 | mongod.dead = true 65 | 66 | allDead = true 67 | for mongod in @mongodChilds 68 | if not mongod.dead? 69 | allDead = false 70 | return 71 | if allDead 72 | clearInterval(interval) 73 | @emit "kill-done", null, @mongodChilds 74 | attempts++ 75 | else 76 | clearInterval(interval) 77 | log.error "spacejam: Error: Unable to kill all mongodb children, even after 40 attempts" 78 | @emit "kill-done", new Error("Unable to kill all mongodb children, even after 40 attempts"), @mongodChilds 79 | 80 | onInterval() 81 | interval = setInterval onInterval, 100 82 | 83 | 84 | module.exports = MeteorMongodb 85 | -------------------------------------------------------------------------------- /lib/PackageJSStubs.coffee: -------------------------------------------------------------------------------- 1 | global.Package = 2 | description: null 3 | 4 | describe: (options) -> 5 | Package.description = options 6 | 7 | onUse: (f) -> 8 | return 9 | 10 | on_use: (f) -> 11 | return 12 | 13 | onTest: (f) -> 14 | return 15 | 16 | on_test: (f) -> 17 | return 18 | 19 | registerBuildPlugin: (options) -> 20 | return 21 | 22 | _transitional_registerBuildPlugin: (options) -> 23 | return 24 | 25 | includeTool: -> 26 | return 27 | 28 | 29 | global.Npm = 30 | depends: (_npmDependencies) -> 31 | return 32 | 33 | strip: (discards) -> 34 | return 35 | 36 | require: (name) -> 37 | return 38 | 39 | 40 | global.Cordova = 41 | depends: (_cordovaDependencies) -> 42 | return 43 | -------------------------------------------------------------------------------- /lib/Phantomjs.coffee: -------------------------------------------------------------------------------- 1 | _ = require "underscore" 2 | expect = require('chai').expect 3 | ChildProcess = require './ChildProcess' 4 | EventEmitter = require('events').EventEmitter 5 | path = require 'path' 6 | phantomjs = require 'phantomjs-prebuilt' 7 | 8 | DEFAULT_PATH = process.env.PATH 9 | 10 | 11 | class Phantomjs extends EventEmitter 12 | 13 | childProcess: null 14 | 15 | run: (url, options = '--load-images=no --ssl-protocol=TLSv1', script = "phantomjs-test-in-console.js", pipeClass = undefined, pipeClassOptions = undefined, useSystemPhantomjs = false)=> 16 | log.debug "Phantomjs.run()", arguments 17 | expect(@childProcess,"ChildProcess is already running").to.be.null 18 | expect(url, "Invalid url").to.be.a 'string' 19 | expect(options, "Invalid options").to.be.a 'string' 20 | expect(script, "Invalid script").to.be.a 'string' 21 | expect(pipeClass, "Invalid pipeClass").to.be.a 'function' if pipeClass? 22 | expect(pipeClassOptions, "Invalid pipeClassOptions").to.be.an 'object' if pipeClassOptions? 23 | expect(useSystemPhantomjs, "Invalid useSystemPhantomjs").to.be.a 'boolean' 24 | 25 | env = _.extend process.env, {ROOT_URL: url} 26 | 27 | log.debug("script=#{__dirname}/#{script}") 28 | spawnArgs = options.split(' ') 29 | spawnArgs.push(script) 30 | log.debug 'spawnArgs:', spawnArgs 31 | spawnOptions = 32 | cwd: __dirname 33 | detached: false 34 | env: env 35 | log.debug 'spawnOptions:', spawnOptions 36 | 37 | # Add phantomjs NPM package bin to PATH unless --use-system-phantomjs is passed 38 | if useSystemPhantomjs 39 | process.env.PATH = DEFAULT_PATH 40 | else 41 | process.env.PATH = path.dirname(phantomjs.path) + ':' + DEFAULT_PATH 42 | 43 | @childProcess = new ChildProcess() 44 | @childProcess.spawn("phantomjs", spawnArgs, spawnOptions, pipeClass, pipeClassOptions) 45 | 46 | @childProcess.child.on "exit", (code, signal) => 47 | @emit "exit", code, signal 48 | 49 | kill: (signal = "SIGTERM")-> 50 | log.debug "Phantomjs.kill()" 51 | @childProcess?.kill(signal) 52 | 53 | 54 | module.exports = Phantomjs 55 | 56 | -------------------------------------------------------------------------------- /lib/Pipe.coffee: -------------------------------------------------------------------------------- 1 | class Pipe 2 | 3 | constructor: (@stdout, @stderr)-> 4 | @stdout.setEncoding "utf8" 5 | @stderr.setEncoding "utf8" 6 | 7 | @stdout.on "data", (data)=> 8 | process.stdout.write data 9 | 10 | @stderr.on "data", (data)=> 11 | process.stderr.write data 12 | 13 | module.exports = Pipe 14 | -------------------------------------------------------------------------------- /lib/Spacejam.coffee: -------------------------------------------------------------------------------- 1 | require('./log') 2 | expect = require("chai").expect 3 | _ = require("underscore") 4 | EventEmitter = require('events').EventEmitter 5 | Meteor = require("./Meteor") 6 | Phantomjs = require("./Phantomjs") 7 | XunitFilePipe = require './XunitFilePipe' 8 | 9 | 10 | class Spacejam extends EventEmitter 11 | 12 | instance = null 13 | 14 | @get: -> 15 | instance ?= new Spacejam() 16 | 17 | defaultOptions: -> 18 | { 19 | 'phantomjs-script': 'phantomjs-test-in-console.js' 20 | 'phantomjs-options': '--load-images=no --ssl-protocol=TLSv1' 21 | } 22 | 23 | meteor: null 24 | 25 | waitForMeteorMongodbKillDone: false 26 | 27 | phantomjs: null 28 | 29 | doneCode: null 30 | 31 | childrenKilled: false 32 | 33 | @DONE: 34 | TEST_SUCCESS: 0 35 | TEST_FAILED: 2 36 | METEOR_ERROR: 3 37 | TEST_TIMEOUT: 4 38 | ALREADY_RUNNING: 5 39 | CLIENT_ERROR: 6 40 | 41 | @DONE_MESSAGE: [ 42 | "All tests have passed" 43 | "Usage error" 44 | "Some tests have failed" 45 | "meteor is crashing server side" 46 | "Total timeout for tests has been reached" 47 | "spacejam is already running" 48 | "Unhandled error in meteor client side code" 49 | ] 50 | 51 | constructor: -> 52 | log.debug "Spacejam.constructor()" 53 | 54 | 55 | runTests: (command, options = {})-> 56 | log.debug "Spacejam.testPackages()", options 57 | expect(options).to.be.an "object" 58 | expect(command).to.be.a "string" 59 | expect(options.timeout).to.be.a 'number' if options.timeout? 60 | expect(options['crash-spacejam-after']).to.be.a 'number' if options['crash-spacejam-after']? 61 | 62 | expect(@meteor, "Meteor is already running").to.be.null 63 | 64 | @options = _.extend @defaultOptions(), options 65 | log.debug @options 66 | 67 | try 68 | @meteor = new Meteor() 69 | @phantomjs = new Phantomjs() 70 | catch err 71 | console.trace err 72 | @emit "done", 1 73 | return 74 | 75 | 76 | @meteor.on "exit", (code)=> 77 | log.debug "Spacejam.meteor.on 'exit':", arguments 78 | @meteor = null 79 | if code 80 | @killChildren Spacejam.DONE.METEOR_ERROR 81 | 82 | @meteor.on "mongodb ready", => 83 | log.info "spacejam: meteor mongodb is ready" 84 | @waitForMeteorMongodbKillDone = true 85 | @meteor.mongodb.on "kill-done", @onMeteorMongodbKillDone 86 | 87 | @meteor.on "ready", => 88 | log.info "spacejam: meteor is ready" 89 | 90 | scriptArgs = '' 91 | pipeClass = null 92 | spawnOptions = {} 93 | 94 | @runPhantom() 95 | 96 | @meteor.on "error", => 97 | log.error "spacejam: meteor has errors" 98 | @killChildren(Spacejam.DONE.METEOR_ERROR) if not @options.watch 99 | 100 | try 101 | @meteor.runTestCommand(command, @options) 102 | catch err 103 | console.trace err 104 | @emit "done", 1 105 | return 106 | 107 | if @options.timeout? and +@options.timeout > 0 108 | setTimeout => 109 | log.error "spacejam: Error: tests timed out after #{options.timeout} milliseconds." 110 | @killChildren( Spacejam.DONE.TEST_TIMEOUT ) 111 | , +options.timeout 112 | 113 | if @options['crash-spacejam-after']? and +@options['crash-spacejam-after'] > 0 114 | setTimeout => 115 | throw new Error("Testing spacejam crashing.") 116 | , +options['crash-spacejam-after'] 117 | 118 | 119 | runPhantom: -> 120 | log.debug "Spacejam.runPhantom()" 121 | expect(@phantomjs).to.be.ok 122 | expect(@meteor.options["root-url"]).to.be.ok 123 | expect(@options["phantomjs-options"]).to.be.ok 124 | expect(@options["phantomjs-script"]).to.be.ok 125 | 126 | url = @meteor.options["root-url"] 127 | 128 | if @options['xunit-out']? 129 | url += 'xunit' 130 | pipeClass = XunitFilePipe 131 | pipeClassOptions = pipeToFile: @options['xunit-out'] 132 | else 133 | url += 'local' 134 | 135 | @phantomjs.on "exit", (code, signal)=> 136 | @phantomjs = null 137 | @meteor?.kill() 138 | if code? 139 | @done code 140 | 141 | @phantomjs.run(url, @options['phantomjs-options'], @options['phantomjs-script'], pipeClass, pipeClassOptions, @options['use-system-phantomjs']?) 142 | 143 | 144 | onMeteorMongodbKillDone: => 145 | log.debug "Spacejam.onMeteorMongodbKillDone()", @doneCode 146 | @emit "done", @doneCode 147 | 148 | 149 | #Kill all running child_process instances 150 | killChildren: (code = 1)-> 151 | log.debug "Spacejam.killChildren()",arguments 152 | expect(code,"Invalid exit code").to.be.a "number" 153 | 154 | if not @childrenKilled 155 | @meteor?.kill() 156 | @phantomjs?.kill() 157 | @childrenKilled = true 158 | @done(code) 159 | 160 | 161 | done: (code)-> 162 | log.debug "Spacejam.done()", arguments 163 | expect(code, "Invalid done code").to.be.a "number" 164 | 165 | log.debug 'Spacejam.done() @meteor?=' + @meteor? 166 | @waitForMeteorMongodbKillDone = @meteor?.hasMongodb() 167 | log.debug 'Spacejam.done() @waitForMeteorMongodbKillDone=' + @waitForMeteorMongodbKillDone 168 | @emit "done", code if not @waitForMeteorMongodbKillDone 169 | log.debug 'Spacejam.done() waiting for mongodb to exit before calling done' 170 | @doneCode = code 171 | 172 | 173 | module.exports = Spacejam 174 | -------------------------------------------------------------------------------- /lib/XunitFilePipe.coffee: -------------------------------------------------------------------------------- 1 | fs = require('fs') 2 | Pipe = require("./Pipe") 3 | 4 | class XunitFilePipe extends Pipe 5 | constructor: (@stdout, @stderr, @options)-> 6 | @stdout.setEncoding "utf8" 7 | @stderr.setEncoding "utf8" 8 | 9 | outputFile = @options.pipeToFile 10 | outputStream = fs.createWriteStream(outputFile, { 11 | flags: 'w' 12 | encoding: 'utf8' 13 | }) 14 | 15 | @stdoutBuffer = '' 16 | 17 | @stdout.on "data", (data)=> 18 | @stdoutBuffer += data 19 | lines = @stdoutBuffer.split('\n') 20 | return if lines.length is 1 # No complete lines received yet 21 | @stdoutBuffer = lines.pop() # Save last incomplete line in stdout buffer 22 | for line in lines 23 | if line.indexOf('##_meteor_magic##xunit: ') is 0 24 | outputStream.write line.substr(24) + '\n' 25 | else 26 | process.stdout.write line + '\n' 27 | 28 | @stderr.on "data", (data)=> 29 | process.stderr.write data 30 | 31 | 32 | module.exports = XunitFilePipe 33 | -------------------------------------------------------------------------------- /lib/log.coffee: -------------------------------------------------------------------------------- 1 | global.log = require('loglevel') 2 | 3 | logLevelOpts = require("rc")("spacejam",{ 4 | "loglevel" : "info" 5 | }) 6 | 7 | #originalFactory = log.methodFactory 8 | # 9 | #log.methodFactory = (methodName, logLevel)=> 10 | # console.error 'loglevel=', level 11 | # rawMethod = originalFactory(methodName, level) 12 | # return (message)=> 13 | # rawMethod("spacejam: " + message) 14 | # 15 | log.setLevel logLevelOpts["loglevel"] 16 | -------------------------------------------------------------------------------- /lib/main.coffee: -------------------------------------------------------------------------------- 1 | npmExports = {} 2 | 3 | npmExports.Spacejam = require("./Spacejam") 4 | npmExports.Meteor = require("./Meteor") 5 | npmExports.Phantomjs = require("./Phantomjs") 6 | 7 | module.exports = npmExports 8 | -------------------------------------------------------------------------------- /lib/phantomjs-test-in-console.js: -------------------------------------------------------------------------------- 1 | var page, system; 2 | 3 | page = require('webpage').create(); 4 | 5 | system = require('system'); 6 | 7 | // TODO replace test-in-console with actual driver package 8 | console.log("phantomjs: Running tests at " + system.env.ROOT_URL + " using test-in-console"); 9 | 10 | page.onConsoleMessage = function (message) { 11 | console.log(message); 12 | }; 13 | 14 | page.open(system.env.ROOT_URL); 15 | 16 | page.onError = function (msg, trace) { 17 | var mochaIsRunning; 18 | mochaIsRunning = page.evaluate(function () { 19 | return window.mochaIsRunning; 20 | }); 21 | if (mochaIsRunning) { 22 | return; 23 | } 24 | console.log("phantomjs: " + msg); 25 | trace.forEach(function (item) { 26 | console.log(" " + item.file + ": " + item.line); 27 | }); 28 | phantom.exit(6); 29 | }; 30 | 31 | setInterval(function () { 32 | var done, failures; 33 | done = page.evaluate(function () { 34 | if (typeof TEST_STATUS !== "undefined" && TEST_STATUS !== null) { 35 | return TEST_STATUS.DONE; 36 | } 37 | if (typeof DONE !== "undefined" && DONE !== null) { 38 | return DONE; 39 | } 40 | return false; 41 | }); 42 | if (done) { 43 | failures = page.evaluate(function () { 44 | if (typeof TEST_STATUS !== "undefined" && TEST_STATUS !== null) { 45 | return TEST_STATUS.FAILURES; 46 | } 47 | if (typeof FAILURES !== "undefined" && FAILURES !== null) { 48 | return FAILURES; 49 | } 50 | return false; 51 | }); 52 | return phantom.exit(failures ? 2 : 0); 53 | } 54 | }, 500); 55 | 56 | // --- 57 | // generated by coffee-script 1.9.2 -------------------------------------------------------------------------------- /lib/phantomjs-test-in-velocity.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.8.0 2 | (function() { 3 | var page, system; 4 | 5 | page = require('webpage').create(); 6 | 7 | system = require('system'); 8 | 9 | console.log("phantomjs: Running tests at " + system.env.ROOT_URL + " using test-in-velocity"); 10 | 11 | page.onConsoleMessage = function(message) { 12 | return console.log(message); 13 | }; 14 | 15 | page.open(system.env.ROOT_URL); 16 | 17 | }).call(this); 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "spacejam", 3 | "version": "1.6.1", 4 | "dependencies": { 5 | "chai": "1.9.2", 6 | "glob": "4.0.6", 7 | "loglevel": "1.1.0", 8 | "phantomjs-prebuilt": "^2.1.7", 9 | "psext": "0.0.4", 10 | "rc": "0.5.1", 11 | "semver": "4.1.0", 12 | "underscore": "1.7.0" 13 | }, 14 | "devDependencies": { 15 | "coffee-script": "1.8.0", 16 | "mocha": "1.21.5", 17 | "sinon-chai": "2.6.0", 18 | "tmp": "0.0.25", 19 | "xmldom": "0.1.19", 20 | "xpath": "0.0.9" 21 | }, 22 | "main": "lib/main.js", 23 | "scripts": { 24 | "test": "bin/npm-test.sh", 25 | "compile": "cake compile", 26 | "prepublish": "cake compile" 27 | }, 28 | "bin": { 29 | "spacejam": "bin/spacejam", 30 | "spacejam-mocha": "bin/spacejam-mocha", 31 | "spacejam-init-bashrc": "bin/spacejam-init-bashrc", 32 | "meteor-mocha": "bin/meteor-mocha", 33 | "mrun": "bin/mrun", 34 | "mtp": "bin/mtp", 35 | "set-meteor-env": "bin/set-meteor-env", 36 | "unset-meteor-env": "bin/unset-meteor-env", 37 | "mongo-reset": "bin/mongo-reset", 38 | "mdeploy": "bin/mdeploy", 39 | "mpublish": "bin/mpublish", 40 | "mmpublish": "bin/mmpublish", 41 | "npm-publish": "bin/npm-publish" 42 | }, 43 | "description": "Run your meteor package tinytests and mocha tests from the command line with phantomjs.", 44 | "homepage": "https://github.com/practicalmeteor/spacejam", 45 | "bugs": "https://github.com/practicalmeteor/spacejam/issues", 46 | "keywords": [ 47 | "spacejam", 48 | "meteor", 49 | "test-packages", 50 | "test-in-console", 51 | "tinytest", 52 | "mocha", 53 | "mocha.js", 54 | "practicalmeteor", 55 | "practicalmeteor:mocha", 56 | "practicalmeteor:mocha-console-runner", 57 | "ci", 58 | "continuous integration", 59 | "cd", 60 | "continuous delivery" 61 | ], 62 | "licenses": [ 63 | { 64 | "type": "MIT", 65 | "url": "https://github.com/practicalmeteor/spacejam/blob/master/LICENSE.txt" 66 | } 67 | ], 68 | "engines": { 69 | "node": ">= 0.10.x", 70 | "npm": ">= 1.4.x" 71 | }, 72 | "repository": { 73 | "type": "git", 74 | "url": "https://github.com/practicalmeteor/spacejam.git" 75 | }, 76 | "author": { 77 | "name": "Spacejam.io", 78 | "url": "http://spacejam.io/" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /packages.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | notices-for-facebook-graph-api-2 9 | 1.2.0-standard-minifiers-package 10 | 1.2.0-meteor-platform-split 11 | 1.2.0-cordova-changes 12 | 1.2.0-breaking-changes 13 | 1.3.0-split-minifiers-package 14 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/.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 | 1bh8l5qn9dk77ahre38 8 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/.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 # Packages every Meteor app needs to have 8 | mobile-experience # Packages for a great mobile UX 9 | mongo # The database Meteor supports right now 10 | blaze-html-templates # Compile .html files into Meteor Blaze views 11 | reactive-var # Reactive variable for tracker 12 | jquery # Helpful client-side library 13 | tracker # Meteor's client-side reactive programming library 14 | 15 | standard-minifier-css # CSS minifier run for production mode 16 | standard-minifier-js # JS minifier run for production mode 17 | es5-shim # ECMAScript 5 compatibility for older browsers. 18 | ecmascript # Enable ECMAScript2015+ syntax in app code 19 | 20 | autopublish # Publish all data to the clients (for prototyping) 21 | insecure # Allow all DB writes from clients (for prototyping) 22 | practicalmeteor:mocha@2.4.5_2 23 | practicalmeteor:mocha-console-runner@0.2.0 24 | practicalmeteor:chai 25 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.3 2 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/.meteor/versions: -------------------------------------------------------------------------------- 1 | allow-deny@1.0.2 2 | autopublish@1.0.5 3 | autoupdate@1.2.6 4 | babel-compiler@6.5.2 5 | babel-runtime@0.1.6 6 | base64@1.0.6 7 | binary-heap@1.0.6 8 | blaze@2.1.5 9 | blaze-html-templates@1.0.2 10 | blaze-tools@1.0.6 11 | boilerplate-generator@1.0.6 12 | caching-compiler@1.0.2 13 | caching-html-compiler@1.0.4 14 | callback-hook@1.0.6 15 | check@1.1.2 16 | coffeescript@1.0.15 17 | ddp@1.2.3 18 | ddp-client@1.2.3 19 | ddp-common@1.2.3 20 | ddp-server@1.2.4 21 | deps@1.0.10 22 | diff-sequence@1.0.3 23 | ecmascript@0.4.1 24 | ecmascript-runtime@0.2.8 25 | ejson@1.0.9 26 | es5-shim@4.5.8 27 | fastclick@1.0.9 28 | geojson-utils@1.0.6 29 | hot-code-push@1.0.2 30 | html-tools@1.0.7 31 | htmljs@1.0.7 32 | http@1.1.3 33 | id-map@1.0.5 34 | insecure@1.0.5 35 | jquery@1.11.6 36 | launch-screen@1.0.8 37 | livedata@1.0.16 38 | logging@1.0.10 39 | meteor@1.1.12 40 | meteor-base@1.0.2 41 | minifier-css@1.1.9 42 | minifier-js@1.1.9 43 | minimongo@1.0.12 44 | mobile-experience@1.0.2 45 | mobile-status-bar@1.0.10 46 | modules@0.5.1 47 | modules-runtime@0.6.1 48 | mongo@1.1.5 49 | mongo-id@1.0.2 50 | npm-mongo@1.4.41 51 | observe-sequence@1.0.9 52 | ordered-dict@1.0.5 53 | practicalmeteor:chai@2.1.0_1 54 | practicalmeteor:loglevel@1.2.0_2 55 | practicalmeteor:mocha@2.4.6-rc.1 56 | practicalmeteor:mocha-console-runner@0.2.1-rc.2 57 | practicalmeteor:mocha-core@0.1.4 58 | practicalmeteor:sinon@1.14.1_2 59 | promise@0.6.5 60 | random@1.0.7 61 | reactive-var@1.0.7 62 | reload@1.1.6 63 | retry@1.0.5 64 | routepolicy@1.0.8 65 | spacebars@1.0.9 66 | spacebars-compiler@1.0.9 67 | standard-minifier-css@1.0.4 68 | standard-minifier-js@1.0.4 69 | templating@1.1.7 70 | templating-tools@1.0.2 71 | tmeasday:test-reporter-helpers@0.2.1 72 | tracker@1.0.11 73 | ui@1.0.9 74 | underscore@1.0.6 75 | url@1.0.7 76 | webapp@1.2.6 77 | webapp-hashing@1.0.7 78 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/app.app-tests.js: -------------------------------------------------------------------------------- 1 | import {expect} from "meteor/practicalmeteor:chai" 2 | 3 | describe("Test", ()=>{ 4 | 5 | it("This app test should fail", ()=>{ 6 | expect(true).to.be.false 7 | }) 8 | 9 | }); 10 | 11 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/app.tests.js: -------------------------------------------------------------------------------- 1 | import {expect} from "meteor/practicalmeteor:chai" 2 | 3 | describe("Test", ()=>{ 4 | 5 | it("This unit test should fail", ()=>{ 6 | expect(true).to.be.false 7 | }) 8 | 9 | }); 10 | 11 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/client/main.css: -------------------------------------------------------------------------------- 1 | /* CSS declarations go here */ 2 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/client/main.html: -------------------------------------------------------------------------------- 1 | 2 | simple 3 | 4 | 5 | 6 |

Welcome to Meteor!

7 | 8 | {{> hello}} 9 | {{> info}} 10 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/client/main.js: -------------------------------------------------------------------------------- 1 | import { Template } from 'meteor/templating'; 2 | import { ReactiveVar } from 'meteor/reactive-var'; 3 | 4 | import './main.html'; 5 | 6 | Template.hello.onCreated(function helloOnCreated() { 7 | // counter starts at 0 8 | this.counter = new ReactiveVar(0); 9 | }); 10 | 11 | Template.hello.helpers({ 12 | counter() { 13 | return Template.instance().counter.get(); 14 | }, 15 | }); 16 | 17 | Template.hello.events({ 18 | 'click button'(event, instance) { 19 | // increment the counter when button is clicked 20 | instance.counter.set(instance.counter.get() + 1); 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "failing-app-tests", 3 | "private": true, 4 | "scripts": { 5 | "start": "meteor run" 6 | }, 7 | "dependencies": { 8 | "meteor-node-stubs": "~0.2.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/apps/failing-app-tests/server/main.js: -------------------------------------------------------------------------------- 1 | import { Meteor } from 'meteor/meteor'; 2 | 3 | Meteor.startup(() => { 4 | // code to run on server at startup 5 | }); 6 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | versions 3 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/.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 | zelo5i1amay5feb3c7s 8 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # 3 | # 'meteor add' and 'meteor remove' will edit this file for you, 4 | # but you can also edit it by hand. 5 | 6 | standard-app-packages 7 | autopublish 8 | insecure 9 | preserve-inputs 10 | success 11 | settings 12 | failure 13 | timeout 14 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.0.2 2 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/leaderboard.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 3 | font-weight: 200; 4 | margin: 50px 0; 5 | padding: 0; 6 | -webkit-user-select: none; 7 | -khtml-user-select: none; 8 | -moz-user-select: none; 9 | -o-user-select: none; 10 | user-select: none; 11 | } 12 | 13 | #outer { 14 | width: 600px; 15 | margin: 0 auto; 16 | } 17 | 18 | .player { 19 | cursor: pointer; 20 | padding: 5px; 21 | } 22 | 23 | .player .name { 24 | display: inline-block; 25 | width: 300px; 26 | font-size: 1.75em; 27 | } 28 | 29 | .player .score { 30 | display: inline-block; 31 | width: 100px; 32 | text-align: right; 33 | font-size: 2em; 34 | font-weight: bold; 35 | color: #777; 36 | } 37 | 38 | .player.selected { 39 | background-color: yellow; 40 | } 41 | 42 | .player.selected .score { 43 | color: black; 44 | } 45 | 46 | .details, .none { 47 | font-weight: bold; 48 | font-size: 2em; 49 | border-style: dashed none none none; 50 | border-color: #ccc; 51 | border-width: 4px; 52 | margin: 50px 10px; 53 | padding: 10px 0px; 54 | } 55 | 56 | .none { 57 | color: #777; 58 | } 59 | 60 | .inc { 61 | cursor: pointer; 62 | } 63 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/leaderboard.html: -------------------------------------------------------------------------------- 1 | 2 | Leaderboard 3 | 4 | 5 | 6 |
7 | {{> leaderboard}} 8 |
9 | 10 | 11 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/leaderboard.js: -------------------------------------------------------------------------------- 1 | // Set up a collection to contain player information. On the server, 2 | // it is backed by a MongoDB collection named "players". 3 | 4 | Players = new Meteor.Collection("players"); 5 | 6 | if (Meteor.isClient) { 7 | Template.leaderboard.players = function () { 8 | return Players.find({}, {sort: {score: -1, name: 1}}); 9 | }; 10 | 11 | Template.leaderboard.selected_name = function () { 12 | var player = Players.findOne(Session.get("selected_player")); 13 | return player && player.name; 14 | }; 15 | 16 | Template.player.selected = function () { 17 | return Session.equals("selected_player", this._id) ? "selected" : ''; 18 | }; 19 | 20 | Template.leaderboard.events({ 21 | 'click input.inc': function () { 22 | Players.update(Session.get("selected_player"), {$inc: {score: 5}}); 23 | } 24 | }); 25 | 26 | Template.player.events({ 27 | 'click': function () { 28 | Session.set("selected_player", this._id); 29 | } 30 | }); 31 | } 32 | 33 | // On server startup, create some players if the database is empty. 34 | if (Meteor.isServer) { 35 | Meteor.startup(function () { 36 | if (Players.find().count() === 0) { 37 | var names = ["Ada Lovelace", 38 | "Grace Hopper", 39 | "Marie Curie", 40 | "Carl Friedrich Gauss", 41 | "Nikola Tesla", 42 | "Claude Shannon"]; 43 | for (var i = 0; i < names.length; i++) 44 | Players.insert({name: names[i], score: Math.floor(Random.fraction()*10)*5}); 45 | } 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/failure/.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/failure/failure-test.coffee: -------------------------------------------------------------------------------- 1 | Tinytest.add "failure",(test)-> 2 | test.equal true, false 3 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/failure/failure.coffee: -------------------------------------------------------------------------------- 1 | console.log("I am package: leaderboard/failure") 2 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/failure/package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | summary: "failure" 3 | }); 4 | 5 | Package.onUse(function (api) { 6 | api.use(['coffeescript']); 7 | 8 | api.addFiles(['failure.coffee']) 9 | }); 10 | 11 | Package.onTest(function(api) { 12 | api.use(['coffeescript', 'tinytest', 'failure']); 13 | 14 | api.addFiles('failure-test.coffee'); 15 | }); 16 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/failure/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | [ 4 | "coffeescript", 5 | "1.0.4" 6 | ], 7 | [ 8 | "meteor", 9 | "1.1.3" 10 | ], 11 | [ 12 | "underscore", 13 | "1.0.1" 14 | ] 15 | ], 16 | "pluginDependencies": [], 17 | "toolVersion": "meteor-tool@1.0.36", 18 | "format": "1.0" 19 | } -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/settings/.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/settings/package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | summary: "settings" 3 | }); 4 | 5 | Package.onUse(function (api) { 6 | api.use(['meteor', 'coffeescript']); 7 | 8 | api.addFiles(['settings.coffee']) 9 | }); 10 | 11 | Package.onTest(function(api) { 12 | api.use(['meteor', 'coffeescript', 'tinytest', 'settings']); 13 | 14 | api.addFiles('settings-test.coffee'); 15 | }); 16 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/settings/settings-test.coffee: -------------------------------------------------------------------------------- 1 | Tinytest.add "settings",(test)-> 2 | if Meteor.isServer 3 | test.equal Meteor.settings.serverSetting, "server" 4 | else 5 | test.equal Meteor.settings.public.clientSetting, "client" 6 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/settings/settings.coffee: -------------------------------------------------------------------------------- 1 | console.log("I am package: leaderboard/settings") 2 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/settings/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | [ 4 | "coffeescript", 5 | "1.0.4" 6 | ], 7 | [ 8 | "meteor", 9 | "1.1.3" 10 | ], 11 | [ 12 | "underscore", 13 | "1.0.1" 14 | ] 15 | ], 16 | "pluginDependencies": [], 17 | "toolVersion": "meteor-tool@1.0.36", 18 | "format": "1.0" 19 | } -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/success/.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/success/package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | summary: "success" 3 | }); 4 | 5 | Package.onUse(function (api) { 6 | api.use(['coffeescript']); 7 | 8 | api.addFiles(['success.coffee']) 9 | }); 10 | 11 | Package.onTest(function(api) { 12 | api.use(['coffeescript', 'tinytest', 'success']); 13 | 14 | api.addFiles('success-test.coffee'); 15 | }); 16 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/success/success-test.coffee: -------------------------------------------------------------------------------- 1 | Tinytest.add "success",(test)-> 2 | test.equal true, true 3 | 4 | if Meteor.isServer 5 | Tinytest.add "process.env.METEOR_TEST_PACKAGES is '1'",(test)-> 6 | test.equal process.env.METEOR_TEST_PACKAGES, '1' 7 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/success/success.coffee: -------------------------------------------------------------------------------- 1 | console.log("I am package: leaderboard/success") 2 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/success/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | [ 4 | "coffeescript", 5 | "1.0.4" 6 | ], 7 | [ 8 | "meteor", 9 | "1.1.3" 10 | ], 11 | [ 12 | "underscore", 13 | "1.0.1" 14 | ] 15 | ], 16 | "pluginDependencies": [], 17 | "toolVersion": "meteor-tool@1.0.36", 18 | "format": "1.0" 19 | } -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/timeout/.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/timeout/package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | summary: "timeout" 3 | }); 4 | 5 | Package.onUse(function (api) { 6 | api.use(['coffeescript']); 7 | 8 | api.addFiles(['timeout.coffee']) 9 | }); 10 | 11 | Package.onTest(function(api) { 12 | api.use(['coffeescript', 'tinytest', 'timeout']); 13 | 14 | api.addFiles('timeout-test.coffee'); 15 | }); 16 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/timeout/timeout-test.coffee: -------------------------------------------------------------------------------- 1 | Tinytest.addAsync "timeout",(test, onComplete)-> 2 | test.equal true, true 3 | # Never call onComplete so test will timeout 4 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/timeout/timeout.coffee: -------------------------------------------------------------------------------- 1 | console.log("I am package: leaderboard/timeout") 2 | -------------------------------------------------------------------------------- /tests/apps/leaderboard/packages/timeout/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | [ 4 | "coffeescript", 5 | "1.0.4" 6 | ], 7 | [ 8 | "meteor", 9 | "1.1.3" 10 | ], 11 | [ 12 | "underscore", 13 | "1.0.1" 14 | ] 15 | ], 16 | "pluginDependencies": [], 17 | "toolVersion": "meteor-tool@1.0.36", 18 | "format": "1.0" 19 | } -------------------------------------------------------------------------------- /tests/apps/leaderboard/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "serverSetting": "server", 3 | "public": { 4 | "clientSetting": "client" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | notices-for-facebook-graph-api-2 9 | 1.2.0-standard-minifiers-package 10 | 1.2.0-meteor-platform-split 11 | 1.2.0-cordova-changes 12 | 1.2.0-breaking-changes 13 | 1.3.0-split-minifiers-package 14 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/.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 | 63nuz2j5k347160cerl 8 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/.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 # Packages every Meteor app needs to have 8 | mobile-experience # Packages for a great mobile UX 9 | mongo # The database Meteor supports right now 10 | blaze-html-templates # Compile .html files into Meteor Blaze views 11 | reactive-var # Reactive variable for tracker 12 | jquery # Helpful client-side library 13 | tracker # Meteor's client-side reactive programming library 14 | 15 | standard-minifier-css # CSS minifier run for production mode 16 | standard-minifier-js # JS minifier run for production mode 17 | es5-shim # ECMAScript 5 compatibility for older browsers. 18 | ecmascript # Enable ECMAScript2015+ syntax in app code 19 | 20 | autopublish # Publish all data to the clients (for prototyping) 21 | insecure # Allow all DB writes from clients (for prototyping) 22 | practicalmeteor:mocha@2.4.5_2 23 | practicalmeteor:mocha-console-runner@0.2.0 24 | practicalmeteor:chai 25 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.3 2 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/.meteor/versions: -------------------------------------------------------------------------------- 1 | allow-deny@1.0.2 2 | autopublish@1.0.5 3 | autoupdate@1.2.6 4 | babel-compiler@6.5.2 5 | babel-runtime@0.1.6 6 | base64@1.0.6 7 | binary-heap@1.0.6 8 | blaze@2.1.5 9 | blaze-html-templates@1.0.2 10 | blaze-tools@1.0.6 11 | boilerplate-generator@1.0.6 12 | caching-compiler@1.0.2 13 | caching-html-compiler@1.0.4 14 | callback-hook@1.0.6 15 | check@1.1.2 16 | coffeescript@1.0.15 17 | ddp@1.2.3 18 | ddp-client@1.2.3 19 | ddp-common@1.2.3 20 | ddp-server@1.2.4 21 | deps@1.0.10 22 | diff-sequence@1.0.3 23 | ecmascript@0.4.1 24 | ecmascript-runtime@0.2.8 25 | ejson@1.0.9 26 | es5-shim@4.5.8 27 | fastclick@1.0.9 28 | geojson-utils@1.0.6 29 | hot-code-push@1.0.2 30 | html-tools@1.0.7 31 | htmljs@1.0.7 32 | http@1.1.3 33 | id-map@1.0.5 34 | insecure@1.0.5 35 | jquery@1.11.6 36 | launch-screen@1.0.8 37 | livedata@1.0.16 38 | logging@1.0.10 39 | meteor@1.1.12 40 | meteor-base@1.0.2 41 | minifier-css@1.1.9 42 | minifier-js@1.1.9 43 | minimongo@1.0.12 44 | mobile-experience@1.0.2 45 | mobile-status-bar@1.0.10 46 | modules@0.5.1 47 | modules-runtime@0.6.1 48 | mongo@1.1.5 49 | mongo-id@1.0.2 50 | npm-mongo@1.4.41 51 | observe-sequence@1.0.9 52 | ordered-dict@1.0.5 53 | practicalmeteor:chai@2.1.0_1 54 | practicalmeteor:loglevel@1.2.0_2 55 | practicalmeteor:mocha@2.4.6-rc.1 56 | practicalmeteor:mocha-console-runner@0.2.1-rc.2 57 | practicalmeteor:mocha-core@0.1.4 58 | practicalmeteor:sinon@1.14.1_2 59 | promise@0.6.5 60 | random@1.0.7 61 | reactive-var@1.0.7 62 | reload@1.1.6 63 | retry@1.0.5 64 | routepolicy@1.0.8 65 | spacebars@1.0.9 66 | spacebars-compiler@1.0.9 67 | standard-minifier-css@1.0.4 68 | standard-minifier-js@1.0.4 69 | templating@1.1.7 70 | templating-tools@1.0.2 71 | tmeasday:test-reporter-helpers@0.2.1 72 | tracker@1.0.11 73 | ui@1.0.9 74 | underscore@1.0.6 75 | url@1.0.7 76 | webapp@1.2.6 77 | webapp-hashing@1.0.7 78 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/app.app-tests.js: -------------------------------------------------------------------------------- 1 | import {expect} from "meteor/practicalmeteor:chai" 2 | 3 | describe("Test", ()=>{ 4 | 5 | it("This app test should pass", ()=>{ 6 | expect(true).to.be.true 7 | }) 8 | 9 | }); 10 | 11 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/app.tests.js: -------------------------------------------------------------------------------- 1 | import {expect} from "meteor/practicalmeteor:chai" 2 | 3 | describe("Test", ()=>{ 4 | 5 | it("This unit test should pass", ()=>{ 6 | expect(true).to.be.true 7 | }) 8 | 9 | }); 10 | 11 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/client/main.css: -------------------------------------------------------------------------------- 1 | /* CSS declarations go here */ 2 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/client/main.html: -------------------------------------------------------------------------------- 1 | 2 | simple 3 | 4 | 5 | 6 |

Welcome to Meteor!

7 | 8 | {{> hello}} 9 | {{> info}} 10 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/client/main.js: -------------------------------------------------------------------------------- 1 | import { Template } from 'meteor/templating'; 2 | import { ReactiveVar } from 'meteor/reactive-var'; 3 | 4 | import './main.html'; 5 | 6 | Template.hello.onCreated(function helloOnCreated() { 7 | // counter starts at 0 8 | this.counter = new ReactiveVar(0); 9 | }); 10 | 11 | Template.hello.helpers({ 12 | counter() { 13 | return Template.instance().counter.get(); 14 | }, 15 | }); 16 | 17 | Template.hello.events({ 18 | 'click button'(event, instance) { 19 | // increment the counter when button is clicked 20 | instance.counter.set(instance.counter.get() + 1); 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "passing-app-tests", 3 | "private": true, 4 | "scripts": { 5 | "start": "meteor run" 6 | }, 7 | "dependencies": { 8 | "meteor-node-stubs": "~0.2.0" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/apps/passing-app-tests/server/main.js: -------------------------------------------------------------------------------- 1 | import { Meteor } from 'meteor/meteor'; 2 | 3 | Meteor.startup(() => { 4 | // code to run on server at startup 5 | }); 6 | -------------------------------------------------------------------------------- /tests/apps/todos/.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | -------------------------------------------------------------------------------- /tests/apps/todos/.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | versions 3 | -------------------------------------------------------------------------------- /tests/apps/todos/.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 | lnqc3qby8uspjom45 8 | -------------------------------------------------------------------------------- /tests/apps/todos/.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # 3 | # 'meteor add' and 'meteor remove' will edit this file for you, 4 | # but you can also edit it by hand. 5 | 6 | standard-app-packages 7 | underscore 8 | backbone 9 | spiderable 10 | jquery 11 | preserve-inputs 12 | insecure 13 | appfails 14 | -------------------------------------------------------------------------------- /tests/apps/todos/.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /tests/apps/todos/.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.0.2 2 | -------------------------------------------------------------------------------- /tests/apps/todos/client/todos.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | ul { 7 | list-style: none; 8 | } 9 | 10 | html, body { 11 | height: 100%; 12 | } 13 | 14 | body { 15 | font-size: 16px; 16 | line-height: 1.5; 17 | background: #eeeeee; 18 | color: #333333; 19 | } 20 | 21 | body, input { 22 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 23 | } 24 | 25 | input { 26 | font-size: 100%; 27 | } 28 | 29 | a, a:visited, a:active { 30 | color: #258; 31 | } 32 | 33 | h3 { 34 | font-weight: bold; 35 | text-decoration: underline; 36 | font-size: 120%; 37 | padding: 8px 6px; 38 | text-align: center; 39 | } 40 | 41 | #top-tag-filter, #main-pane, #side-pane, #bottom-pane { 42 | position: absolute; 43 | left: 0; 44 | right: 0; 45 | top: 0; 46 | bottom: 0; 47 | overflow: hidden; 48 | } 49 | 50 | #top-tag-filter { 51 | left: 200px; 52 | height: 44px; 53 | bottom: auto; 54 | background: #ddd; 55 | border-bottom: 1px solid #999; 56 | } 57 | 58 | #help { 59 | padding: 8px; 60 | } 61 | 62 | #main-pane { 63 | top: 45px; 64 | bottom: 0; 65 | left: 220px; 66 | overflow: auto; 67 | } 68 | 69 | #side-pane { 70 | width: 200px; 71 | right: auto; 72 | overflow: auto; 73 | background: #eee; 74 | border-right: 1px solid #999; 75 | background: #ddd; 76 | } 77 | 78 | .tag { 79 | cursor: pointer; 80 | float: left; 81 | margin: 5px; 82 | padding: 2px 7px; 83 | font-size: 80%; 84 | font-weight: bold; 85 | background: #999; 86 | color: #fff; 87 | border-radius: 4px; 88 | -webkit-border-radius: 4px; 89 | -moz-border-radius: 4px; 90 | -o-border-radius: 4px; 91 | 92 | opacity: 1; 93 | transition: opacity 0.3s linear; 94 | -moz-transition: opacity 0.3s linear; 95 | -webkit-transition: opacity 0.3s linear; 96 | -o-transition: opacity 0.3s linear; 97 | 98 | position: relative; 99 | } 100 | 101 | #tag-filter .label { 102 | float: left; 103 | margin-top: 9px; 104 | margin-left: 12px; 105 | margin-right: 8px; 106 | } 107 | 108 | #tag-filter .tag { 109 | margin-top: 10px; 110 | border: 1px solid #777; 111 | } 112 | 113 | #tag-filter .selected { 114 | background: #69d; 115 | } 116 | 117 | #tag-filter .count { 118 | font-weight: normal; 119 | padding-left: 2px; 120 | } 121 | 122 | #lists .list { 123 | padding: 3px 6px; 124 | } 125 | 126 | #lists .selected { 127 | padding: 2px 6px; 128 | background: #9be; 129 | font-weight: bold; 130 | } 131 | 132 | #lists .list-name { 133 | cursor: pointer; 134 | color: black; 135 | text-decoration: none; 136 | } 137 | 138 | #createList { 139 | padding: 3px 6px; 140 | margin-top: 5px; 141 | } 142 | 143 | #createList input { 144 | width: 180px; 145 | } 146 | 147 | #new-todo-box { 148 | margin-top: 10px; 149 | margin-bottom: 10px; 150 | margin-left: 60px; 151 | margin-right: 20px; 152 | font-size: 160%; 153 | position: relative; 154 | height: 40px; 155 | } 156 | 157 | #new-todo { 158 | position: absolute; 159 | width: 100%; 160 | } 161 | 162 | #items-view { 163 | margin-top: 5px; 164 | margin-left: 5px; 165 | } 166 | 167 | #item-list .todo { 168 | display: block; 169 | height: 50px; 170 | position: relative; 171 | overflow: hidden; 172 | border-top: 1px solid #ccc; 173 | } 174 | 175 | #item-list .todo .destroy { 176 | cursor: pointer; 177 | position: absolute; 178 | left: 5px; 179 | top: 15px; 180 | height: 20px; 181 | width: 20px; 182 | } 183 | 184 | #item-list .todo .display, #item-list .todo .edit { 185 | margin-left: 30px; 186 | height: 100%; 187 | width: auto; 188 | float: left; 189 | padding-top: 18px; 190 | line-height: 1; 191 | } 192 | 193 | #todo-input { 194 | width: 300px; 195 | position: relative; 196 | top: -3px; 197 | } 198 | 199 | #item-list .done .todo-text { 200 | text-decoration: line-through; 201 | color: #999; 202 | } 203 | 204 | #item-list .todo:hover .destroy { 205 | background: url('/destroy.png') no-repeat 0 0; 206 | } 207 | 208 | #item-list .todo .destroy:hover { 209 | background-position: 0 -20px; 210 | } 211 | 212 | #item-list .todo .item-tags { 213 | overflow: auto; 214 | float: right; 215 | margin-right: 8px; 216 | } 217 | 218 | #item-list .todo .item-tags .tag { 219 | margin-top: 15px; 220 | } 221 | 222 | #item-list .todo .item-tags .removable_tag { 223 | padding-right: 22px; 224 | } 225 | 226 | #item-list .todo .item-tags .tag .remove { 227 | position: absolute; 228 | top: 0; 229 | right: 4px; 230 | bottom: 0; 231 | width: 16px; 232 | background: url("/close_16.png") no-repeat 0 center; 233 | } 234 | 235 | #item-list .todo .item-tags .tag .remove:hover { 236 | background-position: -16px center; 237 | } 238 | 239 | #item-list .todo .item-tags div.addtag { 240 | background: none; 241 | color: #333; 242 | border: 1px dashed #999; 243 | } 244 | 245 | #item-list .todo .check { 246 | float: left; 247 | width: 25px; 248 | } 249 | 250 | #item-list .todo .todo-text { 251 | float: left; 252 | margin-left: 10px; 253 | font-size: 100%; 254 | } 255 | 256 | #item-list .todo .edit input { 257 | margin-left: 35px; 258 | } 259 | 260 | #edittag-input { 261 | width: 80px; 262 | } 263 | 264 | -------------------------------------------------------------------------------- /tests/apps/todos/client/todos.html: -------------------------------------------------------------------------------- 1 | 2 | Todos 3 | 4 | 5 | 6 |
7 | {{> tag_filter}} 8 |
9 | 10 |
11 | {{> todos}} 12 |
13 | 14 |
15 | {{> lists}} 16 |
17 | 18 | 19 | 46 | 47 | 65 | 66 | 98 | 99 | 109 | -------------------------------------------------------------------------------- /tests/apps/todos/client/todos.js: -------------------------------------------------------------------------------- 1 | // Client-side JavaScript, bundled and sent to client. 2 | FAIL 3 | // Define Minimongo collections to match server/publish.js. 4 | Lists = new Meteor.Collection("lists"); 5 | Todos = new Meteor.Collection("todos"); 6 | 7 | // ID of currently selected list 8 | Session.setDefault('list_id', null); 9 | 10 | // Name of currently selected tag for filtering 11 | Session.setDefault('tag_filter', null); 12 | 13 | // When adding tag to a todo, ID of the todo 14 | Session.setDefault('editing_addtag', null); 15 | 16 | // When editing a list name, ID of the list 17 | Session.setDefault('editing_listname', null); 18 | 19 | // When editing todo text, ID of the todo 20 | Session.setDefault('editing_itemname', null); 21 | 22 | // Subscribe to 'lists' collection on startup. 23 | // Select a list once data has arrived. 24 | var listsHandle = Meteor.subscribe('lists', function () { 25 | if (!Session.get('list_id')) { 26 | var list = Lists.findOne({}, {sort: {name: 1}}); 27 | if (list) 28 | Router.setList(list._id); 29 | } 30 | }); 31 | 32 | var todosHandle = null; 33 | // Always be subscribed to the todos for the selected list. 34 | Deps.autorun(function () { 35 | var list_id = Session.get('list_id'); 36 | if (list_id) 37 | todosHandle = Meteor.subscribe('todos', list_id); 38 | else 39 | todosHandle = null; 40 | }); 41 | 42 | 43 | ////////// Helpers for in-place editing ////////// 44 | 45 | // Returns an event map that handles the "escape" and "return" keys and 46 | // "blur" events on a text input (given by selector) and interprets them 47 | // as "ok" or "cancel". 48 | var okCancelEvents = function (selector, callbacks) { 49 | var ok = callbacks.ok || function () {}; 50 | var cancel = callbacks.cancel || function () {}; 51 | 52 | var events = {}; 53 | events['keyup '+selector+', keydown '+selector+', focusout '+selector] = 54 | function (evt) { 55 | if (evt.type === "keydown" && evt.which === 27) { 56 | // escape = cancel 57 | cancel.call(this, evt); 58 | 59 | } else if (evt.type === "keyup" && evt.which === 13 || 60 | evt.type === "focusout") { 61 | // blur/return/enter = ok/submit if non-empty 62 | var value = String(evt.target.value || ""); 63 | if (value) 64 | ok.call(this, value, evt); 65 | else 66 | cancel.call(this, evt); 67 | } 68 | }; 69 | 70 | return events; 71 | }; 72 | 73 | var activateInput = function (input) { 74 | input.focus(); 75 | input.select(); 76 | }; 77 | 78 | ////////// Lists ////////// 79 | 80 | Template.lists.loading = function () { 81 | return !listsHandle.ready(); 82 | }; 83 | 84 | Template.lists.lists = function () { 85 | return Lists.find({}, {sort: {name: 1}}); 86 | }; 87 | 88 | Template.lists.events({ 89 | 'mousedown .list': function (evt) { // select list 90 | Router.setList(this._id); 91 | }, 92 | 'click .list': function (evt) { 93 | // prevent clicks on from refreshing the page. 94 | evt.preventDefault(); 95 | }, 96 | 'dblclick .list': function (evt, tmpl) { // start editing list name 97 | Session.set('editing_listname', this._id); 98 | Deps.flush(); // force DOM redraw, so we can focus the edit field 99 | activateInput(tmpl.find("#list-name-input")); 100 | } 101 | }); 102 | 103 | // Attach events to keydown, keyup, and blur on "New list" input box. 104 | Template.lists.events(okCancelEvents( 105 | '#new-list', 106 | { 107 | ok: function (text, evt) { 108 | var id = Lists.insert({name: text}); 109 | Router.setList(id); 110 | evt.target.value = ""; 111 | } 112 | })); 113 | 114 | Template.lists.events(okCancelEvents( 115 | '#list-name-input', 116 | { 117 | ok: function (value) { 118 | Lists.update(this._id, {$set: {name: value}}); 119 | Session.set('editing_listname', null); 120 | }, 121 | cancel: function () { 122 | Session.set('editing_listname', null); 123 | } 124 | })); 125 | 126 | Template.lists.selected = function () { 127 | return Session.equals('list_id', this._id) ? 'selected' : ''; 128 | }; 129 | 130 | Template.lists.name_class = function () { 131 | return this.name ? '' : 'empty'; 132 | }; 133 | 134 | Template.lists.editing = function () { 135 | return Session.equals('editing_listname', this._id); 136 | }; 137 | 138 | ////////// Todos ////////// 139 | 140 | Template.todos.loading = function () { 141 | return todosHandle && !todosHandle.ready(); 142 | }; 143 | 144 | Template.todos.any_list_selected = function () { 145 | return !Session.equals('list_id', null); 146 | }; 147 | 148 | Template.todos.events(okCancelEvents( 149 | '#new-todo', 150 | { 151 | ok: function (text, evt) { 152 | var tag = Session.get('tag_filter'); 153 | Todos.insert({ 154 | text: text, 155 | list_id: Session.get('list_id'), 156 | done: false, 157 | timestamp: (new Date()).getTime(), 158 | tags: tag ? [tag] : [] 159 | }); 160 | evt.target.value = ''; 161 | } 162 | })); 163 | 164 | Template.todos.todos = function () { 165 | // Determine which todos to display in main pane, 166 | // selected based on list_id and tag_filter. 167 | 168 | var list_id = Session.get('list_id'); 169 | if (!list_id) 170 | return {}; 171 | 172 | var sel = {list_id: list_id}; 173 | var tag_filter = Session.get('tag_filter'); 174 | if (tag_filter) 175 | sel.tags = tag_filter; 176 | 177 | return Todos.find(sel, {sort: {timestamp: 1}}); 178 | }; 179 | 180 | Template.todo_item.tag_objs = function () { 181 | var todo_id = this._id; 182 | return _.map(this.tags || [], function (tag) { 183 | return {todo_id: todo_id, tag: tag}; 184 | }); 185 | }; 186 | 187 | Template.todo_item.done_class = function () { 188 | return this.done ? 'done' : ''; 189 | }; 190 | 191 | Template.todo_item.done_checkbox = function () { 192 | return this.done ? 'checked="checked"' : ''; 193 | }; 194 | 195 | Template.todo_item.editing = function () { 196 | return Session.equals('editing_itemname', this._id); 197 | }; 198 | 199 | Template.todo_item.adding_tag = function () { 200 | return Session.equals('editing_addtag', this._id); 201 | }; 202 | 203 | Template.todo_item.events({ 204 | 'click .check': function () { 205 | Todos.update(this._id, {$set: {done: !this.done}}); 206 | }, 207 | 208 | 'click .destroy': function () { 209 | Todos.remove(this._id); 210 | }, 211 | 212 | 'click .addtag': function (evt, tmpl) { 213 | Session.set('editing_addtag', this._id); 214 | Deps.flush(); // update DOM before focus 215 | activateInput(tmpl.find("#edittag-input")); 216 | }, 217 | 218 | 'dblclick .display .todo-text': function (evt, tmpl) { 219 | Session.set('editing_itemname', this._id); 220 | Deps.flush(); // update DOM before focus 221 | activateInput(tmpl.find("#todo-input")); 222 | }, 223 | 224 | 'click .remove': function (evt) { 225 | var tag = this.tag; 226 | var id = this.todo_id; 227 | 228 | evt.target.parentNode.style.opacity = 0; 229 | // wait for CSS animation to finish 230 | Meteor.setTimeout(function () { 231 | Todos.update({_id: id}, {$pull: {tags: tag}}); 232 | }, 300); 233 | } 234 | }); 235 | 236 | Template.todo_item.events(okCancelEvents( 237 | '#todo-input', 238 | { 239 | ok: function (value) { 240 | Todos.update(this._id, {$set: {text: value}}); 241 | Session.set('editing_itemname', null); 242 | }, 243 | cancel: function () { 244 | Session.set('editing_itemname', null); 245 | } 246 | })); 247 | 248 | Template.todo_item.events(okCancelEvents( 249 | '#edittag-input', 250 | { 251 | ok: function (value) { 252 | Todos.update(this._id, {$addToSet: {tags: value}}); 253 | Session.set('editing_addtag', null); 254 | }, 255 | cancel: function () { 256 | Session.set('editing_addtag', null); 257 | } 258 | })); 259 | 260 | ////////// Tag Filter ////////// 261 | 262 | // Pick out the unique tags from all todos in current list. 263 | Template.tag_filter.tags = function () { 264 | var tag_infos = []; 265 | var total_count = 0; 266 | 267 | Todos.find({list_id: Session.get('list_id')}).forEach(function (todo) { 268 | _.each(todo.tags, function (tag) { 269 | var tag_info = _.find(tag_infos, function (x) { return x.tag === tag; }); 270 | if (! tag_info) 271 | tag_infos.push({tag: tag, count: 1}); 272 | else 273 | tag_info.count++; 274 | }); 275 | total_count++; 276 | }); 277 | 278 | tag_infos = _.sortBy(tag_infos, function (x) { return x.tag; }); 279 | tag_infos.unshift({tag: null, count: total_count}); 280 | 281 | return tag_infos; 282 | }; 283 | 284 | Template.tag_filter.tag_text = function () { 285 | return this.tag || "All items"; 286 | }; 287 | 288 | Template.tag_filter.selected = function () { 289 | return Session.equals('tag_filter', this.tag) ? 'selected' : ''; 290 | }; 291 | 292 | Template.tag_filter.events({ 293 | 'mousedown .tag': function () { 294 | if (Session.equals('tag_filter', this.tag)) 295 | Session.set('tag_filter', null); 296 | else 297 | Session.set('tag_filter', this.tag); 298 | } 299 | }); 300 | 301 | ////////// Tracking selected list in URL ////////// 302 | 303 | var TodosRouter = Backbone.Router.extend({ 304 | routes: { 305 | ":list_id": "main" 306 | }, 307 | main: function (list_id) { 308 | var oldList = Session.get("list_id"); 309 | if (oldList !== list_id) { 310 | Session.set("list_id", list_id); 311 | Session.set("tag_filter", null); 312 | } 313 | }, 314 | setList: function (list_id) { 315 | this.navigate(list_id, true); 316 | } 317 | }); 318 | 319 | Router = new TodosRouter; 320 | 321 | Meteor.startup(function () { 322 | Backbone.history.start({pushState: true}); 323 | }); 324 | -------------------------------------------------------------------------------- /tests/apps/todos/packages/appclientsideerror/.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | -------------------------------------------------------------------------------- /tests/apps/todos/packages/appclientsideerror/appfails-test.js: -------------------------------------------------------------------------------- 1 | var TestHelper = function() {}; 2 | TestHelper.prototype.blah = function() { 3 | describe('test', function() { 4 | it('test', function() { 5 | var test = false; 6 | const thisshouldntwork = " ".split(); 7 | }); 8 | }); 9 | }; 10 | 11 | describe('testing', function() { 12 | var t = new TestHelper(); 13 | t.blah(); 14 | }); 15 | -------------------------------------------------------------------------------- /tests/apps/todos/packages/appclientsideerror/appfails.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/practicalmeteor/spacejam/a3dc79b6bfce70e696f490edf626e1b24948d518/tests/apps/todos/packages/appclientsideerror/appfails.js -------------------------------------------------------------------------------- /tests/apps/todos/packages/appclientsideerror/package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | summary: "appfails" 3 | }); 4 | 5 | Package.onUse(function (api) { 6 | api.addFiles(['appfails.js']); 7 | }); 8 | 9 | Package.onTest(function(api) { 10 | api.addFiles('appfails-test.js', 'client'); 11 | }); 12 | -------------------------------------------------------------------------------- /tests/apps/todos/packages/appfails/.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | -------------------------------------------------------------------------------- /tests/apps/todos/packages/appfails/appfails-test.coffee: -------------------------------------------------------------------------------- 1 | FAIL 2 | Tinytest.add "appfails",(test)-> 3 | test.equal true, true 4 | -------------------------------------------------------------------------------- /tests/apps/todos/packages/appfails/appfails.coffee: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/practicalmeteor/spacejam/a3dc79b6bfce70e696f490edf626e1b24948d518/tests/apps/todos/packages/appfails/appfails.coffee -------------------------------------------------------------------------------- /tests/apps/todos/packages/appfails/package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | summary: "appfails" 3 | }); 4 | 5 | Package.onUse(function (api) { 6 | api.use(['coffeescript']); 7 | 8 | api.addFiles(['appfails.coffee']); 9 | }); 10 | 11 | Package.onTest(function(api) { 12 | api.use(['coffeescript', 'tinytest', 'appfails']); 13 | 14 | api.addFiles('appfails-test.coffee'); 15 | }); 16 | -------------------------------------------------------------------------------- /tests/apps/todos/packages/appfails/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | [ 4 | "coffeescript", 5 | "1.0.4" 6 | ], 7 | [ 8 | "meteor", 9 | "1.1.3" 10 | ], 11 | [ 12 | "underscore", 13 | "1.0.1" 14 | ] 15 | ], 16 | "pluginDependencies": [], 17 | "toolVersion": "meteor-tool@1.0.36", 18 | "format": "1.0" 19 | } -------------------------------------------------------------------------------- /tests/apps/todos/public/close_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/practicalmeteor/spacejam/a3dc79b6bfce70e696f490edf626e1b24948d518/tests/apps/todos/public/close_16.png -------------------------------------------------------------------------------- /tests/apps/todos/public/destroy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/practicalmeteor/spacejam/a3dc79b6bfce70e696f490edf626e1b24948d518/tests/apps/todos/public/destroy.png -------------------------------------------------------------------------------- /tests/apps/todos/server/bootstrap.js: -------------------------------------------------------------------------------- 1 | // if the database is empty on server start, create some sample data. 2 | Meteor.startup(function () { 3 | if (Lists.find().count() === 0) { 4 | var data = [ 5 | {name: "Meteor Principles", 6 | contents: [ 7 | ["Data on the Wire", "Simplicity", "Better UX", "Fun"], 8 | ["One Language", "Simplicity", "Fun"], 9 | ["Database Everywhere", "Simplicity"], 10 | ["Latency Compensation", "Better UX"], 11 | ["Full Stack Reactivity", "Better UX", "Fun"], 12 | ["Embrace the Ecosystem", "Fun"], 13 | ["Simplicity Equals Productivity", "Simplicity", "Fun"] 14 | ] 15 | }, 16 | {name: "Languages", 17 | contents: [ 18 | ["Lisp", "GC"], 19 | ["C", "Linked"], 20 | ["C++", "Objects", "Linked"], 21 | ["Python", "GC", "Objects"], 22 | ["Ruby", "GC", "Objects"], 23 | ["JavaScript", "GC", "Objects"], 24 | ["Scala", "GC", "Objects"], 25 | ["Erlang", "GC"], 26 | ["6502 Assembly", "Linked"] 27 | ] 28 | }, 29 | {name: "Favorite Scientists", 30 | contents: [ 31 | ["Ada Lovelace", "Computer Science"], 32 | ["Grace Hopper", "Computer Science"], 33 | ["Marie Curie", "Physics", "Chemistry"], 34 | ["Carl Friedrich Gauss", "Math", "Physics"], 35 | ["Nikola Tesla", "Physics"], 36 | ["Claude Shannon", "Math", "Computer Science"] 37 | ] 38 | } 39 | ]; 40 | 41 | var timestamp = (new Date()).getTime(); 42 | for (var i = 0; i < data.length; i++) { 43 | var list_id = Lists.insert({name: data[i].name}); 44 | for (var j = 0; j < data[i].contents.length; j++) { 45 | var info = data[i].contents[j]; 46 | Todos.insert({list_id: list_id, 47 | text: info[0], 48 | timestamp: timestamp, 49 | tags: info.slice(1)}); 50 | timestamp += 1; // ensure unique timestamp. 51 | } 52 | } 53 | } 54 | }); 55 | -------------------------------------------------------------------------------- /tests/apps/todos/server/publish.js: -------------------------------------------------------------------------------- 1 | // Lists -- {name: String} 2 | Lists = new Meteor.Collection("lists"); 3 | 4 | // Publish complete set of lists to all clients. 5 | Meteor.publish('lists', function () { 6 | return Lists.find(); 7 | }); 8 | 9 | 10 | // Todos -- {text: String, 11 | // done: Boolean, 12 | // tags: [String, ...], 13 | // list_id: String, 14 | // timestamp: Number} 15 | Todos = new Meteor.Collection("todos"); 16 | 17 | // Publish all items for requested list_id. 18 | Meteor.publish('todos', function (list_id) { 19 | check(list_id, String); 20 | return Todos.find({list_id: list_id}); 21 | }); 22 | 23 | -------------------------------------------------------------------------------- /tests/bin/meteor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env coffee 2 | 3 | output = 4 | argv: process.argv 5 | env: process.env 6 | 7 | process.stdout.write(JSON.stringify(output, null, 2)) 8 | 9 | process.exit(0) 10 | -------------------------------------------------------------------------------- /tests/lib/CLITest.coffee: -------------------------------------------------------------------------------- 1 | DEFAULT_PATH = process.env.PATH 2 | 3 | fs = require('fs') 4 | path = require 'path' 5 | phantomjs = require("phantomjs-prebuilt") 6 | chai = require("chai") 7 | expect = chai.expect 8 | sinon = require("sinon") 9 | sinonChai = require("sinon-chai") 10 | chai.use(sinonChai) 11 | require '../../lib/log' 12 | CLI = require '../../lib/CLI' 13 | Spacejam = require '../../lib/Spacejam' 14 | ChildProcess = require '../../lib/ChildProcess' 15 | 16 | 17 | 18 | describe "CLI", -> 19 | @timeout 30000 20 | 21 | processArgv = null 22 | 23 | cli = null 24 | spacejam = null 25 | exitStub = null 26 | testPackagesStub = null 27 | spawnSpy = null 28 | phantomjsScript = null 29 | 30 | before -> 31 | processArgv = process.argv 32 | 33 | after -> 34 | process.argv = processArgv 35 | 36 | beforeEach -> 37 | process.chdir(__dirname + "/../apps/leaderboard") 38 | delete process.env.PORT 39 | delete process.env.ROOT_URL 40 | delete process.env.MONGO_URL 41 | delete process.env.PACKAGE_DIRS 42 | 43 | process.env.PATH = DEFAULT_PATH 44 | 45 | process.argv = ['coffee', path.normalize __dirname + "/../bin/spacejam"] 46 | cli = new CLI() 47 | spacejam = cli.spacejam 48 | exitStub = sinon.stub(process, 'exit') 49 | testPackagesStub = sinon.stub(spacejam, 'runTests') 50 | phantomjsScript = 'phantomjs-test-in-console.js' 51 | 52 | afterEach -> 53 | exitStub?.restore?() 54 | exitStub = null 55 | testPackagesStub?.restore?() 56 | testPackagesStub = null 57 | spawnSpy?.restore?() 58 | spawnSpy = null 59 | spacejam = null 60 | 61 | it "should call Spacejam.runTests() test command and full-app mode with a empty array of packages", -> 62 | process.argv.push "test", "--full-app" 63 | cli.exec() 64 | expect(testPackagesStub).to.have.been.calledWith("test", {command: "test","full-app":true, packages: []}) 65 | 66 | it "should call Spacejam.runTests() with an empty options.packages array, if no packages where provided on the command line", -> 67 | process.argv.push "test-packages" 68 | cli.exec() 69 | expect(testPackagesStub).to.have.been.calledWith("test-packages", {command: "test-packages", packages: []}) 70 | 71 | it "should call Spacejam.runTests() with options.packages set to the packages provided on the command line", -> 72 | process.argv.push 'test-packages', '--settings', 'settings.json', 'package1', 'package2' 73 | cli.exec() 74 | expect(testPackagesStub).to.have.been.calledWith("test-packages", {command: "test-packages", settings: 'settings.json', packages: ['package1', 'package2']}) 75 | 76 | it "should spawn phantomjs with the value of --phantomjs-options", (done)-> 77 | log.setLevel 'debug' 78 | testPackagesStub.restore() 79 | spawnSpy = sinon.spy(ChildProcess, '_spawn') 80 | process.chdir(__dirname + "/../apps/leaderboard/packages/success") 81 | # We set mongo-url to mongodb:// so test will be faster 82 | process.argv.push 'test-packages', '--port', '11096', '--mongo-url', 'mongodb://', '--phantomjs-options=--ignore-ssl-errors=true --load-images=false', './' 83 | cli.exec() 84 | spacejam.on 'done', (code)=> 85 | try 86 | if code is 0 then done() else done("spacejam.done=#{code}") 87 | expect(spawnSpy).to.have.been.calledTwice 88 | expect(spawnSpy.secondCall.args[1]).to.deep.equal(['--ignore-ssl-errors=true', '--load-images=false', phantomjsScript]) 89 | catch err 90 | done(err) 91 | 92 | it "should modify PATH to include the path to the bundled phantomjs", (done)-> 93 | testPackagesStub.restore() 94 | process.chdir(__dirname + "/../apps/leaderboard/packages/success") 95 | # We set mongo-url to mongodb:// so test will be faster 96 | process.argv.push 'test-packages', '--port', '12096', '--mongo-url', 'mongodb://', '--phantomjs-options=--ignore-ssl-errors=true --load-images=false', './' 97 | cli.exec() 98 | spacejam.on 'done', (code)=> 99 | try 100 | if code is 0 then done() else done("spacejam.done=#{code}") 101 | 102 | firstPathEntry = process.env.PATH.split(":")[0] 103 | expect(firstPathEntry).to.equal(path.dirname(phantomjs.path)) 104 | catch err 105 | done(err) 106 | 107 | it "should not modify PATH if --use-system-phantomjs is given", (done)-> 108 | testPackagesStub.restore() 109 | process.chdir(__dirname + "/../apps/leaderboard/packages/success") 110 | # We set mongo-url to mongodb:// so test will be faster 111 | process.argv.push 'test-packages', '--port', '13096', '--mongo-url', 'mongodb://', '--use-system-phantomjs', '--phantomjs-options=--ignore-ssl-errors=true --load-images=false', './' 112 | console.log(process.argv.join(" ")) 113 | cli.exec() 114 | spacejam.on 'done', (code)=> 115 | try 116 | if code is 0 then done() else done("spacejam.done=#{code}") 117 | 118 | expect(process.env.PATH).to.equal(DEFAULT_PATH) 119 | catch err 120 | done(err) 121 | -------------------------------------------------------------------------------- /tests/lib/FunctionalTests.coffee: -------------------------------------------------------------------------------- 1 | path = require 'path' 2 | fs = require 'fs' 3 | DOMParser = require('xmldom').DOMParser 4 | xpath = require('xpath') 5 | 6 | expect = require("chai").expect 7 | 8 | CLI = require '../../lib/CLI' 9 | ChildProcess = require '../../lib/ChildProcess' 10 | Spacejam = require '../../lib/Spacejam' 11 | spacejamBin = require.resolve("../../bin/spacejam") 12 | 13 | log.info spacejamBin 14 | 15 | 16 | describe "spacejam", -> 17 | @timeout 120000 18 | 19 | spacejamChild = null 20 | 21 | spacejamChild2 = null 22 | 23 | testApp1 = "leaderboard" 24 | 25 | testApp2 = "todos" 26 | 27 | standAlonePackage = "../packages/standalone-package" 28 | 29 | before -> 30 | log.debug "spacejam.before" 31 | 32 | beforeEach -> 33 | log.debug "spacejam.beforeEach" 34 | process.chdir(__dirname + "/../apps/leaderboard") 35 | delete process.env.PORT 36 | delete process.env.ROOT_URL 37 | delete process.env.MONGO_URL 38 | delete process.env.PACKAGE_DIRS 39 | 40 | spacejamChild = new ChildProcess() 41 | 42 | afterEach -> 43 | log.debug "spacejam.afterEach" 44 | try 45 | spacejamChild?.kill('SIGPIPE') 46 | finally 47 | spacejamChild = null 48 | 49 | try 50 | spacejamChild2?.kill('SIGPIPE') 51 | finally 52 | spacejamChild2 = null 53 | 54 | describe "test-packages", -> 55 | 56 | it "should exit with 0 if tests pass for a meteor app package. Also verifies METEOR_TEST_PACKAGES is '1'", (done)-> 57 | spacejamChild = new ChildProcess() 58 | args = ["test-packages", "success"] 59 | spacejamChild.spawn(spacejamBin,args) 60 | spacejamChild.child.on "exit", (code) => 61 | expect(code,"spacejam exited with errors").to.equal Spacejam.DONE.TEST_SUCCESS 62 | done() 63 | 64 | 65 | it "should exit with 0 if tests pass for a standalone package", (done)-> 66 | process.chdir(__dirname + "/../packages/standalone-package") 67 | process.env.PACKAGE_DIRS = path.normalize __dirname + '/../packages' 68 | spacejamChild = new ChildProcess() 69 | args = ["test-packages", "./"] 70 | spacejamChild.spawn(spacejamBin,args) 71 | spacejamChild.child.on "exit", (code) => 72 | expect(code,"spacejam exited with errors").to.equal Spacejam.DONE.TEST_SUCCESS 73 | done() 74 | 75 | it "should execute multiple independent package tests provided by path while not in a meteor app or package folder", (done)-> 76 | process.chdir(path.resolve(__dirname, "..")) 77 | spacejamChild = new ChildProcess() 78 | args = ["test-packages", "packages/standalone-package-dep", 'apps/leaderboard/packages/success'] 79 | spacejamChild.spawn(spacejamBin,args) 80 | spacejamChild.child.on "exit", (code) => 81 | try 82 | expect(code,"spacejam exited with errors").to.equal Spacejam.DONE.TEST_SUCCESS 83 | done() 84 | catch err 85 | done(err) 86 | 87 | it "should exit with 3, if meteor couldn't find package", (done)-> 88 | process.chdir(__dirname) 89 | spacejamChild = new ChildProcess() 90 | args = ["test-packages", "success"] 91 | spacejamChild.spawn(spacejamBin,args) 92 | spacejamChild.child.on "exit", (code) => 93 | expect(code,"spacejam exited with the wrong code").to.equal Spacejam.DONE.METEOR_ERROR 94 | done() 95 | 96 | 97 | it "should exit with 3, if package could not be found", (done)-> 98 | spacejamChild = new ChildProcess() 99 | args = ["test-packages", standAlonePackage] 100 | spacejamChild.spawn(spacejamBin,args) 101 | spacejamChild.child.on "exit", (code) => 102 | expect(code,"spacejam exited with errors").to.equal Spacejam.DONE.METEOR_ERROR 103 | done() 104 | 105 | 106 | it "should exit with 2, if tests failed", (done)-> 107 | spacejamChild = new ChildProcess() 108 | testPort = "6096" 109 | args = ["test-packages", "--port", testPort, "failure"] 110 | spacejamChild.spawn(spacejamBin,args) 111 | spacejamChild.child.on "exit", (code) => 112 | expect(code,"spacejam exited with the wrong code").to.equal Spacejam.DONE.TEST_FAILED 113 | done() 114 | 115 | 116 | it "should exit with 4, if --timeout has passed", (done)-> 117 | spacejamChild = new ChildProcess() 118 | testPort = "7096" 119 | args = ["test-packages", "--timeout", "30000", "--port", testPort, 'timeout'] 120 | spacejamChild.spawn(spacejamBin,args) 121 | spacejamChild.child.on "exit", (code) => 122 | expect(code,"spacejam exited with the wrong code").to.equal Spacejam.DONE.TEST_TIMEOUT 123 | done() 124 | 125 | 126 | it "should exit with 2, if the meteor app crashes", (done)-> 127 | @timeout 90000 128 | process.chdir(__dirname + "/../apps/todos") 129 | spacejamChild = new ChildProcess() 130 | testPort = "8096" 131 | args = ["test-packages", "--port", testPort, 'appfails'] 132 | spacejamChild.spawn(spacejamBin,args) 133 | spacejamChild.child.on "exit", (code) => 134 | expect(code).to.equal Spacejam.DONE.METEOR_ERROR 135 | done() 136 | 137 | it "should exit with 6, if the tests contain an error", (done)-> 138 | @timeout 90000 139 | process.chdir(__dirname + "/../apps/todos") 140 | spacejamChild = new ChildProcess() 141 | testPort = "8096" 142 | args = ["test-packages", "--port", testPort, 'appclientsideerror'] 143 | spacejamChild.spawn(spacejamBin,args) 144 | spacejamChild.child.on "exit", (code) => 145 | expect(code).to.equal Spacejam.DONE.CLIENT_ERROR 146 | done() 147 | 148 | 149 | it "should save xunit output to file, if --xunit-out is specified", (done)-> 150 | spacejamChild = new ChildProcess() 151 | # TODO: Have a global singleton to provide the port 152 | testPort = "20096" 153 | args = ["test-packages", "--port", testPort, '--xunit-out', '/tmp/xunit.xml', "success"] 154 | spacejamChild.spawn(spacejamBin,args) 155 | spacejamChild.child.on "close", (code, signal) => 156 | try 157 | expect(code,"spacejam exited with errors").to.equal Spacejam.DONE.TEST_SUCCESS 158 | xml = fs.readFileSync('/tmp/xunit.xml', encoding: 'utf8') 159 | log.debug xml 160 | expect(xml).to.be.ok 161 | xmlDom = new DOMParser().parseFromString(xml) 162 | expect(xmlDom.documentElement.tagName).to.equal 'testsuite' 163 | testCaseNodes = xpath.select("//testcase", xmlDom) 164 | expect(testCaseNodes).to.have.length 3 165 | done() 166 | catch ex 167 | done(ex) 168 | 169 | 170 | it "should exit with 0, in case of a complete test, with a settings file, multiple packages, including wildcards in package names", (done)-> 171 | spacejamChild = new ChildProcess() 172 | testPort = "10096" 173 | args = ["test-packages", "--settings", "settings.json", "--port", testPort, 'packages/settings', 'success*'] 174 | spacejamChild.spawn(spacejamBin,args) 175 | spacejamChild.child.on "exit", (code) => 176 | expect(code,"spacejam exited with errors").to.equal Spacejam.DONE.TEST_SUCCESS 177 | done() 178 | 179 | describe "package-version", -> 180 | 181 | it "should print the package version", (done)-> 182 | process.chdir(__dirname + "/../packages/standalone-package") 183 | spacejamChild = new ChildProcess() 184 | spacejamChild.exec "#{spacejamBin} package-version", null, (err, stdout, stderr)=> 185 | try 186 | expect(err).to.be.null 187 | expect(stdout.toString()).to.contain '0.9.5' 188 | done() 189 | catch err 190 | done(err) 191 | 192 | describe "test", -> 193 | 194 | 195 | describe "--full-app mode", -> 196 | 197 | 198 | it "should exit with 0 with successful tests", (done)-> 199 | process.chdir(__dirname + "/../apps/passing-app-tests") 200 | args = ["test", "--driver-package", "practicalmeteor:mocha-console-runner", "--full-app"] 201 | spacejamChild.spawn(spacejamBin, args) 202 | spacejamChild.child.on "exit", (code) => 203 | expect(code,"spacejam exited with the wrong code").to.equal Spacejam.DONE.TEST_SUCCESS 204 | done() 205 | 206 | it "should exit with 1 with successful tests", (done)-> 207 | process.chdir(__dirname + "/../apps/failing-app-tests") 208 | args = ["test", "--driver-package", "practicalmeteor:mocha-console-runner", "--full-app"] 209 | args = ["test", "--driver-package", "practicalmeteor:mocha-console-runner", "--full-app"] 210 | spacejamChild.spawn(spacejamBin, args) 211 | spacejamChild.child.on "exit", (code) => 212 | expect(code,"spacejam exited with the wrong code").to.equal Spacejam.DONE.TEST_FAILED 213 | done() 214 | 215 | 216 | describe "unit tests mode", -> 217 | 218 | it "should exit with 0 with successful tests", (done)-> 219 | process.chdir(__dirname + "/../apps/passing-app-tests") 220 | args = ["test", "--driver-package", "practicalmeteor:mocha-console-runner"] 221 | spacejamChild.spawn(spacejamBin, args) 222 | spacejamChild.child.on "exit", (code) => 223 | expect(code,"spacejam exited with the wrong code").to.equal Spacejam.DONE.TEST_SUCCESS 224 | done() 225 | 226 | it "should exit with 2 with failed tests", (done)-> 227 | process.chdir(__dirname + "/../apps/failing-app-tests") 228 | args = ["test", "--driver-package", "practicalmeteor:mocha-console-runner"] 229 | spacejamChild.spawn(spacejamBin, args) 230 | spacejamChild.child.on "exit", (code) => 231 | expect(code,"spacejam exited with the wrong code").to.equal Spacejam.DONE.TEST_FAILED 232 | done() 233 | 234 | -------------------------------------------------------------------------------- /tests/lib/MeteorTest.coffee: -------------------------------------------------------------------------------- 1 | _ = require("underscore") 2 | chai = require("chai") 3 | expect = chai.expect 4 | sinon = require("sinon") 5 | sinonChai = require("sinon-chai") 6 | chai.use(sinonChai) 7 | Meteor = require "../../lib/Meteor" 8 | ChildProcess = require "../../lib/ChildProcess" 9 | ps = require('psext') 10 | path = require "path" 11 | 12 | 13 | describe "Meteor", -> 14 | @timeout 30000 15 | 16 | meteor = null 17 | 18 | spawnStub = null 19 | 20 | defaultTestPort = 4096 21 | 22 | env = null 23 | 24 | packageToTest = 'success' 25 | 26 | expectedSpawnOptions = null 27 | 28 | expectedSpawnArgs = null 29 | 30 | childProcessMockObj = { 31 | on:-> 32 | stdout: 33 | on:-> 34 | stderr: 35 | on:-> 36 | } 37 | 38 | 39 | before -> 40 | delete process.env.PORT 41 | delete process.env.ROOT_URL 42 | delete process.env.MONGO_URL 43 | 44 | 45 | beforeEach -> 46 | process.chdir(__dirname + "/../apps/leaderboard") 47 | 48 | env = _.clone process.env 49 | 50 | meteor = new Meteor() 51 | expectedSpawnArgs = ['test-packages', '--driver-package', 'test-in-console'] 52 | spawnStub = sinon.stub(ChildProcess.prototype, "spawn") 53 | ChildProcess.prototype.child = childProcessMockObj 54 | 55 | 56 | afterEach -> 57 | ChildProcess.prototype.child = null 58 | spawnStub?.restore?() 59 | spawnStub = null 60 | 61 | getExpectedSpawnOptions = (port, rootUrl, mongoUrl, cwd = process.cwd())-> 62 | expectedSpawnOptions = {cwd: cwd, detached: false, env: env} 63 | rootUrl ?= "http://localhost:#{port}/" 64 | expectedSpawnOptions.env.METEOR_TEST_PACKAGES = '1' 65 | expectedSpawnOptions.env.ROOT_URL = rootUrl 66 | expectedSpawnOptions.env.MONGO_URL = mongoUrl if mongoUrl? 67 | return expectedSpawnOptions 68 | 69 | 70 | it "getTestArgs() - get common args for test and test-packages command", -> 71 | options = { 72 | "driver-package": "package" 73 | "release": 'release' 74 | "port": '3000' 75 | "settings": 'settings' 76 | "production": true 77 | "packages": ['pkg1', 'pkg2'] 78 | } 79 | 80 | args = meteor.getTestArgs('test', options) 81 | 82 | expect(args).to.be.deep.equal([ 83 | "test", 84 | "--driver-package", "package", 85 | "--release", "release", 86 | "--port", "3000", 87 | "--settings", "settings" 88 | "--production" 89 | ]) 90 | 91 | 92 | describe "getTestArgs()", -> 93 | 94 | beforeEach -> 95 | @options = { 96 | "driver-package": "package" 97 | "release": 'release' 98 | "port": '3000' 99 | "settings": 'settings' 100 | "production": true, 101 | "packages": ['pkg1', 'pkg2'] 102 | } 103 | meteor.options = @options 104 | 105 | 106 | it "create args for test-packages command", -> 107 | 108 | args = meteor.getTestArgs('test-packages', @options) 109 | 110 | expect(args).to.be.deep.equal([ 111 | "test-packages", 112 | "--driver-package", "package", 113 | "--release", "release", 114 | "--port", "3000", 115 | "--settings", "settings" 116 | "--production", 117 | "pkg1", "pkg2" 118 | ]) 119 | 120 | it "create args for test command", -> 121 | 122 | _.extend(@options,{ 123 | "test-app-path": "/tmp/app" 124 | "full-app": true 125 | }) 126 | 127 | 128 | args = meteor.getTestArgs('test', @options) 129 | 130 | expect(args).to.be.deep.equal( [ 131 | "test", 132 | "--driver-package", "package", 133 | "--release", "release", 134 | "--port", "3000", 135 | "--settings", "settings", 136 | "--production", 137 | "--test-app-path", "/tmp/app", 138 | "--full-app" 139 | ]) 140 | 141 | 142 | it "testApp - should spawn meteor with correct arguments", -> 143 | meteor.testApp({"full-app": true}) 144 | expectedSpawnArgs = [ 145 | "test", 146 | "--driver-package", "test-in-console" 147 | "--port", defaultTestPort 148 | "--full-app" 149 | ] 150 | expect(spawnStub.args[0]).to.eql(["meteor", expectedSpawnArgs, getExpectedSpawnOptions(4096)]) 151 | 152 | it "testPackages() - should spawn meteor with no package arguments",-> 153 | meteor.testPackages() 154 | expectedSpawnArgs.push("--port", defaultTestPort) 155 | expect(spawnStub.args[0]).to.eql(["meteor", expectedSpawnArgs, getExpectedSpawnOptions(4096)]) 156 | 157 | 158 | it "testPackages() - should spawn meteor with a package name argument",-> 159 | meteor.testPackages({packages: [packageToTest]}) 160 | expectedSpawnArgs.push("--port", defaultTestPort, packageToTest) 161 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(4096)]) 162 | 163 | 164 | it "testPackages() - should spawn meteor with an absolute path to a --dir relative path",-> 165 | meteor.testPackages({dir: '../todos'}) 166 | expectedSpawnArgs.push("--port", defaultTestPort) 167 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(4096, null, null, path.resolve("../todos"))]) 168 | 169 | it "testPackages() - should spawn meteor with an absolute path to a --dir absolute path",-> 170 | meteor.testPackages({dir: path.resolve("../todos")}) 171 | expectedSpawnArgs.push("--port", defaultTestPort) 172 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(4096, null, null, path.resolve("../todos"))]) 173 | 174 | it "testPackages() - should spawn meteor with a ROOT_URL set to http://localhost:--port/",-> 175 | rootUrl = "http://localhost:5000/" 176 | meteor.testPackages({port: 5000}) 177 | expectedSpawnArgs.push("--port", 5000) 178 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(5000, rootUrl)]) 179 | 180 | 181 | it "testPackages() - should ignore env ROOT_URL",-> 182 | process.env.ROOT_URL = "http://localhost:5000/" 183 | meteor.testPackages() 184 | expectedSpawnArgs.push("--port", defaultTestPort) 185 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(defaultTestPort)]) 186 | 187 | 188 | it "testPackages() - should spawn meteor with a --settings argument",-> 189 | meteor.testPackages({settings: "settings.json", packages: [packageToTest]}) 190 | expectedSpawnArgs.push("--port", defaultTestPort, "--settings", "settings.json", packageToTest) 191 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(4096)]) 192 | 193 | 194 | 195 | it "testPackages() - should spawn meteor with a --production argument",-> 196 | meteor.testPackages({packages: [packageToTest], production: true}) 197 | expectedSpawnArgs.push("--port", defaultTestPort, "--production", packageToTest) 198 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(4096)]) 199 | 200 | 201 | 202 | it "testPackages() - should spawn meteor with a --release argument",-> 203 | releaseToTest = '0.9.0' 204 | meteor.testPackages({release: releaseToTest, packages: [packageToTest]}) 205 | expectedSpawnArgs.push "--release", releaseToTest, "--port", defaultTestPort, packageToTest 206 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(4096)]) 207 | 208 | 209 | it "testPackages() - should spawn meteor with ROOT_URL set to --root-url",-> 210 | rootUrl = "http://test.meteor.com/" 211 | meteor.testPackages({"root-url": rootUrl, packages: [packageToTest]}) 212 | expectedSpawnArgs.push "--port", defaultTestPort, packageToTest 213 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(4096, rootUrl)]) 214 | expect(spawnStub.args[0][2].env.ROOT_URL).to.equal rootUrl 215 | 216 | 217 | it "testPackages() - should ignore env MONGO_URL",-> 218 | process.env.MONGO_URL = "mongodb://localhost/mydb" 219 | meteor.testPackages() 220 | delete process.env.MONGO_URL 221 | expectedSpawnArgs.push "--port", defaultTestPort 222 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(4096)]) 223 | 224 | 225 | it "testPackages() - should spawn meteor with MONGO_URL set to --mongo-url",-> 226 | mongoUrl = "mongodb://localhost/mydb" 227 | meteor.testPackages({"mongo-url": mongoUrl, packages: [packageToTest]}) 228 | expectedSpawnArgs.push "--port", defaultTestPort, packageToTest 229 | expect(spawnStub.args[0]).to.eql(["meteor",expectedSpawnArgs,getExpectedSpawnOptions(4096, null, mongoUrl)]) 230 | expect(spawnStub.args[0][2].env.MONGO_URL).to.equal mongoUrl 231 | 232 | 233 | it "kill() - should kill internal mongodb child processes", (done)-> 234 | @timeout 60000 235 | spawnStub.restore() 236 | spawnStub = null 237 | ChildProcess.prototype.child = null 238 | 239 | meteor.testPackages({packages: [packageToTest]}) 240 | 241 | meteor.on "ready", => 242 | try 243 | pid = meteor.childProcess.child.pid 244 | expect(meteor.mongodb.mongodChilds).to.have.length 1 245 | mongoPid = meteor.mongodb.mongodChilds[0].pid 246 | expect(mongoPid).to.be.ok 247 | meteor.kill() 248 | timerId = setInterval => 249 | try 250 | process.kill(mongoPid, 0) 251 | catch 252 | # mondogb is dead 253 | clearInterval timerId 254 | done() 255 | , 500 256 | catch e1 257 | done(e1) 258 | -------------------------------------------------------------------------------- /tests/lib/NpmExportsTest.coffee: -------------------------------------------------------------------------------- 1 | chai = require("chai") 2 | expect = chai.expect 3 | 4 | describe "main", -> 5 | it "should export all public classes",-> 6 | npmExports = require "../../lib/main" 7 | expect(npmExports).to.be.an 'object' 8 | expect(npmExports.Spacejam).to.be.a 'function' 9 | expect(npmExports.Meteor).to.be.a 'function' 10 | expect(npmExports.Phantomjs).to.be.a 'function' 11 | -------------------------------------------------------------------------------- /tests/lib/ScriptsTests.coffee: -------------------------------------------------------------------------------- 1 | expect = require("chai").expect 2 | ChildProcess = require '../../lib/ChildProcess' 3 | path = require 'path' 4 | _ = require('underscore') 5 | 6 | describe "scripts", -> 7 | 8 | spacejamBinDir = path.resolve(__dirname, "../../bin") 9 | meteorStubDir = path.resolve(__dirname, "../bin") 10 | 11 | child = null 12 | 13 | execOptions = null 14 | 15 | validateExpectedEnv = (env, expectedEnv)-> 16 | for name, value of expectedEnv 17 | expect(env[name], "process.env.#{name}").to.equal value 18 | 19 | # The meteor stub process prints out a json with the command 20 | # line and env it was executed with. We verify it is what 21 | # we expected 22 | execRun = (done, args, expectedArgs, expectedEnv = {})-> 23 | child.exec "#{spacejamBinDir}/mrun #{args}", execOptions, (err, stdout, stderr)=> 24 | try 25 | expect(err).to.be.null 26 | output = JSON.parse(stdout) 27 | actualArgs = output.argv.slice(2).join(' ') 28 | expect(actualArgs).to.deep.equal(expectedArgs) 29 | validateExpectedEnv(output.env, expectedEnv) 30 | done() 31 | catch err 32 | done(err) 33 | 34 | execTestPackages = (done, args, expectedArgs, expectedEnv = {})-> 35 | cmdLine = "#{spacejamBinDir}/mtp #{args}" 36 | child.exec cmdLine, execOptions, (err, stdout, stderr)=> 37 | try 38 | expect(err).to.be.null 39 | output = JSON.parse(stdout) 40 | actualArgs = output.argv.slice(2).join(' ') 41 | expectedEnv.METEOR_TEST_PACKAGES = '1' # This should always exist. 42 | expectedEnv.PORT ?= '3100' # Env vars are strings 43 | expectedEnv.ROOT_URL ?= 'http://localhost:3100/' 44 | expectedArgs = "test-packages --port #{expectedEnv.PORT} #{expectedArgs}" 45 | expect(actualArgs).to.deep.equal(expectedArgs) 46 | validateExpectedEnv(output.env, expectedEnv) 47 | done() 48 | catch err 49 | done(err) 50 | 51 | beforeEach -> 52 | childEnv = _.clone(process.env) 53 | childEnv.PATH = "#{meteorStubDir}:#{childEnv.PATH}" 54 | delete childEnv.PORT 55 | delete childEnv.ROOT_URL 56 | delete childEnv.MONGO_URL 57 | delete childEnv.METEOR_SETTINGS_PATH 58 | delete childEnv.METEOR_APP_HOME 59 | delete childEnv.METEOR_TEST_PACKAGES 60 | delete childEnv.TEST_PORT 61 | delete childEnv.TEST_ROOT_URL 62 | delete childEnv.TEST_MONGO_URL 63 | delete childEnv.TEST_METEOR_SETTINGS_PATH 64 | 65 | execOptions = 66 | env: childEnv 67 | 68 | child = new ChildProcess() 69 | 70 | afterEach -> 71 | try 72 | child?.kill('SIGTERM') 73 | finally 74 | child = null 75 | 76 | describe "mrun", -> 77 | 78 | it "should launch meteor with the provided command line arguments", (done)-> 79 | execRun(done, '--port 4000', '--port 4000') 80 | 81 | it "should launch meteor with --settings $METEOR_SETTINGS_PATH", (done)-> 82 | settingsPath = __dirname + '/settings.json' 83 | execOptions.env.METEOR_SETTINGS_PATH = settingsPath 84 | expectedArgs = "--settings #{settingsPath} --port 4000" 85 | execRun(done, '--port 4000', expectedArgs) 86 | 87 | it "should cd to and run meteor in $METEOR_APP_HOME", (done)-> 88 | settingsPath = __dirname + '/settings.json' 89 | execOptions.env.METEOR_APP_HOME = path.resolve(__dirname, '../apps/leaderboard') 90 | expectedArgs = "--port 4000" 91 | expectedEnv = 92 | PWD: execOptions.env.METEOR_APP_HOME 93 | execRun(done, '--port 4000', expectedArgs, expectedEnv) 94 | 95 | describe "mtp", -> 96 | 97 | it "should launch meteor with --port 3100 and set ROOT_URL to 'http://localhost:3100/' by default", (done)-> 98 | execTestPackages( 99 | done, 100 | '--production', 101 | '--production' 102 | ) 103 | 104 | it "should launch meteor with --port $TEST_PORT, set PORT to $TEST_PORT and ROOT_URL to 'http://localhost:$TEST_PORT/'", (done)-> 105 | execOptions.env.TEST_PORT = 3200 106 | expectedEnv = 107 | PORT: '3200' # Env vars are strings 108 | ROOT_URL: 'http://localhost:3200/' 109 | execTestPackages( 110 | done, 111 | '--production', 112 | '--production', 113 | expectedEnv 114 | ) 115 | 116 | it "should launch meteor with ROOT_URL set to TEST_ROOT_URL", (done)-> 117 | execOptions.env.TEST_PORT = 3300 118 | execOptions.env.TEST_ROOT_URL = 'https://myvm/' 119 | expectedEnv = 120 | PORT: '3300' 121 | ROOT_URL: 'https://myvm/' 122 | execTestPackages( 123 | done, 124 | '--production', 125 | '--production', 126 | expectedEnv 127 | ) 128 | 129 | it "should launch meteor with MONGO_URL set to TEST_MONGO_URL", (done)-> 130 | execOptions.env.TEST_MONGO_URL = 'mongodb://user:pass@mongohq.com/testdb' 131 | expectedEnv = 132 | MONGO_URL: execOptions.env.TEST_MONGO_URL 133 | execTestPackages( 134 | done, 135 | '--production', 136 | '--production', 137 | expectedEnv 138 | ) 139 | 140 | it "should launch meteor with --settings $METEOR_SETTINGS_PATH", (done)-> 141 | settingsPath = __dirname + '/settings.json' 142 | execOptions.env.METEOR_SETTINGS_PATH = settingsPath 143 | execTestPackages( 144 | done, 145 | '--release 1.0', 146 | "--settings #{settingsPath} --release 1.0" 147 | ) 148 | 149 | it "should launch meteor with --settings $TEST_METEOR_SETTINGS_PATH", (done)-> 150 | settingsPath = __dirname + '/test-settings.json' 151 | execOptions.env.TEST_METEOR_SETTINGS_PATH = settingsPath 152 | execTestPackages( 153 | done, 154 | '--release 1.0', 155 | "--settings #{settingsPath} --release 1.0" 156 | ) 157 | -------------------------------------------------------------------------------- /tests/lib/SpacejamTest.coffee: -------------------------------------------------------------------------------- 1 | chai = require("chai") 2 | expect = chai.expect 3 | sinon = require("sinon") 4 | sinonChai = require("sinon-chai") 5 | chai.use(sinonChai) 6 | path = require "path" 7 | Spacejam = require '../../lib/Spacejam' 8 | 9 | 10 | describe "Spacejam", -> 11 | @timeout 60000 12 | 13 | spacejam = null 14 | 15 | before -> 16 | 17 | beforeEach -> 18 | delete process.env.PORT 19 | delete process.env.ROOT_URL 20 | delete process.env.MONGO_URL 21 | delete process.env.PACKAGE_DIRS 22 | 23 | spacejam = new Spacejam() 24 | 25 | afterEach -> 26 | spacejam = null 27 | -------------------------------------------------------------------------------- /tests/packages/standalone-package-dep/.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | versions.json 3 | -------------------------------------------------------------------------------- /tests/packages/standalone-package-dep/package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: "standalone-package-dep", 3 | version: "1.0.1" 4 | }); 5 | 6 | Package.onUse(function (api) { 7 | api.versionsFrom('0.9.0'); 8 | 9 | api.use(['coffeescript']); 10 | 11 | api.addFiles(['success.coffee']) 12 | }); 13 | 14 | Package.onTest(function(api) { 15 | api.use(['coffeescript', 'tinytest', 'standalone-package-dep']); 16 | 17 | api.addFiles('success-test.coffee'); 18 | }); 19 | -------------------------------------------------------------------------------- /tests/packages/standalone-package-dep/success-test.coffee: -------------------------------------------------------------------------------- 1 | Tinytest.add "standalone-package-dep",(test)-> 2 | test.equal true, true 3 | -------------------------------------------------------------------------------- /tests/packages/standalone-package-dep/success.coffee: -------------------------------------------------------------------------------- 1 | console.log("I am package: standalone-package-dep") 2 | -------------------------------------------------------------------------------- /tests/packages/standalone-package/.gitignore: -------------------------------------------------------------------------------- 1 | .build* 2 | versions.json 3 | -------------------------------------------------------------------------------- /tests/packages/standalone-package/package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: "standalone-package", 3 | summary: "spacejam test - standalone package with passing tests", 4 | version: "0.9.5" 5 | }); 6 | 7 | Package.onUse(function (api) { 8 | api.versionsFrom('0.9.0'); 9 | 10 | api.use(['coffeescript', 'standalone-package-dep']); 11 | 12 | api.addFiles(['success.coffee']) 13 | }); 14 | 15 | Package.onTest(function(api) { 16 | api.use(['coffeescript', 'tinytest', 'standalone-package']); 17 | 18 | api.addFiles('success-test.coffee'); 19 | }); 20 | -------------------------------------------------------------------------------- /tests/packages/standalone-package/success-test.coffee: -------------------------------------------------------------------------------- 1 | Tinytest.add "standalone-package",(test)-> 2 | test.equal true, true 3 | -------------------------------------------------------------------------------- /tests/packages/standalone-package/success.coffee: -------------------------------------------------------------------------------- 1 | console.log("I am package: standalone-package") 2 | --------------------------------------------------------------------------------