diff --git a/lib/canvas/require_js.rb b/lib/canvas/require_js.rb index dd6e1ad945c..2214cac0729 100644 --- a/lib/canvas/require_js.rb +++ b/lib/canvas/require_js.rb @@ -64,7 +64,8 @@ module Canvas :use => 'vendor/use', :uploadify => '../flash/uploadify/jquery.uploadify-3.1.min', 'ic-menu' => 'vendor/ic-menu/dist/main.amd', - 'ic-dialog' => 'vendor/ic-dialog/dist/main.amd.js', + 'ic-dialog' => 'vendor/ic-dialog/dist/main.amd', + 'ic-ajax' => 'vendor/ic-ajax/main', }.update(cache_busting ? cache_busting_paths : {}).update(plugin_paths).update(Canvas::RequireJs::PluginExtension.paths).to_json.gsub(/([,{])/, "\\1\n ") end diff --git a/loom/generators/app.js b/loom/generators/app.js index 33383f3e9f3..df9a5adcc8d 100644 --- a/loom/generators/app.js +++ b/loom/generators/app.js @@ -18,7 +18,8 @@ exports.templates = [ 'new_app/config/app.coffee.hbs', 'new_app/config/routes.coffee.hbs', 'new_app/templates/application.hbs.hbs', - 'new_app/tests/app.coffee.hbs', + 'new_app/routes/route.coffee.hbs', + 'new_app/tests/start_app.coffee.hbs', 'new_app/tests/app.spec.coffee.hbs' ]; @@ -28,7 +29,8 @@ exports.savePath = function(template, env) { 'new_app/config/app.coffee.hbs': 'app/coffeescripts/ember/'+env.appName+'/config/app.coffee', 'new_app/config/routes.coffee.hbs': 'app/coffeescripts/ember/'+env.appName+'/config/routes.coffee', 'new_app/templates/application.hbs.hbs': 'app/coffeescripts/ember/'+env.appName+'/templates/'+env.appName+'.hbs', - 'new_app/tests/app.coffee.hbs': 'app/coffeescripts/ember/'+env.appName+'/tests/app.coffee', + 'new_app/routes/route.coffee.hbs': 'app/coffeescripts/ember/'+env.appName+'/routes/'+env.appName+'_route.coffee', + 'new_app/tests/start_app.coffee.hbs': 'app/coffeescripts/ember/'+env.appName+'/tests/start_app.coffee', 'new_app/tests/app.spec.coffee.hbs': 'app/coffeescripts/ember/'+env.appName+'/tests/app.spec.coffee' }[template]; }; diff --git a/loom/templates/new_app/routes/route.coffee.hbs b/loom/templates/new_app/routes/route.coffee.hbs new file mode 100644 index 00000000000..cf96c93c156 --- /dev/null +++ b/loom/templates/new_app/routes/route.coffee.hbs @@ -0,0 +1,8 @@ +define ['ember', 'ic-ajax'], (Ember, ajax) -> + + FakeRoute = Ember.Route.extend + + model: -> + ajax('/api/v1/users/self/activity_stream').then ({response}) -> + response + diff --git a/loom/templates/new_app/templates/application.hbs.hbs b/loom/templates/new_app/templates/application.hbs.hbs index baff3443ef3..a19e5d32448 100644 --- a/loom/templates/new_app/templates/application.hbs.hbs +++ b/loom/templates/new_app/templates/application.hbs.hbs @@ -1,2 +1,9 @@

HELLO!

+ + + diff --git a/loom/templates/new_app/tests/app.coffee.hbs b/loom/templates/new_app/tests/app.coffee.hbs deleted file mode 100644 index 71a0fcd1f7d..00000000000 --- a/loom/templates/new_app/tests/app.coffee.hbs +++ /dev/null @@ -1,14 +0,0 @@ -define ['../main'], (Application) -> - App = Application.create - LOG_ACTIVE_GENERATION: yes - LOG_MODULE_RESOLVER: yes - LOG_TRANSITIONS: yes - LOG_TRANSITIONS_INTERNAL: yes - LOG_VIEW_LOOKUPS: yes - rootElement: '#fixtures' - history: 'none' - App.setupForTesting() - App.injectTestHelpers() - App.advanceReadiness() - App - diff --git a/loom/templates/new_app/tests/app.spec.coffee.hbs b/loom/templates/new_app/tests/app.spec.coffee.hbs index fc9f665362b..a080b6fd313 100644 --- a/loom/templates/new_app/tests/app.spec.coffee.hbs +++ b/loom/templates/new_app/tests/app.spec.coffee.hbs @@ -1,11 +1,28 @@ -define ['./app', 'ember'], (App, Ember) -> +define [ + './start_app' + 'ember' + 'ic-ajax' +], (startApp, Ember, ajax) -> - module '{{appName}}', -> + App = null + + ajax.defineFixture '/api/v1/users/self/activity_stream', + response: [ + {title: 'foo'} + {title: 'bar'} + ] + jqXHR: {} + textStatus: '' + + module '{{appName}}', setup: -> - App.reset() - Ember.run(App, App.advanceReadiness) + App = startApp() + teardown: -> + Ember.run App, 'destroy' - test 'says hello', -> - visit('/').then -> - equal(find('h1').html().trim(), 'HELLO!') + test 'fetches and renders stream items', -> + controller = App.__container__.lookup('controller:{{appName}}') + equal controller.objectAt(0).title, 'foo' + equal controller.objectAt(1).title, 'bar' + equal find('h1').html().trim(), 'HELLO!' diff --git a/loom/templates/new_app/tests/start_app.coffee.hbs b/loom/templates/new_app/tests/start_app.coffee.hbs new file mode 100644 index 00000000000..6e038bbb03d --- /dev/null +++ b/loom/templates/new_app/tests/start_app.coffee.hbs @@ -0,0 +1,19 @@ +define ['../main'], (Application) -> + startApp = -> + App = null + Ember.run.join -> + App = Application.create + LOG_ACTIVE_GENERATION: yes + LOG_MODULE_RESOLVER: yes + LOG_TRANSITIONS: yes + LOG_TRANSITIONS_INTERNAL: yes + LOG_VIEW_LOOKUPS: yes + rootElement: '#fixtures' + App.Router.reopen history: 'none' + App.setupForTesting() + App.injectTestHelpers() + App.advanceReadiness() + window.App = App + App + + diff --git a/public/javascripts/vendor/ic-ajax/main.js b/public/javascripts/vendor/ic-ajax/main.js new file mode 100644 index 00000000000..6358527c7ca --- /dev/null +++ b/public/javascripts/vendor/ic-ajax/main.js @@ -0,0 +1,114 @@ +/*! + * ic-ajax + * + * - please see license at https://github.com/instructure/ember-ajax + * - inspired by discourse ajax: https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/mixins/ajax.js#L19 + */ + +;(function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(['ember'], function(Ember) { return factory(Ember); }); + } else if (typeof exports === 'object') { + module.exports = factory(require('ember')); + } else { + root.ic = root.ic || {}; + root.ic.ajax = factory(Ember); + } +}(this, function(Ember) { + + /* + * jQuery.ajax wrapper, supports the same signature except providing + * `success` and `error` handlers will throw an error (use promises + * instead). + */ + + var ajax = function() { + return makePromise(parseArgs.apply(null, arguments)); + }; + + /* + * Defines a fixture that will be used instead of an actual ajax + * request to a given url. This is useful for testing, allowing you to + * stub out responses your application will send without requiring + * libraries like sinon or mockjax, etc. + * + * For example: + * + * ajax.defineFixture('/self', { + * response: { firstName: 'Ryan', lastName: 'Florence' }, + * textStatus: 'success' + * jqXHR: {} + * }); + * + * @param {String} url + * @param {Object} fixture + */ + ajax.defineFixture = function(url, fixture) { + ajax.FIXTURES = ajax.FIXTURES || {}; + ajax.FIXTURES[url] = fixture; + }; + + /* + * Looks up a fixture by url. + * + * @param {String} url + */ + + ajax.lookupFixture = function(url) { + return ajax.FIXTURES && ajax.FIXTURES[url]; + }; + + function makePromise(settings) { + return new Ember.RSVP.Promise(function(resolve, reject) { + var fixture = ajax.lookupFixture(settings.url); + if (fixture) { + return resolve(fixture); + } + settings.success = makeSuccess(resolve, reject); + settings.error = makeError(resolve, reject); + Ember.$.ajax(settings); + }); + }; + + function parseArgs() { + var settings = {}; + if (arguments.length === 1) { + if (typeof arguments[0] === "string") { + settings.url = arguments[0]; + } else { + settings = arguments[0]; + } + } else if (arguments.length === 2) { + settings = arguments[1]; + settings.url = arguments[0]; + } + if (settings.success || settings.error) { + throw new Error("ajax should use promises, received 'success' or 'error' callback"); + } + return settings; + } + + function makeSuccess(resolve, reject) { + return function(response, textStatus, jqXHR) { + Ember.run(null, resolve, { + response: response, + textStatus: textStatus, + jqXHR: jqXHR + }); + } + } + + function makeError(resolve, reject) { + return function(jqXHR, textStatus, errorThrown) { + Ember.run(null, reject, { + jqXHR: jqXHR, + textStatus: textStatus, + errorThrown: errorThrown + }); + }; + } + + return ajax; + +})); +