From 01d40851251688d75376c98583d7405c0a959b2f Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Wed, 13 May 2015 14:12:54 -0400 Subject: [PATCH] Removed bad JS tests, upgrade QUnit + ember-qunit --- Gemfile | 2 +- Gemfile.lock | 6 +- .../admin-site-settings-test.js.es6 | 31 - .../components/ace-editor-test.js.es6 | 6 + .../text-field-test.js.es6 | 2 +- .../controllers/user-dropdown-test.js.es6 | 9 - test/javascripts/helpers/init-ember-qunit.js | 5 +- test/javascripts/lib/debounce-test.js.es6 | 82 - test/javascripts/lib/url-test.js.es6 | 32 - test/javascripts/test_helper.js | 11 - .../javascripts/views/header-view-test.js.es6 | 11 - vendor/assets/javascripts/ember-qunit.js | 1316 +++++++++++++---- .../assets/javascripts/sinon-qunit-1.0.0.js | 14 +- 13 files changed, 1062 insertions(+), 465 deletions(-) delete mode 100644 test/javascripts/admin/controllers/admin-site-settings-test.js.es6 create mode 100644 test/javascripts/components/ace-editor-test.js.es6 rename test/javascripts/{views => components}/text-field-test.js.es6 (89%) delete mode 100644 test/javascripts/lib/debounce-test.js.es6 delete mode 100644 test/javascripts/views/header-view-test.js.es6 diff --git a/Gemfile b/Gemfile index 3f7a2446ada..3d9cd514720 100644 --- a/Gemfile +++ b/Gemfile @@ -124,7 +124,7 @@ group :test, :development do gem 'certified', require: false # later appears to break Fabricate(:topic, category: category) gem 'fabrication', '2.9.8', require: false - gem 'qunit-rails' + gem 'discourse-qunit-rails', require: 'qunit-rails' gem 'mocha', require: false gem 'rb-fsevent', require: RUBY_PLATFORM =~ /darwin/i ? 'rb-fsevent' : false gem 'rb-inotify', '~> 0.9', require: RUBY_PLATFORM =~ /linux/i ? 'rb-inotify' : false diff --git a/Gemfile.lock b/Gemfile.lock index fd65ba48793..7cf52c720e3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -64,6 +64,8 @@ GEM daemons (1.2.2) debug_inspector (0.0.2) diff-lcs (1.2.5) + discourse-qunit-rails (0.0.8) + railties docile (1.1.5) dotenv (1.0.2) email_reply_parser (0.5.8) @@ -291,8 +293,6 @@ GEM pry (>= 0.9.10) puma (2.11.1) rack (>= 1.1, < 2.0) - qunit-rails (0.0.7) - railties r2 (0.2.5) rack (1.5.3) rack-mini-profiler (0.9.3) @@ -464,6 +464,7 @@ DEPENDENCIES better_errors binding_of_caller certified + discourse-qunit-rails email_reply_parser ember-rails ember-source (= 1.11.3.1) @@ -510,7 +511,6 @@ DEPENDENCIES pry-nav pry-rails puma - qunit-rails r2 (~> 0.2.5) rack-mini-profiler rack-protection diff --git a/test/javascripts/admin/controllers/admin-site-settings-test.js.es6 b/test/javascripts/admin/controllers/admin-site-settings-test.js.es6 deleted file mode 100644 index 033ca019a85..00000000000 --- a/test/javascripts/admin/controllers/admin-site-settings-test.js.es6 +++ /dev/null @@ -1,31 +0,0 @@ -moduleFor("controller:admin-site-settings"); - -test("filter", function() { - var allSettings = [ - Ember.Object.create({ - nameKey: 'users', name: 'users', - siteSettings: [Discourse.SiteSetting.create({"setting":"username_change_period","description":"x","default":3,"type":"fixnum","value":"3","category":"users"})] - }), - Ember.Object.create({ - nameKey: 'posting', name: 'posting', - siteSettings: [Discourse.SiteSetting.create({"setting":"display_name_on_posts","description":"x","default":false,"type":"bool","value":"true","category":"posting"})] - }) - ]; - - var adminSiteSettingsController = this.subject({ model: allSettings }); - sinon.stub(adminSiteSettingsController, "transitionToRoute"); - - adminSiteSettingsController.set('allSiteSettings', allSettings); - equal(adminSiteSettingsController.get('content')[0].nameKey, 'users', "Can get first site setting category's name key."); - - adminSiteSettingsController.set('filter', 'username_change'); - equal(adminSiteSettingsController.get('content').length, 1, "Filter with one match for username_change"); - equal(adminSiteSettingsController.get('content')[0].nameKey, "all_results", "First element is all the results that match"); - equal(adminSiteSettingsController.get('content')[0].siteSettings[0].setting, "username_change_period", "Filter with one match for username_change"); - - adminSiteSettingsController.setProperties({ filter: '', onlyOverridden: true }); - equal(adminSiteSettingsController.get('content').length, 1, "onlyOverridden with one match"); - equal(adminSiteSettingsController.get('content')[0].nameKey, "all_results", "onlyOverridden with one match"); - equal(adminSiteSettingsController.get('content')[0].siteSettings[0].setting, "display_name_on_posts", "onlyOverridden with one match"); - -}); diff --git a/test/javascripts/components/ace-editor-test.js.es6 b/test/javascripts/components/ace-editor-test.js.es6 new file mode 100644 index 00000000000..2b01e739081 --- /dev/null +++ b/test/javascripts/components/ace-editor-test.js.es6 @@ -0,0 +1,6 @@ +moduleForComponent('ace-editor', {needs: []}); + +test('changing colors', function(assert) { + assert.expect(0); + var component = this.subject(); +}); diff --git a/test/javascripts/views/text-field-test.js.es6 b/test/javascripts/components/text-field-test.js.es6 similarity index 89% rename from test/javascripts/views/text-field-test.js.es6 rename to test/javascripts/components/text-field-test.js.es6 index 7f285703bf6..3b939913421 100644 --- a/test/javascripts/views/text-field-test.js.es6 +++ b/test/javascripts/components/text-field-test.js.es6 @@ -1,4 +1,4 @@ -moduleForComponent("text-field"); +moduleForComponent("text-field", {needs: []}); test("renders correctly with no properties set", function() { var component = this.subject(); diff --git a/test/javascripts/controllers/user-dropdown-test.js.es6 b/test/javascripts/controllers/user-dropdown-test.js.es6 index 6e34107283f..820ff8a69ae 100644 --- a/test/javascripts/controllers/user-dropdown-test.js.es6 +++ b/test/javascripts/controllers/user-dropdown-test.js.es6 @@ -1,14 +1,5 @@ moduleFor("controller:user-dropdown"); -test("logout action logs out the current user", function () { - const logoutMock = sinon.mock(Discourse, "logout"); - logoutMock.expects("logout").once(); - - this.subject().send('logout'); - - logoutMock.verify(); -}); - test("showAdminLinks", function() { const currentUser = Ember.Object.create({ staff: true }); const controller = this.subject({ currentUser }); diff --git a/test/javascripts/helpers/init-ember-qunit.js b/test/javascripts/helpers/init-ember-qunit.js index 84ac701cd64..b96c0fe4668 100644 --- a/test/javascripts/helpers/init-ember-qunit.js +++ b/test/javascripts/helpers/init-ember-qunit.js @@ -1,5 +1,2 @@ -/* global emq */ - var resolver = require('discourse/ember/resolver').default; -emq.globalize(); -emq.setResolver(resolver.create({ namespace: Discourse })); +window.setResolver(resolver.create({ namespace: Discourse })); diff --git a/test/javascripts/lib/debounce-test.js.es6 b/test/javascripts/lib/debounce-test.js.es6 deleted file mode 100644 index d3c88cd4e4d..00000000000 --- a/test/javascripts/lib/debounce-test.js.es6 +++ /dev/null @@ -1,82 +0,0 @@ -var clock, original, debounced; - -var firedOnce = function(message) { - ok(original.calledOnce, message); -}; - -var firedTwice = function(message) { - ok(original.calledTwice, message); -}; - -var notFired = function(message) { - ok(!original.called, message); -}; - -module("Discourse.debounce", { - setup: function() { - clock = sinon.useFakeTimers(); - original = sinon.spy(); - debounced = Discourse.debounce(original, 100); - }, - - teardown: function() { - clock.restore(); - } -}); - -test("delays function execution till the end of the timeout", function() { - debounced(); - notFired("immediately after calling debounced function nothing happens"); - - clock.tick(99); - notFired("just before the end of the timeout still nothing happens"); - - clock.tick(1); - firedOnce("exactly at the end of the timeout the function is executed"); -}); - -test("executes delayed function only once, no matter how many times debounced function is called during the timeout", function() { - debounced(); - debounced(); - - clock.tick(100); - firedOnce("second call was supressed"); -}); - -test("prolongs the timeout when the debounced function is called for the second time during the timeout", function() { - debounced(); - - clock.tick(50); - debounced(); - - clock.tick(50); - notFired("at the end of the original timeout nothing happens"); - - clock.tick(50); - firedOnce("function is executed exactly at the end of the prolonged timeout"); -}); - -test("preserves last call's context and params when executing delayed function", function() { - var firstObj = {}; - var secondObj = {}; - - debounced.call(firstObj, "first"); - debounced.call(secondObj, "second"); - - clock.tick(100); - ok(original.calledOn(secondObj), "the context of the last of two subsequent calls is preserved"); - ok(original.calledWithExactly("second"), "param passed during the last of two subsequent calls is preserved"); -}); - -test("can be called again after timeout passes", function() { - var firstObj = {}; - var secondObj = {}; - - debounced.call(firstObj, "first"); - - clock.tick(100); - debounced.call(secondObj, "second"); - - clock.tick(100); - firedTwice(); -}); diff --git a/test/javascripts/lib/url-test.js.es6 b/test/javascripts/lib/url-test.js.es6 index 781712ca0da..e2696a77932 100644 --- a/test/javascripts/lib/url-test.js.es6 +++ b/test/javascripts/lib/url-test.js.es6 @@ -14,35 +14,3 @@ test("isInternal with a HTTPS url", function() { sandbox.stub(Discourse.URL, "origin").returns("https://eviltrout.com"); ok(Discourse.URL.isInternal("http://eviltrout.com/monocle"), "HTTPS urls match HTTP urls"); }); - -// -------------------------------------------- -// I DON'T KNOW WHY THIS BREAKS OTHER TESTS :( - // -------------------------------------------- - -// test("routeTo", function() { -// sandbox.stub(Discourse.URL, "handleURL", function (path) { return path === "/t/topic-title/42"; }); - -// ok(Discourse.URL.routeTo("https://discourse.org/t/topic-title/42"), "can route HTTPS"); -// ok(Discourse.URL.routeTo("http://discourse.org/t/topic-title/42"), "can route HTTP"); -// ok(Discourse.URL.routeTo("//discourse.org/t/topic-title/42"), "can route schemaless"); -// ok(Discourse.URL.routeTo("/t/topic-title/42"), "can route relative"); -// }); - -// TODO pending: this works but the test is too mocky and needs to be fixed - -// test("navigatedToHome", function() { -// var fakeDiscoveryController = { send: function() { return true; } }; -// var mock = sinon.mock(fakeDiscoveryController); -// sandbox.stub(Discourse.URL, "controllerFor").returns(fakeDiscoveryController); -// -// mock.expects("send").withArgs('refresh').twice(); -// ok(Discourse.URL.navigatedToHome("/", "/")); -// -// var homepage = "/" + Discourse.Utilities.defaultHomepage(); -// ok(Discourse.URL.navigatedToHome(homepage, "/")); -// -// not(Discourse.URL.navigatedToHome("/old", "/new")); -// -// // make sure we called the .refresh() method -// mock.verify(); -// }); diff --git a/test/javascripts/test_helper.js b/test/javascripts/test_helper.js index a968d479479..53757584203 100644 --- a/test/javascripts/test_helper.js +++ b/test/javascripts/test_helper.js @@ -34,7 +34,6 @@ //= require admin //= require_tree ../../app/assets/javascripts/defer - //= require sinon-1.7.1 //= require sinon-qunit-1.0.0 //= require jshint @@ -50,15 +49,6 @@ // //= require ../../public/javascripts/jquery.magnific-popup-min.js -// sinon settings -sinon.config = { - injectIntoThis: true, - injectInto: null, - properties: ["spy", "stub", "mock", "clock", "sandbox"], - useFakeTimers: false, - useFakeServer: false -}; - window.assetPath = function(url) { if (url.indexOf('defer') === 0) { return "/assets/" + url; @@ -103,7 +93,6 @@ QUnit.testStart(function(ctx) { PreloadStore.reset(); window.sandbox = sinon.sandbox.create(); - window.sandbox.stub(Discourse.ScrollingDOMMethods, "bindOnScroll"); window.sandbox.stub(Discourse.ScrollingDOMMethods, "unbindOnScroll"); diff --git a/test/javascripts/views/header-view-test.js.es6 b/test/javascripts/views/header-view-test.js.es6 deleted file mode 100644 index 2ba9595bb9f..00000000000 --- a/test/javascripts/views/header-view-test.js.es6 +++ /dev/null @@ -1,11 +0,0 @@ -moduleFor("view:header"); - -test("showNotifications", function() { - var controllerSpy = { - send: sinon.spy() - }; - var view = this.subject({controller: controllerSpy}); - view.showNotifications(); - - ok(controllerSpy.send.calledWith("showNotifications", view), "sends showNotifications message to the controller, passing header view as a param"); -}); diff --git a/vendor/assets/javascripts/ember-qunit.js b/vendor/assets/javascripts/ember-qunit.js index a6061f542fd..b09e6a02233 100644 --- a/vendor/assets/javascripts/ember-qunit.js +++ b/vendor/assets/javascripts/ember-qunit.js @@ -1,281 +1,1063 @@ -!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.emq=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0; i--) { - var fullName = fullNames[i - 1]; - container.register(fullName, resolver.resolve(fullName)); +var define, requireModule, require, requirejs; + +(function() { + + var _isArray; + if (!Array.isArray) { + _isArray = function (x) { + return Object.prototype.toString.call(x) === "[object Array]"; + }; + } else { + _isArray = Array.isArray; } - return container; -} -},{"./test-resolver":7}],2:[function(_dereq_,module,exports){ -"use strict"; -var Ember = window.Ember["default"] || window.Ember; -var isolatedContainer = _dereq_("./isolated-container")["default"] || _dereq_("./isolated-container"); -var moduleFor = _dereq_("./module-for")["default"] || _dereq_("./module-for"); -var moduleForComponent = _dereq_("./module-for-component")["default"] || _dereq_("./module-for-component"); -var moduleForModel = _dereq_("./module-for-model")["default"] || _dereq_("./module-for-model"); -var test = _dereq_("./test")["default"] || _dereq_("./test"); -var testResolver = _dereq_("./test-resolver")["default"] || _dereq_("./test-resolver"); - -Ember.testing = true; - -function setResolver(resolver) { - testResolver.set(resolver); -} - -function globalize() { - window.moduleFor = moduleFor; - window.moduleForComponent = moduleForComponent; - window.moduleForModel = moduleForModel; - window.test = test; - window.setResolver = setResolver; -} - -exports.globalize = globalize; -exports.moduleFor = moduleFor; -exports.moduleForComponent = moduleForComponent; -exports.moduleForModel = moduleForModel; -exports.test = test; -exports.setResolver = setResolver; -},{"./isolated-container":1,"./module-for":5,"./module-for-component":3,"./module-for-model":4,"./test":8,"./test-resolver":7}],3:[function(_dereq_,module,exports){ -"use strict"; -var testResolver = _dereq_("./test-resolver")["default"] || _dereq_("./test-resolver"); -var moduleFor = _dereq_("./module-for")["default"] || _dereq_("./module-for"); -var Ember = window.Ember["default"] || window.Ember; - -exports["default"] = function moduleForComponent(name, description, callbacks) { - var resolver = testResolver.get(); - - moduleFor('component:' + name, description, callbacks, function(container, context, defaultSubject) { - var layoutName = 'template:components/' + name; - - var layout = resolver.resolve(layoutName); - - if (layout) { - container.register(layoutName, layout); - container.injection('component:' + name, 'layout', layoutName); - } - - context.dispatcher = Ember.EventDispatcher.create(); - context.dispatcher.setup({}, '#ember-testing'); - - context.__setup_properties__.render = function() { - var containerView = Ember.ContainerView.create({container: container}); - var view = Ember.run(function(){ - var subject = context.subject(); - containerView.pushObject(subject); - // TODO: destory this somewhere - containerView.appendTo('#ember-testing'); - return subject; - }); - - return view.$(); - }; - - context.__setup_properties__.append = function(){ - Ember.deprecate('this.append() is deprecated. Please use this.render() instead.'); - return this.render(); - }; - - context.$ = function(){ - var $view = this.render(), subject = this.subject(); - - if(arguments.length){ - return subject.$.apply(subject, arguments); - }else{ - return $view; - } - }; - }); -} -},{"./module-for":5,"./test-resolver":7}],4:[function(_dereq_,module,exports){ -"use strict"; -var moduleFor = _dereq_("./module-for")["default"] || _dereq_("./module-for"); -var Ember = window.Ember["default"] || window.Ember; - -exports["default"] = function moduleForModel(name, description, callbacks) { - if (!DS) throw new Error('You must have Ember Data installed to use `moduleForModel`.'); - - moduleFor('model:' + name, description, callbacks, function(container, context, defaultSubject) { - if (DS._setupContainer) { - DS._setupContainer(container); - } else { - container.register('store:main', DS.Store); - } - - var adapterFactory = container.lookupFactory('adapter:application'); - if (!adapterFactory) { - container.register('adapter:application', DS.FixtureAdapter); - } - - context.__setup_properties__.store = function(){ - return container.lookup('store:main'); - }; - - if (context.__setup_properties__.subject === defaultSubject) { - context.__setup_properties__.subject = function(options) { - return Ember.run(function() { - return container.lookup('store:main').createRecord(name, options); - }); - }; - } - }); -} -},{"./module-for":5}],5:[function(_dereq_,module,exports){ -"use strict"; -var Ember = window.Ember["default"] || window.Ember; -//import QUnit from 'qunit'; // Assumed global in runner -var testContext = _dereq_("./test-context")["default"] || _dereq_("./test-context"); -var isolatedContainer = _dereq_("./isolated-container")["default"] || _dereq_("./isolated-container"); - -exports["default"] = function moduleFor(fullName, description, callbacks, delegate) { - var container; - var context; - var _callbacks = { - setup: function(){ - callbacks = callbacks || { }; + var registry = {}, seen = {}, state = {}; + var FAILED = false; - var needs = [fullName].concat(callbacks.needs || []); - container = isolatedContainer(needs); - - callbacks.subject = callbacks.subject || defaultSubject; - - callbacks.setup = callbacks.setup || function() { }; - callbacks.teardown = callbacks.teardown || function() { }; - - function factory() { - return container.lookupFactory(fullName); - } - - testContext.set({ - container: container, - factory: factory, - dispatcher: null, - __setup_properties__: callbacks - }); - - context = testContext.get(); - - if (delegate) { - delegate(container, context, defaultSubject); - } - - if (Ember.$('#ember-testing').length === 0) { - Ember.$('
').appendTo(document.body); - } - - buildContextVariables(context); - callbacks.setup.call(context, container); - }, - - teardown: function(){ - Ember.run(function(){ - container.destroy(); - - if (context.dispatcher) { - context.dispatcher.destroy(); - } - }); - - callbacks.teardown(container); - Ember.$('#ember-testing').empty(); + define = function(name, deps, callback) { + + if (!_isArray(deps)) { + callback = deps; + deps = []; } + + registry[name] = { + deps: deps, + callback: callback + }; }; - QUnit.module(description || fullName, _callbacks); -} + function reify(deps, name, seen) { + var length = deps.length; + var reified = new Array(length); + var dep; + var exports; -function defaultSubject(options, factory) { - return factory.create(options); -} - -// allow arbitrary named factories, like rspec let -function buildContextVariables(context) { - var cache = { }; - var callbacks = context.__setup_properties__; - var container = context.container; - var factory = context.factory; - - Ember.keys(callbacks).filter(function(key){ - // ignore the default setup/teardown keys - return key !== 'setup' && key !== 'teardown'; - }).forEach(function(key){ - context[key] = function(options) { - if (cache[key]) { return cache[key]; } - - var result = callbacks[key](options, factory(), container); - cache[key] = result; - return result; - }; - }); -} -},{"./isolated-container":1,"./test-context":6}],6:[function(_dereq_,module,exports){ -"use strict"; -var __test_context__; - -function set(context) { - __test_context__ = context; -} - -exports.set = set;function get() { - return __test_context__; -} - -exports.get = get; -},{}],7:[function(_dereq_,module,exports){ -"use strict"; -var __resolver__; - -function set(resolver) { - __resolver__ = resolver; -} - -exports.set = set;function get() { - if (__resolver__ == null) throw new Error('you must set a resolver with `testResolver.set(resolver)`'); - return __resolver__; -} - -exports.get = get; -},{}],8:[function(_dereq_,module,exports){ -"use strict"; -var Ember = window.Ember["default"] || window.Ember; -//import QUnit from 'qunit'; // Assumed global in runner -var testContext = _dereq_("./test-context")["default"] || _dereq_("./test-context"); - -function resetViews() { - Ember.View.views = {}; -} - -exports["default"] = function test(testName, callback) { - - function wrapper() { - var context = testContext.get(); - resetViews(); - var result = callback.call(context); - - function failTestOnPromiseRejection(reason) { - ok(false, reason); + for (var i = 0, l = length; i < l; i++) { + dep = deps[i]; + if (dep === 'exports') { + exports = reified[i] = seen; + } else { + reified[i] = require(resolve(dep, name)); + } } - Ember.run(function(){ - stop(); - Ember.RSVP.Promise.cast(result)['catch'](failTestOnPromiseRejection)['finally'](start); + return { + deps: reified, + exports: exports + }; + } + + requirejs = require = requireModule = function(name) { + if (state[name] !== FAILED && + seen.hasOwnProperty(name)) { + return seen[name]; + } + + if (!registry[name]) { + throw new Error('Could not find module ' + name); + } + + var mod = registry[name]; + var reified; + var module; + var loaded = false; + + seen[name] = { }; // placeholder for run-time cycles + + try { + reified = reify(mod.deps, name, seen[name]); + module = mod.callback.apply(this, reified.deps); + loaded = true; + } finally { + if (!loaded) { + state[name] = FAILED; + } + } + + return reified.exports ? seen[name] : (seen[name] = module); + }; + + function resolve(child, name) { + if (child.charAt(0) !== '.') { return child; } + + var parts = child.split('/'); + var nameParts = name.split('/'); + var parentBase; + + if (nameParts.length === 1) { + parentBase = nameParts; + } else { + parentBase = nameParts.slice(0, -1); + } + + for (var i = 0, l = parts.length; i < l; i++) { + var part = parts[i]; + + if (part === '..') { parentBase.pop(); } + else if (part === '.') { continue; } + else { parentBase.push(part); } + } + + return parentBase.join('/'); + } + + requirejs.entries = requirejs._eak_seen = registry; + requirejs.clear = function(){ + requirejs.entries = requirejs._eak_seen = registry = {}; + seen = state = {}; + }; +})(); + +define('ember-qunit', ['exports', 'ember-qunit/module-for', 'ember-qunit/module-for-component', 'ember-qunit/module-for-model', 'ember-qunit/test', 'ember-test-helpers'], function (exports, moduleFor, moduleForComponent, moduleForModel, test, ember_test_helpers) { + + 'use strict'; + + + + exports.moduleFor = moduleFor['default']; + exports.moduleForComponent = moduleForComponent['default']; + exports.moduleForModel = moduleForModel['default']; + exports.test = test['default']; + exports.setResolver = ember_test_helpers.setResolver; + +}); +define('ember-qunit/module-for-component', ['exports', 'ember-qunit/qunit-module', 'ember-test-helpers'], function (exports, qunit_module, ember_test_helpers) { + + 'use strict'; + + function moduleForComponent(name, description, callbacks) { + qunit_module.createModule(ember_test_helpers.TestModuleForComponent, name, description, callbacks); + } + exports['default'] = moduleForComponent; + +}); +define('ember-qunit/module-for-model', ['exports', 'ember-qunit/qunit-module', 'ember-test-helpers'], function (exports, qunit_module, ember_test_helpers) { + + 'use strict'; + + function moduleForModel(name, description, callbacks) { + qunit_module.createModule(ember_test_helpers.TestModuleForModel, name, description, callbacks); + } + exports['default'] = moduleForModel; + +}); +define('ember-qunit/module-for', ['exports', 'ember-qunit/qunit-module', 'ember-test-helpers'], function (exports, qunit_module, ember_test_helpers) { + + 'use strict'; + + function moduleFor(name, description, callbacks) { + qunit_module.createModule(ember_test_helpers.TestModule, name, description, callbacks); + } + exports['default'] = moduleFor; + +}); +define('ember-qunit/qunit-module', ['exports', 'qunit'], function (exports, qunit) { + + 'use strict'; + + exports.createModule = createModule; + + function beforeEachCallback(callbacks) { + if (typeof callbacks !== 'object') { return; } + if (!callbacks) { return; } + + var beforeEach; + + if (callbacks.setup) { + beforeEach = callbacks.setup; + delete callbacks.setup; + } + + if (callbacks.beforeEach) { + beforeEach = callbacks.beforeEach; + delete callbacks.beforeEach; + } + + return beforeEach; + } + + function afterEachCallback(callbacks) { + if (typeof callbacks !== 'object') { return; } + if (!callbacks) { return; } + + var afterEach; + + if (callbacks.teardown) { + afterEach = callbacks.teardown; + delete callbacks.teardown; + } + + if (callbacks.afterEach) { + afterEach = callbacks.afterEach; + delete callbacks.afterEach; + } + + return afterEach; + } + + function createModule(Constructor, name, description, callbacks) { + var beforeEach = beforeEachCallback(callbacks || description); + var afterEach = afterEachCallback(callbacks || description); + + var module = new Constructor(name, description, callbacks); + + qunit.module(module.name, { + setup: function(assert) { + var done = assert.async(); + module.setup().then(function() { + if (beforeEach) { + beforeEach.call(module.context, assert); + } + })['finally'](done); + }, + + teardown: function(assert) { + if (afterEach) { + afterEach.call(module.context, assert); + } + var done = assert.async(); + module.teardown()['finally'](done); + } }); } - QUnit.test(testName, wrapper); -} -},{"./test-context":6}]},{},[2]) -(2) }); +define('ember-qunit/test', ['exports', 'ember', 'ember-test-helpers', 'qunit'], function (exports, Ember, ember_test_helpers, qunit) { + + 'use strict'; + + function resetViews() { + Ember['default'].View.views = {}; + } + + function test(testName, callback) { + function wrapper(assert) { + var context = ember_test_helpers.getContext(); + + resetViews(); + var result = callback.call(context, assert); + + function failTestOnPromiseRejection(reason) { + var message; + if (reason instanceof Error) { + message = reason.stack; + } else { + message = Ember['default'].inspect(reason); + } + ok(false, message); + } + + Ember['default'].run(function(){ + QUnit.stop(); + Ember['default'].RSVP.Promise.resolve(result)['catch'](failTestOnPromiseRejection)['finally'](QUnit.start); + }); + } + + qunit.test(testName, wrapper); + } + exports['default'] = test; + +}); +define('ember-test-helpers', ['exports', 'ember', 'ember-test-helpers/isolated-container', 'ember-test-helpers/test-module', 'ember-test-helpers/test-module-for-component', 'ember-test-helpers/test-module-for-model', 'ember-test-helpers/test-context', 'ember-test-helpers/test-resolver'], function (exports, Ember, isolated_container, TestModule, TestModuleForComponent, TestModuleForModel, test_context, test_resolver) { + + 'use strict'; + + Ember['default'].testing = true; + + exports.isolatedContainer = isolated_container.isolatedContainer; + exports.TestModule = TestModule['default']; + exports.TestModuleForComponent = TestModuleForComponent['default']; + exports.TestModuleForModel = TestModuleForModel['default']; + exports.getContext = test_context.getContext; + exports.setContext = test_context.setContext; + exports.setResolver = test_resolver.setResolver; + +}); +define('ember-test-helpers/isolated-container', ['exports', 'ember-test-helpers/test-resolver', 'ember'], function (exports, test_resolver, Ember) { + + 'use strict'; + + exports.isolatedRegistry = isolatedRegistry; + exports.isolatedContainer = isolatedContainer; + + function exposeRegistryMethodsWithoutDeprecations(container) { + var methods = [ + 'register', + 'unregister', + 'resolve', + 'normalize', + 'typeInjection', + 'injection', + 'factoryInjection', + 'factoryTypeInjection', + 'has', + 'options', + 'optionsForType' + ]; + + function exposeRegistryMethod(container, method) { + container[method] = function() { + return container._registry[method].apply(container._registry, arguments); + }; + } + + for (var i = 0, l = methods.length; i < l; i++) { + exposeRegistryMethod(container, methods[i]); + } + } + + function isolatedRegistry(fullNames) { + var resolver = test_resolver.getResolver(); + var container; + var registry; + + var normalize = function(fullName) { + return resolver.normalize(fullName); + }; + + if (Ember['default'].Registry) { + registry = new Ember['default'].Registry(); + registry.normalizeFullName = normalize; + + container = registry.container(); + exposeRegistryMethodsWithoutDeprecations(container); + + } else { + container = new Ember['default'].Container(); + + //normalizeFullName only exists since Ember 1.9 + if (Ember['default'].typeOf(container.normalizeFullName) === 'function') { + container.normalizeFullName = normalize; + } else { + container.normalize = normalize; + } + } + + container.optionsForType('component', { singleton: false }); + container.optionsForType('view', { singleton: false }); + container.optionsForType('template', { instantiate: false }); + container.optionsForType('helper', { instantiate: false }); + container.register('component-lookup:main', Ember['default'].ComponentLookup); + container.register('controller:basic', Ember['default'].Controller, { instantiate: false }); + container.register('controller:object', Ember['default'].ObjectController, { instantiate: false }); + container.register('controller:array', Ember['default'].ArrayController, { instantiate: false }); + container.register('view:default', Ember['default']._MetamorphView); + container.register('view:toplevel', Ember['default'].View.extend()); + container.register('view:select', Ember['default'].Select); + container.register('route:basic', Ember['default'].Route, { instantiate: false }); + + // added in Glimmer + container.register('component:-link-to', Ember['default'].LinkView); + container.register('component:-text-field', Ember['default'].TextField); + container.register('component:-text-area', Ember['default'].TextArea); + container.register('component:-checkbox', Ember['default'].Checkbox); + + if (Ember['default']._LegacyEachView) { + container.register('view:-legacy-each', Ember['default']._LegacyEachView); + } + + var globalContext = typeof global === 'object' && global || self; + if (globalContext.DS) { + var DS = globalContext.DS; + if (DS._setupContainer) { + DS._setupContainer(container); + } else { + container.register('transform:boolean', DS.BooleanTransform); + container.register('transform:date', DS.DateTransform); + container.register('transform:number', DS.NumberTransform); + container.register('transform:string', DS.StringTransform); + container.register('serializer:-default', DS.JSONSerializer); + container.register('serializer:-rest', DS.RESTSerializer); + container.register('adapter:-rest', DS.RESTAdapter); + } + } + + for (var i = fullNames.length; i > 0; i--) { + var fullName = fullNames[i - 1]; + var normalizedFullName = resolver.normalize(fullName); + container.register(fullName, resolver.resolve(normalizedFullName)); + } + return { + container: container, + registry: registry + }; + } + + function isolatedContainer(fullNames) { + return isolatedRegistry(fullNames).container; + } + +}); +define('ember-test-helpers/test-context', ['exports'], function (exports) { + + 'use strict'; + + exports.setContext = setContext; + exports.getContext = getContext; + + var __test_context__; + + function setContext(context) { + __test_context__ = context; + } + + function getContext() { + return __test_context__; + } + +}); +define('ember-test-helpers/test-module-for-component', ['exports', 'ember-test-helpers/test-module', 'ember', 'ember-test-helpers/test-resolver'], function (exports, TestModule, Ember, test_resolver) { + + 'use strict'; + + exports['default'] = TestModule['default'].extend({ + init: function(componentName, description, callbacks) { + // Allow `description` to be omitted + if (!callbacks && typeof description === 'object') { + callbacks = description || {}; + description = null; + } + + this.componentName = componentName; + + if (callbacks.needs || callbacks.unit || callbacks.integration === false) { + this.isUnitTest = true; + } else if (callbacks.integration) { + this.isUnitTest = false; + } else { + Ember['default'].deprecate("the component:" + componentName + " test module is implicitly running in unit test mode, which will change to integration test mode by default in an upcoming version of ember-test-helpers. Add `unit: true` or a `needs:[]` list to explicitly opt in to unit test mode."); + this.isUnitTest = true; + } + + if (!this.isUnitTest) { + callbacks.integration = true; + } + + if (description) { + this._super.call(this, 'component:' + componentName, description, callbacks); + } else { + this._super.call(this, 'component:' + componentName, callbacks); + } + + if (this.isUnitTest) { + this.setupSteps.push(this.setupComponentUnitTest); + } else { + this.callbacks.subject = function() { + throw new Error("component integration tests do not support `subject()`."); + }; + this.setupSteps.push(this.setupComponentIntegrationTest); + this.teardownSteps.push(this.teardownComponent); + } + }, + + setupComponentUnitTest: function() { + var _this = this; + var resolver = test_resolver.getResolver(); + var container = this.container; + var context = this.context; + + var layoutName = 'template:components/' + this.componentName; + + var layout = resolver.resolve(layoutName); + + if (layout) { + container.register(layoutName, layout); + container.injection(this.subjectName, 'layout', layoutName); + } + + context.dispatcher = Ember['default'].EventDispatcher.create(); + context.dispatcher.setup({}, '#ember-testing'); + + this.callbacks.render = function() { + var containerView = Ember['default'].ContainerView.create({container: container}); + Ember['default'].run(function(){ + var subject = context.subject(); + containerView.pushObject(subject); + containerView.appendTo('#ember-testing'); + }); + + _this.teardownSteps.unshift(function() { + Ember['default'].run(function() { + Ember['default'].tryInvoke(containerView, 'destroy'); + }); + }); + }; + + this.callbacks.append = function() { + Ember['default'].deprecate('this.append() is deprecated. Please use this.render() or this.$() instead.'); + return context.$(); + }; + + context.$ = function() { + this.render(); + var subject = this.subject(); + + return subject.$.apply(subject, arguments); + }; + }, + + setupComponentIntegrationTest: function() { + var self = this; + var context = this.context; + context.dispatcher = Ember['default'].EventDispatcher.create(); + context.dispatcher.setup({}, '#ember-testing'); + this.actionHooks = {}; + + context.render = function(template) { + if (!template) { + throw new Error("in a component integration test you must pass a template to `render()`"); + } + if (Ember['default'].isArray(template)) { + template = template.join(''); + } + if (typeof template === 'string') { + template = Ember['default'].Handlebars.compile(template); + } + self.component = Ember['default'].View.create({ + context: context, + controller: self, + template: template, + container: self.container + }); + Ember['default'].run(function() { + self.component.appendTo('#ember-testing'); + }); + }; + + context.$ = function() { + return self.component.$.apply(self.component, arguments); + }; + + context.set = function(key, value) { + Ember['default'].run(function() { + Ember['default'].set(context, key, value); + }); + }; + + context.get = function(key) { + return Ember['default'].get(context, key); + }; + + context.on = function(actionName, handler) { + self.actionHooks[actionName] = handler; + }; + + }, + + setupContext: function() { + this._super.call(this); + if (!this.isUnitTest) { + this.context.factory = function() {}; + } + }, + + + send: function(actionName) { + var hook = this.actionHooks[actionName]; + if (!hook) { + throw new Error("integration testing template received unexpected action " + actionName); + } + hook.apply(this, Array.prototype.slice.call(arguments, 1)); + }, + + teardownComponent: function() { + var component = this.component; + if (component) { + Ember['default'].run(function() { + component.destroy(); + }); + } + } + + + }); + +}); +define('ember-test-helpers/test-module-for-model', ['exports', 'ember-test-helpers/test-module', 'ember'], function (exports, TestModule, Ember) { + + 'use strict'; + + exports['default'] = TestModule['default'].extend({ + init: function(modelName, description, callbacks) { + this.modelName = modelName; + + this._super.call(this, 'model:' + modelName, description, callbacks); + + this.setupSteps.push(this.setupModel); + }, + + setupModel: function() { + var container = this.container; + var defaultSubject = this.defaultSubject; + var callbacks = this.callbacks; + var modelName = this.modelName; + + var adapterFactory = container.lookupFactory('adapter:application'); + if (!adapterFactory) { + container.register('adapter:application', DS.FixtureAdapter); + } + + callbacks.store = function(){ + var container = this.container; + + return container.lookup('store:main'); + }; + + if (callbacks.subject === defaultSubject) { + callbacks.subject = function(options) { + var container = this.container; + + return Ember['default'].run(function() { + return container.lookup('store:main').createRecord(modelName, options); + }); + }; + } + } + }); + +}); +define('ember-test-helpers/test-module', ['exports', 'ember', 'ember-test-helpers/isolated-container', 'ember-test-helpers/test-context', 'klassy', 'ember-test-helpers/test-resolver'], function (exports, Ember, isolated_container, test_context, klassy, test_resolver) { + + 'use strict'; + + exports['default'] = klassy.Klass.extend({ + init: function(subjectName, description, callbacks) { + // Allow `description` to be omitted, in which case it should + // default to `subjectName` + if (!callbacks && typeof description === 'object') { + callbacks = description; + description = subjectName; + } + + this.subjectName = subjectName; + this.description = description || subjectName; + this.name = description || subjectName; + this.callbacks = callbacks || {}; + + if (this.callbacks.integration) { + this.isIntegration = callbacks.integration; + delete callbacks.integration; + } + + this.initSubject(); + this.initNeeds(); + this.initSetupSteps(); + this.initTeardownSteps(); + }, + + initSubject: function() { + this.callbacks.subject = this.callbacks.subject || this.defaultSubject; + }, + + initNeeds: function() { + this.needs = [this.subjectName]; + if (this.callbacks.needs) { + this.needs = this.needs.concat(this.callbacks.needs) + delete this.callbacks.needs; + } + }, + + initSetupSteps: function() { + this.setupSteps = []; + this.contextualizedSetupSteps = []; + + if (this.callbacks.beforeSetup) { + this.setupSteps.push( this.callbacks.beforeSetup ); + delete this.callbacks.beforeSetup; + } + + this.setupSteps.push(this.setupContainer); + this.setupSteps.push(this.setupContext); + this.setupSteps.push(this.setupTestElements); + + if (this.callbacks.setup) { + this.contextualizedSetupSteps.push( this.callbacks.setup ); + delete this.callbacks.setup; + } + }, + + initTeardownSteps: function() { + this.teardownSteps = []; + this.contextualizedTeardownSteps = []; + + if (this.callbacks.teardown) { + this.contextualizedTeardownSteps.push( this.callbacks.teardown ); + delete this.callbacks.teardown; + } + + this.teardownSteps.push(this.teardownSubject); + this.teardownSteps.push(this.teardownContainer); + this.teardownSteps.push(this.teardownContext); + this.teardownSteps.push(this.teardownTestElements); + + if (this.callbacks.afterTeardown) { + this.teardownSteps.push( this.callbacks.afterTeardown ); + delete this.callbacks.afterTeardown; + } + }, + + setup: function() { + var self = this; + return self.invokeSteps(self.setupSteps).then(function() { + self.contextualizeCallbacks(); + return self.invokeSteps(self.contextualizedSetupSteps, self.context); + }); + }, + + teardown: function() { + var self = this; + return self.invokeSteps(self.contextualizedTeardownSteps, self.context).then(function() { + return self.invokeSteps(self.teardownSteps); + }).then(function() { + self.cache = null; + self.cachedCalls = null; + }); + }, + + invokeSteps: function(steps, _context) { + var context = _context; + if (!context) { + context = this; + } + steps = steps.slice(); + function nextStep() { + var step = steps.shift(); + if (step) { + return Ember['default'].RSVP.resolve(step.call(context)).then(nextStep); + } else { + return Ember['default'].RSVP.resolve(); + } + } + return nextStep(); + }, + + setupContainer: function() { + if (this.isIntegration) { + this._setupIntegratedContainer(); + } else { + this._setupIsolatedContainer(); + } + }, + + setupContext: function() { + var subjectName = this.subjectName; + var container = this.container; + + var factory = function() { + return container.lookupFactory(subjectName); + }; + + test_context.setContext({ + container: this.container, + registry: this.registry, + factory: factory, + dispatcher: null + }); + + this.context = test_context.getContext(); + }, + + setupTestElements: function() { + if (Ember['default'].$('#ember-testing').length === 0) { + Ember['default'].$('
').appendTo(document.body); + } + }, + + teardownSubject: function() { + var subject = this.cache.subject; + + if (subject) { + Ember['default'].run(function() { + Ember['default'].tryInvoke(subject, 'destroy'); + }); + } + }, + + teardownContainer: function() { + var container = this.container; + Ember['default'].run(function() { + container.destroy(); + }); + }, + + teardownContext: function() { + var context = this.context; + if (context.dispatcher) { + Ember['default'].run(function() { + context.dispatcher.destroy(); + }); + } + }, + + teardownTestElements: function() { + Ember['default'].$('#ember-testing').empty(); + Ember['default'].View.views = {}; + }, + + defaultSubject: function(options, factory) { + return factory.create(options); + }, + + // allow arbitrary named factories, like rspec let + contextualizeCallbacks: function() { + var _this = this; + var callbacks = this.callbacks; + var context = this.context; + var factory = context.factory; + + this.cache = this.cache || {}; + this.cachedCalls = this.cachedCalls || {}; + + var keys = Ember['default'].keys(callbacks); + + for (var i = 0, l = keys.length; i < l; i++) { + (function(key) { + + context[key] = function(options) { + if (_this.cachedCalls[key]) { return _this.cache[key]; } + + var result = callbacks[key].call(_this, options, factory()); + + _this.cache[key] = result; + _this.cachedCalls[key] = true; + + return result; + }; + + })(keys[i]); + } + }, + + + _setupIsolatedContainer: function() { + var isolated = isolated_container.isolatedRegistry(this.needs); + this.container = isolated.container; + this.registry = isolated.registry; + }, + + _setupIntegratedContainer: function() { + var resolver = test_resolver.getResolver(); + var namespace = Ember['default'].Object.create({ + Resolver: { create: function() { return resolver; } } + }); + + if (Ember['default'].Application.buildRegistry) { + var registry; + registry = Ember['default'].Application.buildRegistry(namespace); + registry.register('component-lookup:main', Ember['default'].ComponentLookup); + this.registry = registry; + this.container = registry.container(); + } else { + this.container = Ember['default'].Application.buildContainer(namespace); + this.container.register('component-lookup:main', Ember['default'].ComponentLookup); + } + } + + }); + +}); +define('ember-test-helpers/test-resolver', ['exports'], function (exports) { + + 'use strict'; + + exports.setResolver = setResolver; + exports.getResolver = getResolver; + + var __resolver__; + + function setResolver(resolver) { + __resolver__ = resolver; + } + + function getResolver() { + if (__resolver__ == null) throw new Error('you must set a resolver with `testResolver.set(resolver)`'); + return __resolver__; + } + +}); +define('klassy', ['exports'], function (exports) { + + 'use strict'; + + /** + Extend a class with the properties and methods of one or more other classes. + + When a method is replaced with another method, it will be wrapped in a + function that makes the replaced method accessible via `this._super`. + + @method extendClass + @param {Object} destination The class to merge into + @param {Object} source One or more source classes + */ + var extendClass = function(destination) { + var sources = Array.prototype.slice.call(arguments, 1); + var source; + + for (var i = 0, l = sources.length; i < l; i++) { + source = sources[i]; + + for (var p in source) { + if (source.hasOwnProperty(p) && + destination[p] && + typeof destination[p] === 'function' && + typeof source[p] === 'function') { + + /* jshint loopfunc:true */ + destination[p] = + (function(destinationFn, sourceFn) { + var wrapper = function() { + var prevSuper = this._super; + this._super = destinationFn; + + var ret = sourceFn.apply(this, arguments); + + this._super = prevSuper; + + return ret; + }; + wrapper.wrappedFunction = sourceFn; + return wrapper; + })(destination[p], source[p]); + + } else { + destination[p] = source[p]; + } + } + } + }; + + // `subclassing` is a state flag used by `defineClass` to track when a class is + // being subclassed. It allows constructors to avoid calling `init`, which can + // be expensive and cause undesirable side effects. + var subclassing = false; + + /** + Define a new class with the properties and methods of one or more other classes. + + The new class can be based on a `SuperClass`, which will be inserted into its + prototype chain. + + Furthermore, one or more mixins (object that contain properties and/or methods) + may be specified, which will be applied in order. When a method is replaced + with another method, it will be wrapped in a function that makes the previous + method accessible via `this._super`. + + @method defineClass + @param {Object} SuperClass A base class to extend. If `mixins` are to be included + without a `SuperClass`, pass `null` for SuperClass. + @param {Object} mixins One or more objects that contain properties and methods + to apply to the new class. + */ + var defineClass = function(SuperClass) { + var Klass = function() { + if (!subclassing && this.init) { + this.init.apply(this, arguments); + } + }; + + if (SuperClass) { + subclassing = true; + Klass.prototype = new SuperClass(); + subclassing = false; + } + + if (arguments.length > 1) { + var extendArgs = Array.prototype.slice.call(arguments, 1); + extendArgs.unshift(Klass.prototype); + extendClass.apply(Klass.prototype, extendArgs); + } + + Klass.constructor = Klass; + + Klass.extend = function() { + var args = Array.prototype.slice.call(arguments, 0); + args.unshift(Klass); + return defineClass.apply(Klass, args); + }; + + return Klass; + }; + + /** + A base class that can be extended. + + @example + + ```javascript + var CelestialObject = Klass.extend({ + init: function(name) { + this._super(); + this.name = name; + this.isCelestialObject = true; + }, + greeting: function() { + return 'Hello from ' + this.name; + } + }); + + var Planet = CelestialObject.extend({ + init: function(name) { + this._super.apply(this, arguments); + this.isPlanet = true; + }, + greeting: function() { + return this._super() + '!'; + }, + }); + + var earth = new Planet('Earth'); + + console.log(earth instanceof Klass); // true + console.log(earth instanceof CelestialObject); // true + console.log(earth instanceof Planet); // true + + console.log(earth.isCelestialObject); // true + console.log(earth.isPlanet); // true + + console.log(earth.greeting()); // 'Hello from Earth!' + ``` + + @class Klass + */ + var Klass = defineClass(null, { + init: function() {} + }); + + exports.Klass = Klass; + exports.defineClass = defineClass; + exports.extendClass = extendClass; + +}); +define('qunit', ['exports'], function (exports) { + + 'use strict'; + + /* globals test:true */ + + var module = QUnit.module; + var test = QUnit.test; + var skip = QUnit.skip; + + exports['default'] = QUnit; + + exports.module = module; + exports.test = test; + exports.skip = skip; + +}); +define("ember", ["exports"], function(__exports__) { + __exports__["default"] = window.Ember; +}); + +var emberQunit = requireModule("ember-qunit"); + +window.moduleFor = emberQunit.moduleFor; +window.moduleForComponent = emberQunit.moduleForComponent; +window.moduleForModel = emberQunit.moduleForModel; +window.test = emberQunit.test; +window.setResolver = emberQunit.setResolver; + +})(); diff --git a/vendor/assets/javascripts/sinon-qunit-1.0.0.js b/vendor/assets/javascripts/sinon-qunit-1.0.0.js index 391ab70ebb1..35efda489b6 100644 --- a/vendor/assets/javascripts/sinon-qunit-1.0.0.js +++ b/vendor/assets/javascripts/sinon-qunit-1.0.0.js @@ -41,21 +41,9 @@ sinon.assert.pass = function (assertion) { }; sinon.config = { - injectIntoThis: true, + injectIntoThis: false, injectInto: null, properties: ["spy", "stub", "mock", "clock", "sandbox"], useFakeTimers: true, useFakeServer: false }; - -(function (global) { - var qTest = QUnit.test; - - QUnit.test = global.test = function (testName, expected, callback, async) { - if (arguments.length === 2) { - callback = expected; - expected = null; - } - return qTest(testName, expected, sinon.test(callback), async); - }; -}(this));