├── .versions ├── README.md ├── package.js ├── History.md ├── .gitignore ├── package.json ├── LICENSE └── index.js /.versions: -------------------------------------------------------------------------------- 1 | meteor@1.1.9 2 | underscore@1.0.4 3 | velocity:meteor-stubs@1.1.1 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | meteor-stubs 2 | ============ 3 | 4 | Stubs of Meteor core objects. For use in unit testing frameworks. 5 | 6 | 7 | ## Usage 8 | 9 | Add stubs to global context: 10 | 11 | ```js 12 | // test-script.js 13 | MeteorStubs.install(); 14 | ``` 15 | 16 | Revert context: 17 | 18 | ```js 19 | MeteorStubs.uninstall(); 20 | ``` 21 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | Package.describe({ 2 | name: 'velocity:meteor-stubs', 3 | summary: 'Meteor stubs and mocks for unit testing.', 4 | version: '1.1.1', 5 | git: 'https://github.com/meteor-velocity/meteor-stubs' 6 | }); 7 | 8 | Package.onUse(function (api) { 9 | api.addFiles('index.js'); 10 | api.addAssets('index.js', ['client', 'server']); 11 | api.export('MeteorStubs'); 12 | }); 13 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | ## v0.0.6 2 | 3 | * Include stubs for Meteor.call/apply, ServiceConfiguration, and Collection upsert 4 | 5 | 6 | ## v0.0.5 7 | 8 | * Include stubs for missing Meteor timer functions 9 | 10 | 11 | ## v0.0.4 12 | 13 | * Stub the `Assets` api 14 | 15 | 16 | ## v0.0.3 17 | 18 | * Support 0.9.1 new symbols (Mongo, Tracker) 19 | 20 | 21 | ## v0.0.2 22 | 23 | * Refactor to support client-side use in browsers 24 | * Use `MeteorStubs.install` / `uninstall` to load and unload stubs 25 | 26 | 27 | ## v0.0.1 28 | 29 | Initial commit 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # swap files 6 | *.swp 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | 13 | # Directory for instrumented libs generated by jscoverage/JSCover 14 | lib-cov 15 | 16 | # Coverage directory used by tools like istanbul 17 | coverage 18 | 19 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 20 | .grunt 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # Deployed apps should consider commenting this line out: 27 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 28 | node_modules 29 | .build* 30 | .idea 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "meteor-stubs", 3 | "description": "Stubs for Meteor core objects", 4 | "homepage": "https://github.com/alanning/meteor-stubs", 5 | "version": "0.0.6", 6 | "dependencies": {}, 7 | "devDependencies": {}, 8 | "maintainers": [ 9 | { 10 | "name": "Adrian Lanning", 11 | "email": "alanning@gmail.com" 12 | } 13 | ], 14 | "bugs": { 15 | "url": "https://github.com/alanning/meteor-stubs/issues" 16 | }, 17 | "licenses": [ 18 | { 19 | "type": "MIT" 20 | } 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/alanning/meteor-stubs.git" 25 | }, 26 | "main": "./index.js", 27 | "engines": { 28 | "node": ">=0.8.0" 29 | }, 30 | "scripts": {} 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Adrian Lanning 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. -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /*jshint -W020, -W079 */ 2 | /*global MeteorStubs: true*/ 3 | "use strict"; 4 | 5 | // TODO: Blaze? 6 | // TODO: ReactiveVar 7 | // TODO: EJSON? 8 | 9 | ////////////////////////////////////////////////////////////////////// 10 | // Meteor Stubs 11 | // 12 | // Stubs for the core Meteor objects. 13 | // 14 | // Usage: 15 | // 16 | // MeteorStubs.install() - installs stubs into the global object 17 | // (either `global` or `window`) 18 | // MeteorStubs.uninstall() - restore global object fields to their 19 | // previous values 20 | // 21 | // A note about the structure of this package: 22 | // Having everything all in a single file is not ideal but it makes 23 | // it much easier to include client-side. Please see the ToC below 24 | // to ease browsing. Each section has a unique id which you can 25 | // search on. 26 | // 27 | // 28 | // Table of Contents: 29 | // 30 | // MS00 - MeteorStubs 31 | // MS01 - Common prototypes 32 | // Collection, Cursor, ObjectId 33 | // MS05 - Meteor 34 | // MS05-1 - Meteor.Collection 35 | // MS05-2 - Meteor.Collection.ObjectID 36 | // MS05-3 - Meteor.users 37 | // MS06 - Check 38 | // MS10 - Npm 39 | // MS15 - Tracker 40 | // MS20 - Package 41 | // MS25 - Random 42 | // MS30 - Session 43 | // MS35 - Templates 44 | // MS40 - Handlebars 45 | // MS45 - Accounts 46 | // MS48 - ServiceConfiguration 47 | // MS50 - __meteor_bootstrap__ 48 | // MS55 - share 49 | // MS60 - Mongo 50 | // MS62 - HTTP 51 | // MS63 - Email 52 | // MS65 - Assets 53 | // MS70 - Cordova 54 | // 55 | ////////////////////////////////////////////////////////////////////// 56 | 57 | 58 | // Factory methods are used so that each time `MeteorStubs.install` is 59 | // called, a clean object will be returned. 60 | // Each stub has one factory associated with it. 61 | 62 | var stubFactories = {}, 63 | emptyFn = function () {}, 64 | stringFn = function () { return '' }, 65 | callbackFn = function (fn) { fn() }; 66 | 67 | 68 | 69 | 70 | ////////////////////////////////////////////////////////////////////// 71 | // MS00 - MeteorStubs 72 | ////////////////////////////////////////////////////////////////////// 73 | 74 | ;(function (global) { 75 | var _context = global, 76 | _originals = {}; 77 | 78 | var meteorStubs = { 79 | 80 | /** 81 | * Install Meteor stubs into global context 82 | * 83 | * @method install 84 | * @param {Object} [context] Optional. The context to attach 85 | * stubs to. Default: the global context. 86 | */ 87 | install: function (context) { 88 | 89 | if ('object' == typeof context && null !== context) { 90 | // place stubs on user-defined context 91 | _context = context; 92 | } 93 | 94 | for (var key in stubFactories) { 95 | if (_context[key] && !_originals[key]) { 96 | _originals[key] = _context[key]; 97 | } 98 | _context[key] = stubFactories[key](); 99 | } 100 | 101 | }, 102 | 103 | 104 | /** 105 | * Remove stubs by restoring context's original fields 106 | * 107 | * @method uninstall 108 | */ 109 | uninstall: function () { 110 | for (var key in stubFactories) { 111 | if ('undefined' == typeof _originals[key]) { 112 | delete _context[key]; 113 | } else { 114 | _context[key] = _originals[key]; 115 | } 116 | } 117 | } 118 | 119 | }; // end global.MeteorStubs 120 | 121 | if (typeof Meteor === 'undefined') { 122 | global.MeteorStubs = meteorStubs; 123 | } else { 124 | try { 125 | MeteorStubs = meteorStubs; 126 | } catch (error) { 127 | global.MeteorStubs = meteorStubs; 128 | } 129 | if (Meteor.isClient) { 130 | global.MeteorStubs = meteorStubs; 131 | } 132 | } 133 | 134 | })(typeof global === 'undefined' ? window : global); 135 | 136 | 137 | 138 | ////////////////////////////////////////////////////////////////////// 139 | // Common Prototypes - MS01 140 | ////////////////////////////////////////////////////////////////////// 141 | 142 | var prototypes = { 143 | 144 | Collection: { 145 | find: function () { 146 | var Mongo = stubFactories.Mongo(); 147 | return new Mongo.Cursor(); 148 | }, 149 | findOne: emptyFn, 150 | insert: emptyFn, 151 | update: emptyFn, 152 | upsert: emptyFn, 153 | remove: emptyFn, 154 | allow: emptyFn, 155 | deny: emptyFn, 156 | // TODO: Still needed? 157 | _ensureIndex: emptyFn 158 | }, // end Collection 159 | 160 | Cursor: { 161 | forEach: emptyFn, 162 | map: emptyFn, 163 | fetch: emptyFn, 164 | count: emptyFn, 165 | observe: emptyFn, 166 | observeChanges: emptyFn 167 | }, 168 | 169 | ObjectID: { 170 | getTimestamp: stringFn, 171 | toHexString: stringFn, 172 | toJSONValue: stringFn 173 | } 174 | 175 | }; // end prototypes 176 | 177 | 178 | ////////////////////////////////////////////////////////////////////// 179 | // Meteor - MS05 180 | ////////////////////////////////////////////////////////////////////// 181 | 182 | stubFactories.Meteor = function () { 183 | var _instantiationCounts = {}, 184 | Meteor; 185 | 186 | function collectionFn (collectionName) { 187 | var current = _instantiationCounts[collectionName]; 188 | 189 | if (!current) { 190 | _instantiationCounts[collectionName] = 1 191 | } else { 192 | _instantiationCounts[collectionName] = current + 1 193 | } 194 | } 195 | 196 | Meteor = { 197 | // Core 198 | isClient: true, 199 | isServer: true, 200 | isCordova: false, 201 | startup: function (newStartupFunction) { 202 | this.startupFunctions.push(newStartupFunction); 203 | }, 204 | wrapAsync: emptyFn, 205 | absoluteUrl: emptyFn, 206 | settings: { public: {} }, 207 | release: undefined, 208 | 209 | // Publish and subscribe 210 | publish: function (modelName, publishFunction) { 211 | this.publishFunctions[modelName] = publishFunction; 212 | }, 213 | subscribe: function (modelName, subscribeFunction) { 214 | this.subscribeFunctions[modelName] = subscribeFunction; 215 | return { 216 | ready: function () { 217 | return true; 218 | } 219 | }; 220 | }, 221 | 222 | // Methods 223 | methods: function (map) { 224 | for (var name in map) { 225 | //noinspection JSUnfilteredForInLoop 226 | this.methodMap[name] = map[name]; 227 | } 228 | }, 229 | Error: function(error, reason, details) { 230 | if (error) this.error = error; 231 | if (reason) this.reason = reason; 232 | if (details) this.details = details; 233 | }, 234 | call: function(name /* .. [arguments] .. callback */) { 235 | // if it's a function, the last argument is the result callback, 236 | // not a parameter to the remote method. 237 | var args = Array.prototype.slice.call(arguments, 1); 238 | if (args.length && typeof args[args.length - 1] === "function") { 239 | var callback = args.pop(); 240 | } 241 | 242 | return Meteor.apply(name, args, callback) 243 | }, 244 | callInContext: function(name, context /* .. [arguments] .. callback */) { 245 | // if it's a function, the last argument is the result callback, 246 | // not a parameter to the remote method. 247 | var args = Array.prototype.slice.call(arguments, 2); 248 | if (args.length && typeof args[args.length - 1] === "function") { 249 | var callback = args.pop(); 250 | } 251 | 252 | return Meteor.applyInContext(name, context, args, callback) 253 | }, 254 | // TODO: Support options.onResultReceived 255 | apply: function(name, args, options, callback) { 256 | var context = { 257 | userId: null, 258 | setUserId: emptyFn, 259 | isSimulation: false, 260 | unblock: emptyFn, 261 | connection: null 262 | }; 263 | 264 | return Meteor.applyInContext(name, context, args, options, callback); 265 | }, 266 | // TODO: Support options.onResultReceived 267 | applyInContext: function(name, context, args, options, callback) { 268 | // We were passed 4 arguments. 269 | // They may be either (name, context, args, options) 270 | // or (name, context, args, callback) 271 | if (!callback && typeof options === 'function') { 272 | callback = options; 273 | //options = {}; 274 | } 275 | //options = options || {}; 276 | 277 | return Meteor.executeFunction(function() { 278 | return Meteor.methodMap[name].apply(context, args); 279 | }, callback); 280 | }, 281 | 282 | // Server connections 283 | status: function () { 284 | return { 285 | connected: true, 286 | status: 'connected', 287 | retryCount: 0, 288 | retryTime: undefined, 289 | reason: undefined 290 | } 291 | }, 292 | reconnect: emptyFn, 293 | disconnect: emptyFn, 294 | onConnection: emptyFn, 295 | // TODO: DDP.connect 296 | 297 | // Collections 298 | /* 299 | * @Deprecated Use Mongo.Collection 300 | */ 301 | Collection: collectionFn, 302 | /* 303 | * @Deprecated Use Mongo.Collection 304 | */ 305 | SmartCollection: collectionFn, 306 | 307 | // Accounts 308 | user: function () { 309 | return { 310 | emails: [] 311 | }; 312 | }, 313 | userId: function () { 314 | return null; 315 | }, 316 | loggingIn: emptyFn, 317 | logout: emptyFn, 318 | logoutOtherClients: emptyFn, 319 | loginWithMeteorDeveloperAccount: emptyFn, 320 | loginWithFacebook: emptyFn, 321 | loginWithGithub: emptyFn, 322 | loginWithGoogle: emptyFn, 323 | loginWithMeetup: emptyFn, 324 | loginWithTwitter: emptyFn, 325 | loginWithWeibo: emptyFn, 326 | 327 | // Timers 328 | setTimeout: emptyFn, 329 | setInterval: emptyFn, 330 | clearTimeout: emptyFn, 331 | clearInterval: emptyFn, 332 | 333 | // Internal stub state 334 | instantiationCounts: _instantiationCounts, 335 | startupFunctions: [], 336 | publishFunctions: {}, 337 | subscribeFunctions: {}, 338 | methodMap: {}, 339 | 340 | // Methods of the stub 341 | executeFunction: function(func, callback) { 342 | var exception = null; 343 | var result = null; 344 | 345 | try { 346 | result = func(); 347 | } catch (ex) { 348 | exception = ex; 349 | } 350 | 351 | // if we specify the callback function execute it 352 | if (callback) { 353 | callback(exception, result); 354 | } else { 355 | if (exception != null) { 356 | // rethrow exception 357 | throw exception; 358 | } else if (Meteor.isServer) { 359 | return result; 360 | } 361 | } 362 | }, 363 | 364 | runStartupMethods: function () { 365 | for (var i = 0; i < this.startupFunctions.length; i += 1) { 366 | this.startupFunctions[i](); 367 | } 368 | } 369 | }; 370 | 371 | 372 | ////////////////////////////////////////////////////////////////////// 373 | // Meteor.Collection - MS05.1 374 | ////////////////////////////////////////////////////////////////////// 375 | 376 | Meteor.Collection.prototype = prototypes.Collection; 377 | 378 | 379 | 380 | 381 | ////////////////////////////////////////////////////////////////////// 382 | // Meteor.Collection.ObjectID - MS05.2 383 | ////////////////////////////////////////////////////////////////////// 384 | 385 | Meteor.Collection.ObjectID = function () { 386 | return { _str: '' }; 387 | }; 388 | Meteor.Collection.ObjectID.prototype = prototypes.ObjectID 389 | 390 | 391 | 392 | ////////////////////////////////////////////////////////////////////// 393 | // Meteor.users - MS05.3 394 | // 395 | // Instantiate the users default collection 396 | ////////////////////////////////////////////////////////////////////// 397 | 398 | Meteor.users = new Meteor.Collection('users'); 399 | 400 | 401 | 402 | 403 | return Meteor; 404 | 405 | }; // Meteor 406 | 407 | 408 | ////////////////////////////////////////////////////////////////////// 409 | // MS06 - Check 410 | ////////////////////////////////////////////////////////////////////// 411 | 412 | stubFactories.check = function () { 413 | return emptyFn; 414 | }; 415 | 416 | stubFactories.Match = function () { 417 | return { 418 | test: emptyFn 419 | }; 420 | }; 421 | 422 | 423 | ////////////////////////////////////////////////////////////////////// 424 | // MS10 - Npm 425 | ////////////////////////////////////////////////////////////////////// 426 | 427 | stubFactories.Npm = function () { 428 | return { 429 | depends: emptyFn, 430 | require: emptyFn 431 | }; 432 | }; 433 | 434 | 435 | ////////////////////////////////////////////////////////////////////// 436 | // MS15 - Deps / Tracker 437 | ////////////////////////////////////////////////////////////////////// 438 | 439 | // TODO: Tracker.Computation (if needed) 440 | // TODO: Tracker.Dependency (if needed) 441 | 442 | stubFactories.Tracker = function () { 443 | return { 444 | autorun: callbackFn, 445 | flush: emptyFn, 446 | nonreactive: callbackFn, 447 | active: false, 448 | currentComputation: emptyFn, 449 | onInvalidate: emptyFn, 450 | afterFlush: emptyFn 451 | }; 452 | }; 453 | stubFactories.Deps = stubFactories.Tracker 454 | 455 | 456 | ////////////////////////////////////////////////////////////////////// 457 | // MS20 - Package 458 | ////////////////////////////////////////////////////////////////////// 459 | 460 | stubFactories.Package = function () { 461 | return { 462 | describe: emptyFn, 463 | onUse: emptyFn, 464 | onTest: emptyFn, 465 | registerBuildPlugin: emptyFn 466 | }; 467 | }; 468 | 469 | 470 | 471 | ////////////////////////////////////////////////////////////////////// 472 | // MS25 - Random 473 | ////////////////////////////////////////////////////////////////////// 474 | 475 | stubFactories.Random = function () { 476 | return { 477 | id: emptyFn, 478 | secret: emptyFn, 479 | fraction: emptyFn, 480 | choice: emptyFn, 481 | hexString: emptyFn 482 | }; 483 | }; 484 | 485 | 486 | 487 | ////////////////////////////////////////////////////////////////////// 488 | // MS30 - Session 489 | ////////////////////////////////////////////////////////////////////// 490 | 491 | stubFactories.Session = function () { 492 | return { 493 | store: {}, 494 | set: function (key, value) { 495 | this.store[key] = value; 496 | }, 497 | setDefault: function (key, value) { 498 | if (typeof this.get(key) === 'undefined') { 499 | this.set(key, value); 500 | } 501 | }, 502 | get: function (key) { 503 | return this.store[key]; 504 | }, 505 | equals: function (key, value) { 506 | return this.store[key] === value; 507 | } 508 | }; 509 | }; 510 | 511 | 512 | ////////////////////////////////////////////////////////////////////// 513 | // MS35 - Templates 514 | ////////////////////////////////////////////////////////////////////// 515 | 516 | function TemplateClass () {} 517 | TemplateClass.prototype = { 518 | stub: function (templateName) { 519 | TemplateClass.prototype[templateName] = { 520 | eventMap: {}, 521 | events: function (eventMap) { 522 | for (var event in eventMap) { 523 | //noinspection JSUnfilteredForInLoop 524 | TemplateClass.prototype[templateName].eventMap[event] = eventMap[event]; 525 | } 526 | }, 527 | helpers: function (helperMap) { 528 | for (var helper in helperMap) { 529 | //noinspection JSUnfilteredForInLoop 530 | TemplateClass.prototype[templateName][helper] = helperMap[helper]; 531 | } 532 | }, 533 | fireEvent: function (key) { 534 | if (arguments.length > 1) { 535 | var args = Array.prototype.slice.call(arguments, 1); 536 | TemplateClass.prototype[templateName].eventMap[key].apply(null, args); 537 | } else { 538 | TemplateClass.prototype[templateName].eventMap[key](); 539 | } 540 | }, 541 | // Allows you to set an attribute in the event 'this' context 542 | addContextAttribute: function (key, value) { 543 | TemplateClass.prototype[templateName].eventMap[key] = value; 544 | } 545 | }; 546 | } 547 | }; 548 | 549 | stubFactories.Template = function () { 550 | var Template = new TemplateClass(); 551 | 552 | Template.registerHelper = emptyFn; 553 | Template.instance = emptyFn; 554 | Template.currentData = emptyFn; 555 | Template.parentData = emptyFn; 556 | Template.body = {}; 557 | 558 | return Template; 559 | }; 560 | 561 | 562 | ////////////////////////////////////////////////////////////////////// 563 | // MS40 - Handlebars 564 | ////////////////////////////////////////////////////////////////////// 565 | 566 | function HandlebarsClass () {} 567 | HandlebarsClass.prototype = { 568 | helpers: {}, 569 | registerHelper: function (name, method) { 570 | this.helpers[name] = method; 571 | } 572 | }; 573 | 574 | stubFactories.Handlebars = function () { 575 | return new HandlebarsClass(); 576 | }; 577 | 578 | 579 | 580 | ////////////////////////////////////////////////////////////////////// 581 | // MS45 - Accounts 582 | ////////////////////////////////////////////////////////////////////// 583 | 584 | stubFactories.Accounts = function () { 585 | return { 586 | // Accounts 587 | config: emptyFn, 588 | ui: { 589 | config: emptyFn 590 | }, 591 | validateNewUser: emptyFn, 592 | onCreateUser: emptyFn, 593 | validateLoginAttempt: emptyFn, 594 | onLogin: emptyFn, 595 | onLoginFailure: emptyFn, 596 | 597 | // Passwords 598 | createUser: emptyFn, 599 | changePassword: emptyFn, 600 | forgotPassword: emptyFn, 601 | resetPassword: emptyFn, 602 | setPassword: emptyFn, 603 | verifyEmail: emptyFn, 604 | 605 | sendResetPasswordEmail: emptyFn, 606 | sendEnrollmentEmail: emptyFn, 607 | sendVerificationEmail: emptyFn, 608 | 609 | onResetPasswordLink: emptyFn, 610 | onEnrollmentLink: emptyFn, 611 | onEmailVerificationLink: emptyFn, 612 | 613 | emailTemplates: { 614 | resetPassword: {}, 615 | enrollAccount: {}, 616 | verifyEmail: {} 617 | } 618 | }; 619 | }; 620 | 621 | 622 | ////////////////////////////////////////////////////////////////////// 623 | // MS48 - ServiceConfiguration 624 | ////////////////////////////////////////////////////////////////////// 625 | 626 | stubFactories.ServiceConfiguration = function () { 627 | var Mongo = stubFactories.Mongo(); 628 | var ServiceConfiguration = { 629 | configurations: new Mongo.Collection('meteor_accounts_loginServiceConfiguration') 630 | } 631 | 632 | return ServiceConfiguration; 633 | }; 634 | 635 | 636 | ////////////////////////////////////////////////////////////////////// 637 | // MS50 - __meteor_bootstrap__ 638 | ////////////////////////////////////////////////////////////////////// 639 | 640 | stubFactories.__meteor_bootstrap__ = function () { 641 | return { 642 | deployConfig: { 643 | packages: { 'mongo-livedata': { url: '' } } 644 | } 645 | }; 646 | }; 647 | 648 | ////////////////////////////////////////////////////////////////////// 649 | // MS55 - share 650 | ////////////////////////////////////////////////////////////////////// 651 | 652 | stubFactories.share = function () { 653 | return {}; 654 | }; 655 | 656 | 657 | ////////////////////////////////////////////////////////////////////// 658 | // MS60 - Mongo 659 | ////////////////////////////////////////////////////////////////////// 660 | 661 | stubFactories.Mongo = function () { 662 | var _instantiationCounts = {}, 663 | Mongo; 664 | 665 | function collectionFn (collectionName) { 666 | var current = _instantiationCounts[collectionName]; 667 | 668 | if (!current) { 669 | _instantiationCounts[collectionName] = 1 670 | } else { 671 | _instantiationCounts[collectionName] = current + 1 672 | } 673 | } 674 | 675 | Mongo = { 676 | instantiationCounts: _instantiationCounts, 677 | Collection: collectionFn, 678 | Cursor: emptyFn, 679 | ObjectID: function () { 680 | return { _str: '' }; 681 | } 682 | }; 683 | 684 | Mongo.Collection.prototype = prototypes.Collection; 685 | Mongo.Cursor.prototype = prototypes.Cursor; 686 | Mongo.ObjectID.prototype = prototypes.ObjectID; 687 | 688 | return Mongo; 689 | }; 690 | 691 | 692 | ////////////////////////////////////////////////////////////////////// 693 | // MS62 - HTTP 694 | ////////////////////////////////////////////////////////////////////// 695 | stubFactories.HTTP = function () { 696 | return { 697 | call: emptyFn, 698 | get: emptyFn, 699 | post: emptyFn, 700 | put: emptyFn, 701 | del: emptyFn 702 | }; 703 | }; 704 | 705 | 706 | ////////////////////////////////////////////////////////////////////// 707 | // MS63 - Email 708 | ////////////////////////////////////////////////////////////////////// 709 | stubFactories.Email = function () { 710 | return { 711 | send: emptyFn 712 | }; 713 | }; 714 | 715 | 716 | ////////////////////////////////////////////////////////////////////// 717 | // MS65 - Assets 718 | ////////////////////////////////////////////////////////////////////// 719 | 720 | stubFactories.Assets = function () { 721 | return { 722 | getText: stringFn, 723 | getBinary: emptyFn 724 | }; 725 | }; 726 | 727 | 728 | ////////////////////////////////////////////////////////////////////// 729 | // MS70 - Cordova 730 | ////////////////////////////////////////////////////////////////////// 731 | stubFactories.Cordova = function () { 732 | return { 733 | depends: emptyFn 734 | }; 735 | } 736 | 737 | --------------------------------------------------------------------------------