From 0471ad393c6e61630bf044802d85a1583711e79d Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Wed, 24 Aug 2016 14:35:07 -0400 Subject: [PATCH] Scaffold for new Wizard - Rails / Ember / Tests --- app/assets/javascripts/discourse-objects.js | 2 + app/assets/javascripts/env.js | 5 --- app/assets/javascripts/vendor.js | 1 + app/assets/javascripts/wizard-application.js | 6 +++ app/assets/javascripts/wizard-vendor.js | 2 + .../wizard/controllers/step.js.es6 | 3 ++ app/assets/javascripts/wizard/resolver.js.es6 | 26 ++++++++++++ app/assets/javascripts/wizard/router.js.es6 | 7 +++ .../javascripts/wizard/routes/index.js.es6 | 5 +++ .../javascripts/wizard/routes/step.js.es6 | 12 ++++++ .../wizard/templates/application.hbs | 7 +++ .../javascripts/wizard/templates/step.hbs | 3 ++ .../wizard/test/acceptance/wizard-test.js.es6 | 10 +++++ .../javascripts/wizard/test/test_helper.js | 40 ++++++++++++++++++ app/assets/javascripts/wizard/wizard.js.es6 | 8 ++++ app/assets/stylesheets/wizard.scss | 31 ++++++++++++++ app/controllers/wizard/wizard_controller.rb | 16 +++++++ app/views/wizard/wizard/index.html.erb | 21 +++++++++ app/views/wizard/wizard/qunit.html.erb | 15 +++++++ config/application.rb | 3 +- config/routes.rb | 5 +++ public/images/wizard/bubbles.png | Bin 0 -> 29250 bytes .../wizard/wizard_controller_spec.rb | 25 +++++++++++ 23 files changed, 247 insertions(+), 6 deletions(-) create mode 100644 app/assets/javascripts/discourse-objects.js create mode 100644 app/assets/javascripts/wizard-application.js create mode 100644 app/assets/javascripts/wizard-vendor.js create mode 100644 app/assets/javascripts/wizard/controllers/step.js.es6 create mode 100644 app/assets/javascripts/wizard/resolver.js.es6 create mode 100644 app/assets/javascripts/wizard/router.js.es6 create mode 100644 app/assets/javascripts/wizard/routes/index.js.es6 create mode 100644 app/assets/javascripts/wizard/routes/step.js.es6 create mode 100644 app/assets/javascripts/wizard/templates/application.hbs create mode 100644 app/assets/javascripts/wizard/templates/step.hbs create mode 100644 app/assets/javascripts/wizard/test/acceptance/wizard-test.js.es6 create mode 100644 app/assets/javascripts/wizard/test/test_helper.js create mode 100644 app/assets/javascripts/wizard/wizard.js.es6 create mode 100644 app/assets/stylesheets/wizard.scss create mode 100644 app/controllers/wizard/wizard_controller.rb create mode 100644 app/views/wizard/wizard/index.html.erb create mode 100644 app/views/wizard/wizard/qunit.html.erb create mode 100644 public/images/wizard/bubbles.png create mode 100644 spec/controllers/wizard/wizard_controller_spec.rb diff --git a/app/assets/javascripts/discourse-objects.js b/app/assets/javascripts/discourse-objects.js new file mode 100644 index 00000000000..d55626ef029 --- /dev/null +++ b/app/assets/javascripts/discourse-objects.js @@ -0,0 +1,2 @@ +window.Discourse = {}; +Discourse.SiteSettings = {}; diff --git a/app/assets/javascripts/env.js b/app/assets/javascripts/env.js index 5537a6c10bc..d5fe8823609 100644 --- a/app/assets/javascripts/env.js +++ b/app/assets/javascripts/env.js @@ -1,8 +1,3 @@ window.ENV = { }; - -window.Discourse = {}; -Discourse.SiteSettings = {}; - window.EmberENV = window.EmberENV || {}; window.EmberENV['FORCE_JQUERY'] = true; - diff --git a/app/assets/javascripts/vendor.js b/app/assets/javascripts/vendor.js index a6a8c814290..22624ed0089 100644 --- a/app/assets/javascripts/vendor.js +++ b/app/assets/javascripts/vendor.js @@ -1,5 +1,6 @@ //= require logster //= require ./env +//= require ./discourse-objects //= require probes.js //= require template_include.js diff --git a/app/assets/javascripts/wizard-application.js b/app/assets/javascripts/wizard-application.js new file mode 100644 index 00000000000..1d77f9dfa57 --- /dev/null +++ b/app/assets/javascripts/wizard-application.js @@ -0,0 +1,6 @@ +//= require wizard/resolver +//= require wizard/router +//= require wizard/wizard +//= require_tree ./wizard/templates +//= require_tree ./wizard/routes +//= require_tree ./wizard/controllers diff --git a/app/assets/javascripts/wizard-vendor.js b/app/assets/javascripts/wizard-vendor.js new file mode 100644 index 00000000000..cb06474666c --- /dev/null +++ b/app/assets/javascripts/wizard-vendor.js @@ -0,0 +1,2 @@ +//= require env +//= require template_include.js diff --git a/app/assets/javascripts/wizard/controllers/step.js.es6 b/app/assets/javascripts/wizard/controllers/step.js.es6 new file mode 100644 index 00000000000..bc7c7b20bd5 --- /dev/null +++ b/app/assets/javascripts/wizard/controllers/step.js.es6 @@ -0,0 +1,3 @@ +export default Ember.Controller.extend({ + step: null, +}); diff --git a/app/assets/javascripts/wizard/resolver.js.es6 b/app/assets/javascripts/wizard/resolver.js.es6 new file mode 100644 index 00000000000..c89bfa593bf --- /dev/null +++ b/app/assets/javascripts/wizard/resolver.js.es6 @@ -0,0 +1,26 @@ +function resolveType(parsedName) { + const entries = requirejs.entries; + + const named = `wizard/${parsedName.type}s/${parsedName.fullNameWithoutType}`; + if (entries[named]) { + const module = require(named, null, null, true /* force sync */); + return module.default; + } +} + +export default Ember.DefaultResolver.extend({ + + resolveRoute(parsedName) { + return resolveType(parsedName) || this._super(parsedName); + }, + + resolveController(parsedName) { + return resolveType(parsedName) || this._super(parsedName); + }, + + resolveTemplate(parsedName) { + const templates = Ember.TEMPLATES; + const withoutType = parsedName.fullNameWithoutType; + return templates[`wizard/templates/${withoutType}`] || this._super(parsedName); + } +}); diff --git a/app/assets/javascripts/wizard/router.js.es6 b/app/assets/javascripts/wizard/router.js.es6 new file mode 100644 index 00000000000..d110766f83f --- /dev/null +++ b/app/assets/javascripts/wizard/router.js.es6 @@ -0,0 +1,7 @@ +const Router = Ember.Router.extend(); + +Router.map(function () { + this.route('step', { path: '/step/:step_id' }); +}); + +export default Router; diff --git a/app/assets/javascripts/wizard/routes/index.js.es6 b/app/assets/javascripts/wizard/routes/index.js.es6 new file mode 100644 index 00000000000..2587b35d811 --- /dev/null +++ b/app/assets/javascripts/wizard/routes/index.js.es6 @@ -0,0 +1,5 @@ +export default Ember.Route.extend({ + beforeModel() { + this.replaceWith('step', 'welcome'); + } +}); diff --git a/app/assets/javascripts/wizard/routes/step.js.es6 b/app/assets/javascripts/wizard/routes/step.js.es6 new file mode 100644 index 00000000000..4de6d180e5d --- /dev/null +++ b/app/assets/javascripts/wizard/routes/step.js.es6 @@ -0,0 +1,12 @@ +export default Ember.Route.extend({ + model(params) { + return { + id: params.step_id, + title: "You're a wizard harry!" + }; + }, + + setupController(controller, model) { + controller.set('step', model); + } +}); diff --git a/app/assets/javascripts/wizard/templates/application.hbs b/app/assets/javascripts/wizard/templates/application.hbs new file mode 100644 index 00000000000..52416fc45ab --- /dev/null +++ b/app/assets/javascripts/wizard/templates/application.hbs @@ -0,0 +1,7 @@ +
+
+ Discourse! + + {{outlet}} +
+
diff --git a/app/assets/javascripts/wizard/templates/step.hbs b/app/assets/javascripts/wizard/templates/step.hbs new file mode 100644 index 00000000000..c8e09a81fb1 --- /dev/null +++ b/app/assets/javascripts/wizard/templates/step.hbs @@ -0,0 +1,3 @@ +
+ {{step.title}} +
diff --git a/app/assets/javascripts/wizard/test/acceptance/wizard-test.js.es6 b/app/assets/javascripts/wizard/test/acceptance/wizard-test.js.es6 new file mode 100644 index 00000000000..f166e7b2465 --- /dev/null +++ b/app/assets/javascripts/wizard/test/acceptance/wizard-test.js.es6 @@ -0,0 +1,10 @@ + +module("Acceptance: wizard"); + +test("Wizard loads", assert => { + visit("/"); + andThen(() => { + assert.ok(exists('.wizard-column-contents')); + assert.equal(currentPath(), 'steps'); + }); +}); diff --git a/app/assets/javascripts/wizard/test/test_helper.js b/app/assets/javascripts/wizard/test/test_helper.js new file mode 100644 index 00000000000..529c5e9b83b --- /dev/null +++ b/app/assets/javascripts/wizard/test/test_helper.js @@ -0,0 +1,40 @@ +/*global document, sinon, QUnit, Logster */ + +//= require env +//= require jquery.debug +//= require loader +//= require jquery.debug +//= require handlebars +//= require ember.debug +//= require ember-template-compiler +//= require ember-qunit +//= require wizard-application +//= require helpers/assertions +//= require_tree ./acceptance + +// Trick JSHint into allow document.write +var d = document; +d.write('
'); +d.write(''); + +if (window.Logster) { + Logster.enabled = false; +} else { + window.Logster = { enabled: false }; +} + +var wizard = require('wizard/wizard').default.create({ + rootElement: '#ember-testing' +}); +wizard.setupForTesting(); +wizard.injectTestHelpers(); + +QUnit.testDone(function() { + wizard.reset(); +}); + +Object.keys(requirejs.entries).forEach(function(entry) { + if ((/\-test/).test(entry)) { + require(entry, null, null, true); + } +}); diff --git a/app/assets/javascripts/wizard/wizard.js.es6 b/app/assets/javascripts/wizard/wizard.js.es6 new file mode 100644 index 00000000000..6318fec2ba0 --- /dev/null +++ b/app/assets/javascripts/wizard/wizard.js.es6 @@ -0,0 +1,8 @@ +import Resolver from 'wizard/resolver'; +import Router from 'wizard/router'; + +export default Ember.Application.extend({ + rootElement: '#wizard-main', + Resolver, + Router +}); diff --git a/app/assets/stylesheets/wizard.scss b/app/assets/stylesheets/wizard.scss new file mode 100644 index 00000000000..228b399f55f --- /dev/null +++ b/app/assets/stylesheets/wizard.scss @@ -0,0 +1,31 @@ +@import "vendor/normalize"; +@import "vendor/font_awesome/font-awesome"; + +body { + background-color: rgb(231,238,247); + background-image: url('/images/wizard/bubbles.png'); + background-repeat: repeat; + background-position: left top; +} + +.wizard-column { + background-color: white; + border-radius: 2px; + box-shadow: 0 5px 10px rgba(0,0,0,0.2); + box-sizing: border-box; + margin: 0.75rem auto; + padding: 0; + max-width: 700px; + min-width: 280px; + width: 100%; + border: 1px solid #ccc; + + .wizard-column-contents { + padding: 1em; + + h1 { + margin: 0; + } + } +} + diff --git a/app/controllers/wizard/wizard_controller.rb b/app/controllers/wizard/wizard_controller.rb new file mode 100644 index 00000000000..09e7ae1f95f --- /dev/null +++ b/app/controllers/wizard/wizard_controller.rb @@ -0,0 +1,16 @@ +class Wizard::WizardController < ApplicationController + + before_filter :ensure_logged_in + before_filter :ensure_staff + + skip_before_filter :check_xhr, :preload_json + + layout false + + def index + end + + def qunit + end + +end diff --git a/app/views/wizard/wizard/index.html.erb b/app/views/wizard/wizard/index.html.erb new file mode 100644 index 00000000000..249921a4ee6 --- /dev/null +++ b/app/views/wizard/wizard/index.html.erb @@ -0,0 +1,21 @@ + + + <%= stylesheet_link_tag 'wizard' %> + <%= javascript_include_tag 'wizard-vendor' %> + <%= javascript_include_tag 'ember_jquery' %> + <%= javascript_include_tag 'wizard-application' %> + + + +
+
+ + + + + + diff --git a/app/views/wizard/wizard/qunit.html.erb b/app/views/wizard/wizard/qunit.html.erb new file mode 100644 index 00000000000..814bfb5c918 --- /dev/null +++ b/app/views/wizard/wizard/qunit.html.erb @@ -0,0 +1,15 @@ + + + + QUnit Test Runner + <%= stylesheet_link_tag "qunit" %> + <%= stylesheet_link_tag "test_helper" %> + <%= javascript_include_tag "qunit" %> + <%= javascript_include_tag "wizard/test/test_helper" %> + <%= csrf_meta_tags %> + + +
+
+ + diff --git a/config/application.rb b/config/application.rb index 577d127993a..70d4427f773 100644 --- a/config/application.rb +++ b/config/application.rb @@ -72,7 +72,8 @@ module Discourse config.assets.precompile += ['vendor.js', 'common.css', 'desktop.css', 'mobile.css', 'admin.js', 'admin.css', 'shiny/shiny.css', 'preload-store.js.es6', 'browser-update.js', 'embed.css', 'break_string.js', 'ember_jquery.js', - 'pretty-text-bundle.js'] + 'pretty-text-bundle.js', 'wizard.css', 'wizard-application.js', + 'wizard-vendor.js'] # Precompile all available locales Dir.glob("#{config.root}/app/assets/javascripts/locales/*.js.erb").each do |file| diff --git a/config/routes.rb b/config/routes.rb index 13163611161..4f516da1397 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -53,6 +53,11 @@ Discourse::Application.routes.draw do resources :forums get "srv/status" => "forums#status" + namespace :wizard, constraints: StaffConstraint.new do + get "" => "wizard#index" + get "qunit" => "wizard#qunit" + end + namespace :admin, constraints: StaffConstraint.new do get "" => "admin#index" diff --git a/public/images/wizard/bubbles.png b/public/images/wizard/bubbles.png new file mode 100644 index 0000000000000000000000000000000000000000..6847ae35926ce6c14a00c2cff6ad73355e506cf7 GIT binary patch literal 29250 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

xL~s)<57{!R=(}?5A3zM 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 literal 0 HcmV?d00001 diff --git a/spec/controllers/wizard/wizard_controller_spec.rb b/spec/controllers/wizard/wizard_controller_spec.rb new file mode 100644 index 00000000000..d6dcc9a24fd --- /dev/null +++ b/spec/controllers/wizard/wizard_controller_spec.rb @@ -0,0 +1,25 @@ +require 'rails_helper' + +describe Wizard::WizardController do + + context 'index' do + render_views + + it 'needs you to be logged in' do + expect { xhr :get, :index }.to raise_error(Discourse::NotLoggedIn) + end + + it "raises an error if you aren't an admin" do + log_in + xhr :get, :index + expect(response).to be_forbidden + end + + it "renders the wizard if you are an admin" do + log_in(:admin) + xhr :get, :index + expect(response).to be_success + end + end + +end