Commit 889af62f910ad4d4ea4f1ef0d196c0f0983ee48d
1 parent
ed78ea13
Exists in
master
and in
1 other branch
Refactor the Issue Tracker forms in App
Showing
21 changed files
with
261 additions
and
30 deletions
Show diff stats
Gemfile
| @@ -25,6 +25,7 @@ gem 'rails_autolink' | @@ -25,6 +25,7 @@ gem 'rails_autolink' | ||
| 25 | # Please don't update hoptoad_notifier to airbrake. | 25 | # Please don't update hoptoad_notifier to airbrake. |
| 26 | # It's for internal use only, and we monkeypatch certain methods | 26 | # It's for internal use only, and we monkeypatch certain methods |
| 27 | gem 'hoptoad_notifier', "~> 2.4" | 27 | gem 'hoptoad_notifier', "~> 2.4" |
| 28 | +gem 'draper', :require => false | ||
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | # Remove / comment out any of the gems below if you want to disable | 31 | # Remove / comment out any of the gems below if you want to disable |
Gemfile.lock
| @@ -95,6 +95,10 @@ GEM | @@ -95,6 +95,10 @@ GEM | ||
| 95 | warden (~> 1.2.3) | 95 | warden (~> 1.2.3) |
| 96 | diff-lcs (1.2.4) | 96 | diff-lcs (1.2.4) |
| 97 | dotenv (0.9.0) | 97 | dotenv (0.9.0) |
| 98 | + draper (1.2.1) | ||
| 99 | + actionpack (>= 3.0) | ||
| 100 | + activesupport (>= 3.0) | ||
| 101 | + request_store (~> 1.0.3) | ||
| 98 | email_spec (1.5.0) | 102 | email_spec (1.5.0) |
| 99 | launchy (~> 2.1) | 103 | launchy (~> 2.1) |
| 100 | mail (~> 2.2) | 104 | mail (~> 2.2) |
| @@ -282,6 +286,7 @@ GEM | @@ -282,6 +286,7 @@ GEM | ||
| 282 | rdoc (3.12.2) | 286 | rdoc (3.12.2) |
| 283 | json (~> 1.4) | 287 | json (~> 1.4) |
| 284 | ref (1.0.5) | 288 | ref (1.0.5) |
| 289 | + request_store (1.0.5) | ||
| 285 | rest-client (1.6.7) | 290 | rest-client (1.6.7) |
| 286 | mime-types (>= 1.16) | 291 | mime-types (>= 1.16) |
| 287 | ri_cal (0.8.8) | 292 | ri_cal (0.8.8) |
| @@ -382,6 +387,7 @@ DEPENDENCIES | @@ -382,6 +387,7 @@ DEPENDENCIES | ||
| 382 | debugger | 387 | debugger |
| 383 | decent_exposure | 388 | decent_exposure |
| 384 | devise | 389 | devise |
| 390 | + draper | ||
| 385 | email_spec | 391 | email_spec |
| 386 | execjs | 392 | execjs |
| 387 | fabrication | 393 | fabrication |
app/controllers/apps_controller.rb
| @@ -16,6 +16,9 @@ class AppsController < ApplicationController | @@ -16,6 +16,9 @@ class AppsController < ApplicationController | ||
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | expose(:app, :ancestor => :app_scope) | 18 | expose(:app, :ancestor => :app_scope) |
| 19 | + expose(:app_decorate) do | ||
| 20 | + AppDecorator.new(app) | ||
| 21 | + end | ||
| 19 | 22 | ||
| 20 | expose(:all_errs) { | 23 | expose(:all_errs) { |
| 21 | !!params[:all_errs] | 24 | !!params[:all_errs] |
| @@ -0,0 +1,19 @@ | @@ -0,0 +1,19 @@ | ||
| 1 | +class AppDecorator < Draper::Decorator | ||
| 2 | + | ||
| 3 | + decorates_association :watchers | ||
| 4 | + decorates_association :issue_tracker, :with => IssueTrackerDecorator | ||
| 5 | + delegate_all | ||
| 6 | + | ||
| 7 | + def email_at_notices | ||
| 8 | + object.email_at_notices.join(', ') | ||
| 9 | + end | ||
| 10 | + | ||
| 11 | + def notify_user_display | ||
| 12 | + object.notify_all_users ? 'display: none;' : '' | ||
| 13 | + end | ||
| 14 | + | ||
| 15 | + def notify_err_display | ||
| 16 | + object.notify_on_errs ? '' : 'display: none;' | ||
| 17 | + end | ||
| 18 | + | ||
| 19 | +end |
| @@ -0,0 +1,35 @@ | @@ -0,0 +1,35 @@ | ||
| 1 | +class IssueTrackerDecorator < Draper::Decorator | ||
| 2 | + | ||
| 3 | + delegate_all | ||
| 4 | + | ||
| 5 | + def issue_trackers | ||
| 6 | + @issue_trackers ||= [ | ||
| 7 | + IssueTracker, | ||
| 8 | + IssueTracker.subclasses | ||
| 9 | + ].flatten | ||
| 10 | + @issue_trackers.each do |it| | ||
| 11 | + yield IssueTrackerDecorator.new(it) | ||
| 12 | + end | ||
| 13 | + end | ||
| 14 | + | ||
| 15 | + def note | ||
| 16 | + object::Note.html_safe | ||
| 17 | + end | ||
| 18 | + | ||
| 19 | + def fields | ||
| 20 | + object::Fields.each do |field, field_info| | ||
| 21 | + yield IssueTrackerFieldDecorator.new(field, field_info) | ||
| 22 | + end | ||
| 23 | + end | ||
| 24 | + | ||
| 25 | + def params_class(tracker) | ||
| 26 | + [choosen?(tracker), label].join(" ").strip | ||
| 27 | + end | ||
| 28 | + | ||
| 29 | + private | ||
| 30 | + | ||
| 31 | + def choosen?(issue_tracker) | ||
| 32 | + object.to_s == issue_tracker._type ? 'chosen' : '' | ||
| 33 | + end | ||
| 34 | + | ||
| 35 | +end |
| @@ -0,0 +1,27 @@ | @@ -0,0 +1,27 @@ | ||
| 1 | +class IssueTrackerFieldDecorator < Draper::Decorator | ||
| 2 | + | ||
| 3 | + def initialize(field, field_info) | ||
| 4 | + @object = field | ||
| 5 | + @field_info = field_info | ||
| 6 | + end | ||
| 7 | + attr_reader :object, :field_info | ||
| 8 | + | ||
| 9 | + alias :key :object | ||
| 10 | + | ||
| 11 | + def label | ||
| 12 | + field_info[:label] || object.to_s.titleize | ||
| 13 | + end | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + def input(form) | ||
| 17 | + form.send(input_field, object, | ||
| 18 | + :placeholder => field_info[:placeholder], | ||
| 19 | + :value => form.object.send(object)) | ||
| 20 | + end | ||
| 21 | + | ||
| 22 | + private | ||
| 23 | + | ||
| 24 | + def input_field | ||
| 25 | + object == :password ? :password_field : :text_field | ||
| 26 | + end | ||
| 27 | +end |
app/models/issue_tracker.rb
| @@ -3,6 +3,11 @@ class IssueTracker | @@ -3,6 +3,11 @@ class IssueTracker | ||
| 3 | include Mongoid::Timestamps | 3 | include Mongoid::Timestamps |
| 4 | include HashHelper | 4 | include HashHelper |
| 5 | include Rails.application.routes.url_helpers | 5 | include Rails.application.routes.url_helpers |
| 6 | + | ||
| 7 | + Fields = [] | ||
| 8 | + Note = 'When no issue tracker has been configured, you will be able to leave comments on errors.' | ||
| 9 | + Label = 'none' | ||
| 10 | + | ||
| 6 | default_url_options[:host] = ActionMailer::Base.default_url_options[:host] | 11 | default_url_options[:host] = ActionMailer::Base.default_url_options[:host] |
| 7 | 12 | ||
| 8 | embedded_in :app, :inverse_of => :issue_tracker | 13 | embedded_in :app, :inverse_of => :issue_tracker |
| @@ -41,7 +46,6 @@ class IssueTracker | @@ -41,7 +46,6 @@ class IssueTracker | ||
| 41 | def url; nil; end | 46 | def url; nil; end |
| 42 | 47 | ||
| 43 | # Retrieve tracker label from either class or instance. | 48 | # Retrieve tracker label from either class or instance. |
| 44 | - Label = '' | ||
| 45 | def self.label; self::Label; end | 49 | def self.label; self::Label; end |
| 46 | def label; self.class.label; end | 50 | def label; self.class.label; end |
| 47 | 51 |
app/views/apps/_fields.html.haml
| @@ -29,9 +29,9 @@ | @@ -29,9 +29,9 @@ | ||
| 29 | = f.check_box :notify_on_errs, 'data-show-when-checked' => '.email_at_notices_nested' | 29 | = f.check_box :notify_on_errs, 'data-show-when-checked' => '.email_at_notices_nested' |
| 30 | = f.label :notify_on_errs, 'Notify on errors' | 30 | = f.label :notify_on_errs, 'Notify on errors' |
| 31 | - if Errbit::Config.per_app_email_at_notices | 31 | - if Errbit::Config.per_app_email_at_notices |
| 32 | - %div.email_at_notices_nested{:style => f.object.notify_on_errs ? '' : 'display: none;'} | 32 | + %div.email_at_notices_nested{:style => app_decorate.notify_err_display} |
| 33 | .field-helpertext Send a notification every | 33 | .field-helpertext Send a notification every |
| 34 | - = f.text_field :email_at_notices, :value => f.object.email_at_notices.join(", ") | 34 | + = f.text_field :email_at_notices, :value => app_decorate.email_at_notices |
| 35 | .field-helpertext times an error occurs (comma separated). | 35 | .field-helpertext times an error occurs (comma separated). |
| 36 | %div.checkbox | 36 | %div.checkbox |
| 37 | = f.check_box :notify_on_deploys | 37 | = f.check_box :notify_on_deploys |
| @@ -42,16 +42,16 @@ | @@ -42,16 +42,16 @@ | ||
| 42 | = f.label :notify_all_users, 'Send notifications to all users' | 42 | = f.label :notify_all_users, 'Send notifications to all users' |
| 43 | 43 | ||
| 44 | 44 | ||
| 45 | -%fieldset.watchers.nested-wrapper{:style => f.object.notify_all_users ? 'display: none;' : ''} | 45 | +%fieldset.watchers.nested-wrapper{:style => app_decorate.notify_user_display} |
| 46 | %legend Watchers | 46 | %legend Watchers |
| 47 | = f.fields_for :watchers do |w| | 47 | = f.fields_for :watchers do |w| |
| 48 | %div.watcher.nested | 48 | %div.watcher.nested |
| 49 | %div.choose | 49 | %div.choose |
| 50 | = w.radio_button :watcher_type, :user | 50 | = w.radio_button :watcher_type, :user |
| 51 | - = label_tag :watcher_type_user, 'User', :for => label_for_attr(w, 'watcher_type_user') | 51 | + = w.label :watcher_type_user, 'User' |
| 52 | = w.radio_button :watcher_type, :email | 52 | = w.radio_button :watcher_type, :email |
| 53 | - = label_tag :watcher_type_email, 'Email Address', :for => label_for_attr(w, 'watcher_type_email') | ||
| 54 | - %div.watcher_params.user{:class => w.object.email.blank? ? 'chosen' : nil} | 53 | + = w.label :watcher_type_email, 'Email Address' |
| 54 | + %div.watcher_params.user{:class => w.object.email_choosen} | ||
| 55 | = w.select :user_id, User.all.map{|u| [u.name,u.id.to_s]}, :include_blank => '-- Select a User --' | 55 | = w.select :user_id, User.all.map{|u| [u.name,u.id.to_s]}, :include_blank => '-- Select a User --' |
| 56 | %div.watcher_params.email{:class => w.object.email.present? ? 'chosen' : nil} | 56 | %div.watcher_params.email{:class => w.object.email.present? ? 'chosen' : nil} |
| 57 | = w.text_field :email | 57 | = w.text_field :email |
app/views/apps/_issue_tracker_fields.html.haml
| 1 | %fieldset | 1 | %fieldset |
| 2 | - %legend Issue tracker | 2 | + %legend= t('.legend') |
| 3 | = f.fields_for :issue_tracker do |w| | 3 | = f.fields_for :issue_tracker do |w| |
| 4 | %div.issue_tracker.nested | 4 | %div.issue_tracker.nested |
| 5 | %div.choose | 5 | %div.choose |
| 6 | - = label_tag :type_none, :for => label_for_attr(w, 'type_issuetracker'), :class => "label_radio none" do | ||
| 7 | - = w.radio_button :type, "IssueTracker", 'data-section' => 'none' | ||
| 8 | - (None) | ||
| 9 | - - IssueTracker.subclasses.each do |tracker| | ||
| 10 | - = label_tag "type_#{tracker.label}:", :for => label_for_attr(w, "type_#{tracker.name.downcase.gsub(':','')}"), :class => "label_radio #{tracker.label}" do | 6 | + - w.object.issue_trackers do |tracker| |
| 7 | + = w.label :type, :class => "label_radio #{tracker.label}", :value => tracker.name do | ||
| 11 | = w.radio_button :type, tracker.name, 'data-section' => tracker.label | 8 | = w.radio_button :type, tracker.name, 'data-section' => tracker.label |
| 12 | - = tracker.name[/::(.*)Tracker/,1].titleize | 9 | + = tracker.label |
| 13 | 10 | ||
| 14 | - %div.tracker_params.none{:class => (w.object && !(w.object.class < IssueTracker)) ? 'chosen' : nil} | ||
| 15 | - %p When no issue tracker has been configured, you will be able to leave comments on errors. | ||
| 16 | - - IssueTracker.subclasses.each do |tracker| | ||
| 17 | - %div.tracker_params{:class => (w.object.is_a?(tracker) ? 'chosen ' : '') << tracker.label} | ||
| 18 | - - if defined?(tracker::Note) | ||
| 19 | - %p= tracker::Note.html_safe | ||
| 20 | - - tracker::Fields.each do |field, field_info| | ||
| 21 | - = w.label field, field_info[:label] || field.to_s.titleize | ||
| 22 | - - field_type = field == :password ? :password_field : :text_field | ||
| 23 | - = w.send field_type, field, :placeholder => field_info[:placeholder], :value => w.object.send(field) | 11 | + - w.object.issue_trackers do |tracker| |
| 12 | + %div.tracker_params{:class => tracker.params_class(w.object)} | ||
| 13 | + %p= tracker.note | ||
| 14 | + - tracker.fields do |field| | ||
| 15 | + = w.label field.key, field.label | ||
| 16 | + = field.input(w) | ||
| 24 | 17 | ||
| 25 | .image_preloader | 18 | .image_preloader |
| 26 | - - (IssueTracker.subclasses.map{|t| t.label } << 'none').each do |tracker| | ||
| 27 | - = image_tag "#{tracker}_inactive.png" | ||
| 28 | - = image_tag "#{tracker}_create.png" | 19 | + - w.object.issue_trackers do |tracker| |
| 20 | + = image_tag "#{tracker.label}_inactive.png" | ||
| 21 | + = image_tag "#{tracker.label}_create.png" | ||
| 29 | 22 |
app/views/apps/edit.html.haml
| @@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
| 5 | :data => { :confirm => t('apps.confirm_delete') }, :class => 'button' | 5 | :data => { :confirm => t('apps.confirm_delete') }, :class => 'button' |
| 6 | = link_to('cancel', app_path(app), :class => 'button') | 6 | = link_to('cancel', app_path(app), :class => 'button') |
| 7 | 7 | ||
| 8 | -= form_for app do |f| | 8 | += form_for app_decorate do |f| |
| 9 | 9 | ||
| 10 | = render 'fields', :f => f | 10 | = render 'fields', :f => f |
| 11 | 11 |
app/views/apps/new.html.haml
| @@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
| 3 | = link_to_copy_attributes_from_other_app | 3 | = link_to_copy_attributes_from_other_app |
| 4 | = link_to('cancel', apps_path, :class => 'button') | 4 | = link_to('cancel', apps_path, :class => 'button') |
| 5 | 5 | ||
| 6 | -= form_for app do |f| | 6 | += form_for app_decorate do |f| |
| 7 | 7 | ||
| 8 | = render 'fields', :f => f | 8 | = render 'fields', :f => f |
| 9 | 9 |
config/application.rb
| @@ -9,6 +9,8 @@ require "action_mailer/railtie" | @@ -9,6 +9,8 @@ require "action_mailer/railtie" | ||
| 9 | require 'mongoid/railtie' | 9 | require 'mongoid/railtie' |
| 10 | require "sprockets/railtie" | 10 | require "sprockets/railtie" |
| 11 | 11 | ||
| 12 | +require 'draper' | ||
| 13 | + | ||
| 12 | if defined?(Bundler) | 14 | if defined?(Bundler) |
| 13 | # If you precompile assets before deploying to production, use this line | 15 | # If you precompile assets before deploying to production, use this line |
| 14 | Bundler.require(*Rails.groups(:assets => %w(development test))) | 16 | Bundler.require(*Rails.groups(:assets => %w(development test))) |
config/locales/en.yml
spec/acceptance/app_regenerate_api_key_spec.rb
| @@ -28,5 +28,4 @@ feature "Regeneration api_Key" do | @@ -28,5 +28,4 @@ feature "Regeneration api_Key" do | ||
| 28 | click_link app.name if page.current_url != app_url(app) | 28 | click_link app.name if page.current_url != app_url(app) |
| 29 | expect(page).to_not have_button I18n.t('apps.show.edit') | 29 | expect(page).to_not have_button I18n.t('apps.show.edit') |
| 30 | end | 30 | end |
| 31 | - | ||
| 32 | end | 31 | end |
| @@ -0,0 +1,37 @@ | @@ -0,0 +1,37 @@ | ||
| 1 | +require 'spec_helper' | ||
| 2 | + | ||
| 3 | +describe AppDecorator do | ||
| 4 | + | ||
| 5 | + describe "#email_at_notices" do | ||
| 6 | + | ||
| 7 | + it 'return the list separate by comma' do | ||
| 8 | + expect(AppDecorator.new(double(:email_at_notices => [2,3])).email_at_notices).to eql '2, 3' | ||
| 9 | + end | ||
| 10 | + | ||
| 11 | + end | ||
| 12 | + | ||
| 13 | + describe "#notify_user_display" do | ||
| 14 | + | ||
| 15 | + it 'return display:none if notify' do | ||
| 16 | + expect(AppDecorator.new(double(:notify_all_users => true)).notify_user_display).to eql 'display: none;' | ||
| 17 | + end | ||
| 18 | + | ||
| 19 | + it 'return blank if no notify' do | ||
| 20 | + expect(AppDecorator.new(double(:notify_all_users => false)).notify_user_display).to eql '' | ||
| 21 | + end | ||
| 22 | + | ||
| 23 | + end | ||
| 24 | + | ||
| 25 | + describe "#notify_err_display" do | ||
| 26 | + | ||
| 27 | + it 'return display:none if no notify' do | ||
| 28 | + expect(AppDecorator.new(double(:notify_on_errs => false)).notify_err_display).to eql 'display: none;' | ||
| 29 | + end | ||
| 30 | + | ||
| 31 | + it 'return blank if no notify' do | ||
| 32 | + expect(AppDecorator.new(double(:notify_on_errs => true)).notify_err_display).to eql '' | ||
| 33 | + end | ||
| 34 | + | ||
| 35 | + end | ||
| 36 | + | ||
| 37 | +end |
| @@ -0,0 +1,59 @@ | @@ -0,0 +1,59 @@ | ||
| 1 | +require 'spec_helper' | ||
| 2 | + | ||
| 3 | +describe IssueTrackerDecorator do | ||
| 4 | + | ||
| 5 | + class Foo | ||
| 6 | + Note = 'hello <strong></strong>' | ||
| 7 | + Fields = [ | ||
| 8 | + [:foo, :bar] | ||
| 9 | + ] | ||
| 10 | + Label = 'foo' | ||
| 11 | + def self.label; Label; end | ||
| 12 | + def _type | ||
| 13 | + 'Foo' | ||
| 14 | + end | ||
| 15 | + end | ||
| 16 | + | ||
| 17 | + class Bar | ||
| 18 | + Label = 'bar' | ||
| 19 | + def self.label; Label; end | ||
| 20 | + def _type | ||
| 21 | + 'Bar' | ||
| 22 | + end | ||
| 23 | + end | ||
| 24 | + | ||
| 25 | + describe "#note" do | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + it 'return the html_safe of Note' do | ||
| 29 | + expect(IssueTrackerDecorator.new(Foo).note).to eql 'hello <strong></strong>'.html_safe | ||
| 30 | + end | ||
| 31 | + end | ||
| 32 | + | ||
| 33 | + describe "#issue_trackers" do | ||
| 34 | + it 'return an array of IssueTrackerDecorator' do | ||
| 35 | + IssueTrackerDecorator.new(Foo).issue_trackers do |it| | ||
| 36 | + expect(it).to be_a(IssueTrackerDecorator) | ||
| 37 | + end | ||
| 38 | + end | ||
| 39 | + end | ||
| 40 | + | ||
| 41 | + describe "#fields" do | ||
| 42 | + it 'return all Fields define decorate' do | ||
| 43 | + IssueTrackerDecorator.new(Foo).fields do |itf| | ||
| 44 | + expect(itf).to be_a(IssueTrackerFieldDecorator) | ||
| 45 | + expect(itf.object).to eql :foo | ||
| 46 | + expect(itf.field_info).to eql :bar | ||
| 47 | + end | ||
| 48 | + end | ||
| 49 | + end | ||
| 50 | + | ||
| 51 | + describe "#params_class" do | ||
| 52 | + it 'add the label in class' do | ||
| 53 | + expect(IssueTrackerDecorator.new(Bar).params_class(Foo.new)).to eql 'bar' | ||
| 54 | + end | ||
| 55 | + it 'add chosen class if _type is same' do | ||
| 56 | + expect(IssueTrackerDecorator.new(Foo).params_class(Foo.new)).to eql 'chosen foo' | ||
| 57 | + end | ||
| 58 | + end | ||
| 59 | +end |
| @@ -0,0 +1,14 @@ | @@ -0,0 +1,14 @@ | ||
| 1 | +require 'spec_helper' | ||
| 2 | + | ||
| 3 | +describe IssueTrackerFieldDecorator do | ||
| 4 | + | ||
| 5 | + describe "#label" do | ||
| 6 | + it 'return the label of field_info by default' do | ||
| 7 | + expect(IssueTrackerFieldDecorator.new(:foo, {:label => 'hello'}).label).to eq 'hello' | ||
| 8 | + end | ||
| 9 | + it 'return the key of field if no label define' do | ||
| 10 | + expect(IssueTrackerFieldDecorator.new(:foo, {}).label).to eq 'foo' | ||
| 11 | + end | ||
| 12 | + end | ||
| 13 | + | ||
| 14 | +end |
| @@ -0,0 +1,17 @@ | @@ -0,0 +1,17 @@ | ||
| 1 | +require 'spec_helper' | ||
| 2 | + | ||
| 3 | +describe WatcherDecorator do | ||
| 4 | + describe "#email_choosen" do | ||
| 5 | + context "with email define" do | ||
| 6 | + it 'return blank' do | ||
| 7 | + expect(WatcherDecorator.new(double(:email => 'foo')).email_choosen).to eql '' | ||
| 8 | + end | ||
| 9 | + end | ||
| 10 | + | ||
| 11 | + context "without email define" do | ||
| 12 | + it 'return choosen' do | ||
| 13 | + expect(WatcherDecorator.new(double(:email => '')).email_choosen).to eql 'chosen' | ||
| 14 | + end | ||
| 15 | + end | ||
| 16 | + end | ||
| 17 | +end |
spec/views/apps/edit.html.haml_spec.rb
| @@ -2,8 +2,10 @@ require 'spec_helper' | @@ -2,8 +2,10 @@ require 'spec_helper' | ||
| 2 | 2 | ||
| 3 | describe "apps/edit.html.haml" do | 3 | describe "apps/edit.html.haml" do |
| 4 | let(:app) { stub_model(App) } | 4 | let(:app) { stub_model(App) } |
| 5 | + let(:app_decorate) { AppDecorator.new(app) } | ||
| 5 | before do | 6 | before do |
| 6 | view.stub(:app).and_return(app) | 7 | view.stub(:app).and_return(app) |
| 8 | + view.stub(:app_decorate).and_return(app_decorate) | ||
| 7 | controller.stub(:current_user) { stub_model(User) } | 9 | controller.stub(:current_user) { stub_model(User) } |
| 8 | end | 10 | end |
| 9 | 11 |
spec/views/apps/new.html.haml_spec.rb
| @@ -2,8 +2,10 @@ require 'spec_helper' | @@ -2,8 +2,10 @@ require 'spec_helper' | ||
| 2 | 2 | ||
| 3 | describe "apps/new.html.haml" do | 3 | describe "apps/new.html.haml" do |
| 4 | let(:app) { stub_model(App) } | 4 | let(:app) { stub_model(App) } |
| 5 | + let(:app_decorate) { AppDecorator.new(app) } | ||
| 5 | before do | 6 | before do |
| 6 | view.stub(:app).and_return(app) | 7 | view.stub(:app).and_return(app) |
| 8 | + view.stub(:app_decorate).and_return(app_decorate) | ||
| 7 | controller.stub(:current_user) { stub_model(User) } | 9 | controller.stub(:current_user) { stub_model(User) } |
| 8 | end | 10 | end |
| 9 | 11 |