Commit 8c60eb54e744ccc0170231436f56d1f0fef7a99e
1 parent
8ef1dc2b
Exists in
master
and in
1 other branch
fix specs related to mongoid5 upgrade
Showing
32 changed files
with
236 additions
and
260 deletions
Show diff stats
app/controllers/problems_controller.rb
@@ -22,7 +22,7 @@ class ProblemsController < ApplicationController | @@ -22,7 +22,7 @@ class ProblemsController < ApplicationController | ||
22 | } | 22 | } |
23 | 23 | ||
24 | expose(:problem) { | 24 | expose(:problem) { |
25 | - app.problems.find(params[:id]) | 25 | + ProblemDecorator.new app.problems.find(params[:id]) |
26 | } | 26 | } |
27 | 27 | ||
28 | expose(:all_errs) { | 28 | expose(:all_errs) { |
@@ -50,7 +50,8 @@ class ProblemsController < ApplicationController | @@ -50,7 +50,8 @@ class ProblemsController < ApplicationController | ||
50 | def index; end | 50 | def index; end |
51 | 51 | ||
52 | def show | 52 | def show |
53 | - @notices = problem.notices.reverse_ordered.page(params[:notice]).per(1) | 53 | + @notices = problem.object.notices.reverse_ordered |
54 | + .page(params[:notice]).per(1) | ||
54 | @notice = @notices.first | 55 | @notice = @notices.first |
55 | @comment = Comment.new | 56 | @comment = Comment.new |
56 | end | 57 | end |
@@ -0,0 +1,76 @@ | @@ -0,0 +1,76 @@ | ||
1 | +class BacktraceLineDecorator < Draper::Decorator | ||
2 | + EMPTY_STRING = ''.freeze | ||
3 | + | ||
4 | + def in_app? | ||
5 | + object[:file].match Backtrace::IN_APP_PATH | ||
6 | + end | ||
7 | + | ||
8 | + def number | ||
9 | + object[:number] | ||
10 | + end | ||
11 | + | ||
12 | + def file | ||
13 | + object[:file] | ||
14 | + end | ||
15 | + | ||
16 | + def method | ||
17 | + object[:method] | ||
18 | + end | ||
19 | + | ||
20 | + def file_relative | ||
21 | + file.to_s.sub(Backtrace::IN_APP_PATH, EMPTY_STRING) | ||
22 | + end | ||
23 | + | ||
24 | + def file_name | ||
25 | + File.basename file | ||
26 | + end | ||
27 | + | ||
28 | + def to_s | ||
29 | + column = object.try(:[], :column) | ||
30 | + "#{file_relative}:#{number}#{column.present? ? ":#{column}" : ''}" | ||
31 | + end | ||
32 | + | ||
33 | + def link_to_source_file(app, &block) | ||
34 | + text = h.capture_haml(&block) | ||
35 | + link_to_in_app_source_file(app, text) || text | ||
36 | + end | ||
37 | + | ||
38 | + private | ||
39 | + def link_to_in_app_source_file(app, text) | ||
40 | + return unless in_app? | ||
41 | + if file_name =~ /\.js$/ | ||
42 | + link_to_hosted_javascript(app, text) | ||
43 | + else | ||
44 | + link_to_repo_source_file(app, text) || | ||
45 | + link_to_issue_tracker_file(app, text) | ||
46 | + end | ||
47 | + end | ||
48 | + | ||
49 | + def link_to_repo_source_file(app, text) | ||
50 | + link_to_github(app, text) || link_to_bitbucket(app, text) | ||
51 | + end | ||
52 | + | ||
53 | + def link_to_hosted_javascript(app, text) | ||
54 | + if app.asset_host? | ||
55 | + h.link_to(text, "#{app.asset_host}/#{file_relative}", :target => '_blank') | ||
56 | + end | ||
57 | + end | ||
58 | + | ||
59 | + def link_to_github(app, text = nil) | ||
60 | + return unless app.github_repo? | ||
61 | + href = "%s#L%s" % [app.github_url_to_file(decorated_path + file_name), number] | ||
62 | + h.link_to(text || file_name, href, :target => '_blank') | ||
63 | + end | ||
64 | + | ||
65 | + def link_to_bitbucket(app, text = nil) | ||
66 | + return unless app.bitbucket_repo? | ||
67 | + href = "%s#cl-%s" % [app.bitbucket_url_to_file(decorated_path + file_name), number] | ||
68 | + h.link_to(text || file_name, href, :target => '_blank') | ||
69 | + end | ||
70 | + | ||
71 | + def link_to_issue_tracker_file(app, text = nil) | ||
72 | + return unless app.issue_tracker && app.issue_tracker.respond_to?(:url_to_file) | ||
73 | + href = app.issue_tracker.url_to_file(file_relative, number) | ||
74 | + h.link_to(text || file_name, href, :target => '_blank') | ||
75 | + end | ||
76 | +end |
app/helpers/backtrace_line_helper.rb
1 | module BacktraceLineHelper | 1 | module BacktraceLineHelper |
2 | - def link_to_source_file(line, &block) | 2 | + def link_to_source_file(line, app, &block) |
3 | text = capture_haml(&block) | 3 | text = capture_haml(&block) |
4 | - link_to_in_app_source_file(line, text) || link_to_external_source_file(text) | 4 | + link_to_in_app_source_file(line, app, text) || text |
5 | end | 5 | end |
6 | 6 | ||
7 | private | 7 | private |
8 | - def link_to_in_app_source_file(line, text) | 8 | + def link_to_in_app_source_file(line, app, text) |
9 | return unless line.in_app? | 9 | return unless line.in_app? |
10 | if line.file_name =~ /\.js$/ | 10 | if line.file_name =~ /\.js$/ |
11 | - link_to_hosted_javascript(line, text) | 11 | + link_to_hosted_javascript(line, app, text) |
12 | else | 12 | else |
13 | - link_to_repo_source_file(line, text) || | ||
14 | - link_to_issue_tracker_file(line, text) | 13 | + link_to_repo_source_file(line, app, text) || |
14 | + link_to_issue_tracker_file(line, app, text) | ||
15 | end | 15 | end |
16 | end | 16 | end |
17 | 17 | ||
18 | - def link_to_repo_source_file(line, text) | ||
19 | - link_to_github(line, text) || link_to_bitbucket(line, text) | 18 | + def link_to_repo_source_file(line, app, text) |
19 | + link_to_github(line, app, text) || link_to_bitbucket(line, app, text) | ||
20 | end | 20 | end |
21 | 21 | ||
22 | - def link_to_hosted_javascript(line, text) | ||
23 | - if line.app.asset_host? | ||
24 | - link_to(text, "#{line.app.asset_host}/#{line.file_relative}", :target => '_blank') | 22 | + def link_to_hosted_javascript(line, app, text) |
23 | + if app.asset_host? | ||
24 | + link_to(text, "#{app.asset_host}/#{line.file_relative}", :target => '_blank') | ||
25 | end | 25 | end |
26 | end | 26 | end |
27 | 27 | ||
28 | - def link_to_external_source_file(text) | ||
29 | - text | ||
30 | - end | ||
31 | - | ||
32 | - def link_to_github(line, text = nil) | ||
33 | - return unless line.app.github_repo? | ||
34 | - href = "%s#L%s" % [line.app.github_url_to_file(line.decorated_path + line.file_name), line.number] | 28 | + def link_to_github(line, app, text = nil) |
29 | + return unless app.github_repo? | ||
30 | + href = "%s#L%s" % [app.github_url_to_file(line.decorated_path + line.file_name), line.number] | ||
35 | link_to(text || line.file_name, href, :target => '_blank') | 31 | link_to(text || line.file_name, href, :target => '_blank') |
36 | end | 32 | end |
37 | 33 | ||
38 | - def link_to_bitbucket(line, text = nil) | ||
39 | - return unless line.app.bitbucket_repo? | ||
40 | - href = "%s#cl-%s" % [line.app.bitbucket_url_to_file(line.decorated_path + line.file_name), line.number] | 34 | + def link_to_bitbucket(line, app, text = nil) |
35 | + return unless app.bitbucket_repo? | ||
36 | + href = "%s#cl-%s" % [app.bitbucket_url_to_file(line.decorated_path + line.file_name), line.number] | ||
41 | link_to(text || line.file_name, href, :target => '_blank') | 37 | link_to(text || line.file_name, href, :target => '_blank') |
42 | end | 38 | end |
43 | 39 | ||
44 | - def link_to_issue_tracker_file(line, text = nil) | ||
45 | - return unless line.app.issue_tracker && line.app.issue_tracker.respond_to?(:url_to_file) | ||
46 | - href = line.app.issue_tracker.url_to_file(line.file_relative, line.number) | 40 | + def link_to_issue_tracker_file(line, app, text = nil) |
41 | + return unless app.issue_tracker && app.issue_tracker.respond_to?(:url_to_file) | ||
42 | + href = app.issue_tracker.url_to_file(line.file_relative, line.number) | ||
47 | link_to(text || line.file_name, href, :target => '_blank') | 43 | link_to(text || line.file_name, href, :target => '_blank') |
48 | end | 44 | end |
49 | 45 |
app/mailers/mailer.rb
@@ -13,11 +13,11 @@ class Mailer < ActionMailer::Base | @@ -13,11 +13,11 @@ class Mailer < ActionMailer::Base | ||
13 | 'Precedence' => 'bulk', | 13 | 'Precedence' => 'bulk', |
14 | 'Auto-Submitted' => 'auto-generated' | 14 | 'Auto-Submitted' => 'auto-generated' |
15 | 15 | ||
16 | - def err_notification(notice) | ||
17 | - @notice = notice | ||
18 | - @app = notice.app | 16 | + def err_notification(error_report) |
17 | + @notice = NoticeDecorator.new error_report.notice | ||
18 | + @app = AppDecorator.new error_report.app | ||
19 | 19 | ||
20 | - count = @notice.similar_count | 20 | + count = error_report.problem.notices_count |
21 | count = count > 1 ? "(#{count}) " : "" | 21 | count = count > 1 ? "(#{count}) " : "" |
22 | 22 | ||
23 | errbit_headers 'App' => @app.name, | 23 | errbit_headers 'App' => @app.name, |
@@ -30,7 +30,7 @@ class Mailer < ActionMailer::Base | @@ -30,7 +30,7 @@ class Mailer < ActionMailer::Base | ||
30 | 30 | ||
31 | def deploy_notification(deploy) | 31 | def deploy_notification(deploy) |
32 | @deploy = deploy | 32 | @deploy = deploy |
33 | - @app = deploy.app | 33 | + @app = AppDecorator.new deploy.app |
34 | 34 | ||
35 | errbit_headers 'App' => @app.name, | 35 | errbit_headers 'App' => @app.name, |
36 | 'Environment' => @deploy.environment, | 36 | 'Environment' => @deploy.environment, |
@@ -44,7 +44,7 @@ class Mailer < ActionMailer::Base | @@ -44,7 +44,7 @@ class Mailer < ActionMailer::Base | ||
44 | def comment_notification(comment) | 44 | def comment_notification(comment) |
45 | @comment = comment | 45 | @comment = comment |
46 | @user = comment.user | 46 | @user = comment.user |
47 | - @problem = comment.err | 47 | + @problem = ProblemDecorator.new comment.err |
48 | @notice = @problem.notices.first | 48 | @notice = @problem.notices.first |
49 | @app = @problem.app | 49 | @app = @problem.app |
50 | 50 |
app/models/backtrace.rb
@@ -2,31 +2,23 @@ class Backtrace | @@ -2,31 +2,23 @@ class Backtrace | ||
2 | include Mongoid::Document | 2 | include Mongoid::Document |
3 | include Mongoid::Timestamps | 3 | include Mongoid::Timestamps |
4 | 4 | ||
5 | - field :fingerprint | ||
6 | - index :fingerprint => 1 | ||
7 | - | ||
8 | - has_many :notices | ||
9 | - has_one :notice | 5 | + IN_APP_PATH = %r{^\[PROJECT_ROOT\](?!(\/vendor))/?} |
10 | 6 | ||
11 | - embeds_many :lines, :class_name => "BacktraceLine" | ||
12 | - | ||
13 | - after_initialize :generate_fingerprint | 7 | + field :fingerprint |
8 | + field :lines | ||
14 | 9 | ||
15 | - delegate :app, :to => :notice | 10 | + index :fingerprint => 1 |
16 | 11 | ||
17 | def self.find_or_create(lines) | 12 | def self.find_or_create(lines) |
18 | fingerprint = generate_fingerprint(lines) | 13 | fingerprint = generate_fingerprint(lines) |
19 | 14 | ||
20 | - where(fingerprint: generate_fingerprint(lines)). | ||
21 | - find_one_and_update( | ||
22 | - { '$setOnInsert' => { fingerprint: fingerprint, lines: lines } }, | ||
23 | - { return_document: :after, upsert: true }) | 15 | + where(fingerprint: fingerprint).find_one_and_update( |
16 | + { '$setOnInsert' => { fingerprint: fingerprint, lines: lines } }, | ||
17 | + { return_document: :after, upsert: true }) | ||
24 | end | 18 | end |
25 | 19 | ||
26 | - def raw=(raw) | ||
27 | - raw.compact.each do |raw_line| | ||
28 | - lines << BacktraceLine.new(BacktraceLineNormalizer.new(raw_line).call) | ||
29 | - end | 20 | + def self.generate_fingerprint(lines) |
21 | + Digest::SHA1.hexdigest(lines.map(&:to_s).join) | ||
30 | end | 22 | end |
31 | 23 | ||
32 | private | 24 | private |
app/models/backtrace_line.rb
@@ -1,42 +0,0 @@ | @@ -1,42 +0,0 @@ | ||
1 | -class BacktraceLine | ||
2 | - include Mongoid::Document | ||
3 | - IN_APP_PATH = %r{^\[PROJECT_ROOT\](?!(\/vendor))/?} | ||
4 | - GEMS_PATH = %r{\[GEM_ROOT\]\/gems\/([^\/]+)} | ||
5 | - | ||
6 | - field :number, :type => Integer | ||
7 | - field :column, :type => Integer | ||
8 | - field :file | ||
9 | - field :method | ||
10 | - | ||
11 | - embedded_in :backtrace | ||
12 | - | ||
13 | - scope :in_app, ->{ where(:file => IN_APP_PATH) } | ||
14 | - | ||
15 | - delegate :app, :to => :backtrace | ||
16 | - | ||
17 | - def to_s | ||
18 | - "#{file_relative}:#{number}" << (column.present? ? ":#{column}" : "") | ||
19 | - end | ||
20 | - | ||
21 | - def in_app? | ||
22 | - !!(file =~ IN_APP_PATH) | ||
23 | - end | ||
24 | - | ||
25 | - def path | ||
26 | - File.dirname(file).gsub(/^\.$/, '') + "/" | ||
27 | - end | ||
28 | - | ||
29 | - def file_relative | ||
30 | - file.to_s.sub(IN_APP_PATH, '') | ||
31 | - end | ||
32 | - | ||
33 | - def file_name | ||
34 | - File.basename file | ||
35 | - end | ||
36 | - | ||
37 | - def decorated_path | ||
38 | - path.sub(BacktraceLine::IN_APP_PATH, ''). | ||
39 | - sub(BacktraceLine::GEMS_PATH, "<strong>\\1</strong>") | ||
40 | - end | ||
41 | - | ||
42 | -end |
app/models/backtrace_line_normalizer.rb
@@ -1,32 +0,0 @@ | @@ -1,32 +0,0 @@ | ||
1 | -class BacktraceLineNormalizer | ||
2 | - def initialize(raw_line) | ||
3 | - @raw_line = raw_line || {} | ||
4 | - end | ||
5 | - | ||
6 | - def call | ||
7 | - @raw_line.merge 'file' => normalized_file, 'method' => normalized_method | ||
8 | - end | ||
9 | - | ||
10 | - private | ||
11 | - def normalized_file | ||
12 | - if @raw_line['file'].blank? | ||
13 | - "[unknown source]" | ||
14 | - else | ||
15 | - file = @raw_line['file'].to_s | ||
16 | - # Detect lines from gem | ||
17 | - file.gsub!(/\[PROJECT_ROOT\]\/.*\/ruby\/[0-9.]+\/gems/, '[GEM_ROOT]/gems') | ||
18 | - # Strip any query strings | ||
19 | - file.gsub!(/\?[^\?]*$/, '') | ||
20 | - @raw_line['file'] = file | ||
21 | - end | ||
22 | - end | ||
23 | - | ||
24 | - def normalized_method | ||
25 | - if @raw_line['method'].blank? | ||
26 | - "[unknown method]" | ||
27 | - else | ||
28 | - @raw_line['method'].to_s.gsub(/[0-9_]{10,}+/, "__FRAGMENT__") | ||
29 | - end | ||
30 | - end | ||
31 | - | ||
32 | -end |
app/models/error_report.rb
@@ -79,23 +79,20 @@ class ErrorReport | @@ -79,23 +79,20 @@ class ErrorReport | ||
79 | # Update problem cache with information about this notice | 79 | # Update problem cache with information about this notice |
80 | def cache_attributes_on_problem | 80 | def cache_attributes_on_problem |
81 | @problem = Problem.cache_notice(@error.problem_id, @notice) | 81 | @problem = Problem.cache_notice(@error.problem_id, @notice) |
82 | - | ||
83 | - # cache_notice returns the old problem, so the count is one higher | ||
84 | - @similar_count = @problem.notices_count + 1 | ||
85 | end | 82 | end |
86 | 83 | ||
87 | # Send email notification if needed | 84 | # Send email notification if needed |
88 | def email_notification | 85 | def email_notification |
89 | return false unless app.emailable? | 86 | return false unless app.emailable? |
90 | - return false unless app.email_at_notices.include?(@similar_count) | ||
91 | - Mailer.err_notification(@notice).deliver | 87 | + return false unless app.email_at_notices.include?(@problem.notices_count) |
88 | + Mailer.err_notification(self).deliver | ||
92 | rescue => e | 89 | rescue => e |
93 | HoptoadNotifier.notify(e) | 90 | HoptoadNotifier.notify(e) |
94 | end | 91 | end |
95 | 92 | ||
96 | def should_notify? | 93 | def should_notify? |
97 | app.notification_service.notify_at_notices.include?(0) || | 94 | app.notification_service.notify_at_notices.include?(0) || |
98 | - app.notification_service.notify_at_notices.include?(@similar_count) | 95 | + app.notification_service.notify_at_notices.include?(@problem.notices_count) |
99 | end | 96 | end |
100 | 97 | ||
101 | # Launch all notification define on the app associate to this notice | 98 | # Launch all notification define on the app associate to this notice |
app/models/notice.rb
@@ -103,10 +103,6 @@ class Notice | @@ -103,10 +103,6 @@ class Notice | ||
103 | request['session'] || {} | 103 | request['session'] || {} |
104 | end | 104 | end |
105 | 105 | ||
106 | - def in_app_backtrace_lines | ||
107 | - backtrace_lines.in_app | ||
108 | - end | ||
109 | - | ||
110 | ## | 106 | ## |
111 | # TODO: Move on decorator maybe | 107 | # TODO: Move on decorator maybe |
112 | # | 108 | # |
app/models/problem.rb
@@ -76,7 +76,7 @@ class Problem | @@ -76,7 +76,7 @@ class Problem | ||
76 | host_digest = Digest::MD5.hexdigest(notice.host) | 76 | host_digest = Digest::MD5.hexdigest(notice.host) |
77 | user_agent_digest = Digest::MD5.hexdigest(notice.user_agent_string) | 77 | user_agent_digest = Digest::MD5.hexdigest(notice.user_agent_string) |
78 | 78 | ||
79 | - Problem.where('_id' => id).find_one_and_update( | 79 | + Problem.where('_id' => id).find_one_and_update({ |
80 | '$set' => { | 80 | '$set' => { |
81 | 'environment' => notice.environment_name, | 81 | 'environment' => notice.environment_name, |
82 | 'error_class' => notice.error_class, | 82 | 'error_class' => notice.error_class, |
@@ -95,7 +95,7 @@ class Problem | @@ -95,7 +95,7 @@ class Problem | ||
95 | "hosts.#{host_digest}.count" => 1, | 95 | "hosts.#{host_digest}.count" => 1, |
96 | "user_agents.#{user_agent_digest}.count" => 1, | 96 | "user_agents.#{user_agent_digest}.count" => 1, |
97 | } | 97 | } |
98 | - ) | 98 | + }, return_document: :after) |
99 | end | 99 | end |
100 | 100 | ||
101 | def uncache_notice(notice) | 101 | def uncache_notice(notice) |
app/views/issue_trackers/issue.md.erb
@@ -27,7 +27,7 @@ | @@ -27,7 +27,7 @@ | ||
27 | 27 | ||
28 | ## Backtrace ## | 28 | ## Backtrace ## |
29 | ~~~ | 29 | ~~~ |
30 | -<% notice.backtrace_lines.each do |line| %><%= line.number %>: <%= line.file_relative %> -> **<%= line.method %>** | 30 | +<% notice.backtrace.lines.each do |line| %><%= line.number %>: <%= line.file_relative %> -> **<%= line.method %>** |
31 | <% end %> | 31 | <% end %> |
32 | ~~~ | 32 | ~~~ |
33 | 33 |
app/views/issue_trackers/issue.txt.erb
@@ -16,6 +16,6 @@ Env: <%= pretty_hash notice.env_vars %> | @@ -16,6 +16,6 @@ Env: <%= pretty_hash notice.env_vars %> | ||
16 | 16 | ||
17 | Backtrace | 17 | Backtrace |
18 | --------- | 18 | --------- |
19 | -<% notice.backtrace_lines.each do |line| %><%= sprintf('%5d: %s **%s', line.number, line.file_relative, line.method) %> | 19 | +<% notice.backtrace.lines.each do |line| %><%= sprintf('%5d: %s **%s', line.number, line.file_relative, line.method) %> |
20 | <% end %> | 20 | <% end %> |
21 | <% end %> | 21 | <% end %> |
app/views/mailer/comment_notification.text.erb
@@ -21,8 +21,8 @@ WHERE: | @@ -21,8 +21,8 @@ WHERE: | ||
21 | 21 | ||
22 | <%= @notice.where %> | 22 | <%= @notice.where %> |
23 | 23 | ||
24 | -<% @notice.in_app_backtrace_lines.each do |line| %> | ||
25 | - <%= line %> | 24 | +<% @notice.backtrace.lines.each do |line| %> |
25 | + <% next unless line.in_app? %><%= line %> | ||
26 | <% end %> | 26 | <% end %> |
27 | 27 | ||
28 | 28 |
app/views/mailer/err_notification.html.haml
@@ -27,9 +27,10 @@ | @@ -27,9 +27,10 @@ | ||
27 | %p.heading WHERE: | 27 | %p.heading WHERE: |
28 | %p.monospace | 28 | %p.monospace |
29 | = @notice.where | 29 | = @notice.where |
30 | - - @notice.in_app_backtrace_lines.each do |line| | 30 | + - @notice.backtrace.lines.each do |line| |
31 | + - next unless line.in_app? | ||
31 | %p.backtrace | 32 | %p.backtrace |
32 | - = link_to_source_file(line) do | 33 | + = line.link_to_source_file(@app) do |
33 | = line.to_s | 34 | = line.to_s |
34 | %br | 35 | %br |
35 | - if @notice.app_version.present? | 36 | - if @notice.app_version.present? |
@@ -59,11 +60,11 @@ | @@ -59,11 +60,11 @@ | ||
59 | %td(style="text-align: right; padding-right: 10px; color: #6a6a6a;")= key.to_s.titleize + ":" | 60 | %td(style="text-align: right; padding-right: 10px; color: #6a6a6a;")= key.to_s.titleize + ":" |
60 | %td= auto_link(value.to_s) | 61 | %td= auto_link(value.to_s) |
61 | %br | 62 | %br |
62 | - - if @notice.backtrace_lines.any? | 63 | + - if @notice.backtrace.lines.any? |
63 | %br | 64 | %br |
64 | %p.heading FULL BACKTRACE: | 65 | %p.heading FULL BACKTRACE: |
65 | - - @notice.backtrace_lines.each do |line| | 66 | + - @notice.backtrace.lines.each do |line| |
66 | %p.backtrace | 67 | %p.backtrace |
67 | - = link_to_source_file(line) do | 68 | + = link_to_source_file(line, @app) do |
68 | = line.to_s | 69 | = line.to_s |
69 | %br | 70 | %br |
app/views/mailer/err_notification.text.erb
@@ -14,7 +14,8 @@ WHERE: | @@ -14,7 +14,8 @@ WHERE: | ||
14 | 14 | ||
15 | <%= @notice.where %> | 15 | <%= @notice.where %> |
16 | 16 | ||
17 | -<% @notice.in_app_backtrace_lines.each do |line| %> | 17 | +<% @notice.backtrace.lines.each do |line| %> |
18 | + <% next unless line.in_app? %> | ||
18 | <%= line %> | 19 | <%= line %> |
19 | <% end %> | 20 | <% end %> |
20 | 21 | ||
@@ -51,7 +52,7 @@ USER: | @@ -51,7 +52,7 @@ USER: | ||
51 | 52 | ||
52 | BACKTRACE: | 53 | BACKTRACE: |
53 | 54 | ||
54 | -<% @notice.backtrace_lines.each do |line| %> | 55 | +<% @notice.backtrace.lines.each do |line| %> |
55 | <%= line %> | 56 | <%= line %> |
56 | <% end %> | 57 | <% end %> |
57 | 58 |
app/views/notices/_backtrace_line.html.haml
1 | %tr{:class => defined?(row_class) && row_class} | 1 | %tr{:class => defined?(row_class) && row_class} |
2 | %td.line{:class => line.in_app? && 'in-app' } | 2 | %td.line{:class => line.in_app? && 'in-app' } |
3 | - = link_to_source_file(line) do | 3 | + = line.link_to_source_file(app) do |
4 | %span.path>= raw line.decorated_path | 4 | %span.path>= raw line.decorated_path |
5 | %span.file>= line.file_name | 5 | %span.file>= line.file_name |
6 | - if line.number.present? | 6 | - if line.number.present? |
spec/acceptance/app_regenerate_api_key_spec.rb
@@ -52,8 +52,8 @@ feature "Create an application" do | @@ -52,8 +52,8 @@ feature "Create an application" do | ||
52 | fill_in 'app_name', :with => 'My new app' | 52 | fill_in 'app_name', :with => 'My new app' |
53 | click_on I18n.t('apps.new.add_app') | 53 | click_on I18n.t('apps.new.add_app') |
54 | page.has_content?(I18n.t('controllers.apps.flash.create.success')) | 54 | page.has_content?(I18n.t('controllers.apps.flash.create.success')) |
55 | - expect(App.where(:name => 'My new app').count).to eql 1 | ||
56 | - expect(App.where(:name => 'My new app 2').count).to eql 0 | 55 | + expect(App.where(:name => 'My new app').count).to eq 1 |
56 | + expect(App.where(:name => 'My new app 2').count).to eq 0 | ||
57 | 57 | ||
58 | 58 | ||
59 | click_on I18n.t('shared.navigation.apps') | 59 | click_on I18n.t('shared.navigation.apps') |
@@ -62,8 +62,8 @@ feature "Create an application" do | @@ -62,8 +62,8 @@ feature "Create an application" do | ||
62 | fill_in 'app_name', :with => 'My new app 2' | 62 | fill_in 'app_name', :with => 'My new app 2' |
63 | click_on I18n.t('apps.edit.update') | 63 | click_on I18n.t('apps.edit.update') |
64 | page.has_content?(I18n.t('controllers.apps.flash.update.success')) | 64 | page.has_content?(I18n.t('controllers.apps.flash.update.success')) |
65 | - expect(App.where(:name => 'My new app').count).to eql 0 | ||
66 | - expect(App.where(:name => 'My new app 2').count).to eql 1 | 65 | + expect(App.where(:name => 'My new app').count).to eq 0 |
66 | + expect(App.where(:name => 'My new app 2').count).to eq 1 | ||
67 | 67 | ||
68 | end | 68 | end |
69 | 69 |
spec/controllers/problems_controller_spec.rb
@@ -145,8 +145,6 @@ describe ProblemsController, type: 'controller' do | @@ -145,8 +145,6 @@ describe ProblemsController, type: 'controller' do | ||
145 | end | 145 | end |
146 | 146 | ||
147 | describe "GET /apps/:app_id/problems/:id" do | 147 | describe "GET /apps/:app_id/problems/:id" do |
148 | - #render_views | ||
149 | - | ||
150 | context 'when logged in as an admin' do | 148 | context 'when logged in as an admin' do |
151 | before do | 149 | before do |
152 | sign_in admin | 150 | sign_in admin |
@@ -250,8 +248,8 @@ describe ProblemsController, type: 'controller' do | @@ -250,8 +248,8 @@ describe ProblemsController, type: 'controller' do | ||
250 | before { sign_in admin } | 248 | before { sign_in admin } |
251 | 249 | ||
252 | context "when app has a issue tracker" do | 250 | context "when app has a issue tracker" do |
253 | - let(:notice) { Fabricate :notice } | ||
254 | - let(:problem) { notice.problem } | 251 | + let(:notice) { NoticeDecorator.new(Fabricate :notice) } |
252 | + let(:problem) { ProblemDecorator.new(notice.problem) } | ||
255 | let(:issue_tracker) do | 253 | let(:issue_tracker) do |
256 | Fabricate(:issue_tracker).tap do |t| | 254 | Fabricate(:issue_tracker).tap do |t| |
257 | t.instance_variable_set(:@tracker, ErrbitPlugin::MockIssueTracker.new(t.options)) | 255 | t.instance_variable_set(:@tracker, ErrbitPlugin::MockIssueTracker.new(t.options)) |
spec/fabricators/err_fabricator.rb
@@ -18,12 +18,11 @@ Fabricator :notice do | @@ -18,12 +18,11 @@ Fabricator :notice do | ||
18 | end | 18 | end |
19 | 19 | ||
20 | Fabricator :backtrace do | 20 | Fabricator :backtrace do |
21 | - lines(:count => 99) { Fabricate.build(:backtrace_line) } | ||
22 | -end | ||
23 | - | ||
24 | -Fabricator :backtrace_line do | ||
25 | - number { rand(999) } | ||
26 | - file { "/path/to/file/#{SecureRandom.hex(4)}.rb" } | ||
27 | - method(:method) { ActiveSupport.methods.shuffle.first } | 21 | + lines(:count => 99) do |
22 | + { | ||
23 | + number: rand(999), | ||
24 | + file: "/path/to/file/#{SecureRandom.hex(4)}.rb", | ||
25 | + method: ActiveSupport.methods.shuffle.first | ||
26 | + } | ||
27 | + end | ||
28 | end | 28 | end |
29 | - |
spec/fabricators/problem_fabricator.rb
@@ -23,8 +23,7 @@ end | @@ -23,8 +23,7 @@ end | ||
23 | 23 | ||
24 | Fabricator(:problem_resolved, :from => :problem) do | 24 | Fabricator(:problem_resolved, :from => :problem) do |
25 | after_create do |pr| | 25 | after_create do |pr| |
26 | - Fabricate(:notice, | ||
27 | - :err => Fabricate(:err, :problem => pr)) | 26 | + Fabricate(:notice, :err => Fabricate(:err, :problem => pr)) |
28 | pr.resolve! | 27 | pr.resolve! |
29 | end | 28 | end |
30 | end | 29 | end |
spec/mailers/mailer_spec.rb
1 | shared_examples "a notification email" do | 1 | shared_examples "a notification email" do |
2 | it "should have X-Mailer header" do | 2 | it "should have X-Mailer header" do |
3 | - expect(@email).to have_header('X-Mailer', 'Errbit') | 3 | + expect(email).to have_header('X-Mailer', 'Errbit') |
4 | end | 4 | end |
5 | 5 | ||
6 | it "should have X-Errbit-Host header" do | 6 | it "should have X-Errbit-Host header" do |
7 | - expect(@email).to have_header('X-Errbit-Host', Errbit::Config.host) | 7 | + expect(email).to have_header('X-Errbit-Host', Errbit::Config.host) |
8 | end | 8 | end |
9 | 9 | ||
10 | it "should have Precedence header" do | 10 | it "should have Precedence header" do |
11 | - expect(@email).to have_header('Precedence', 'bulk') | 11 | + expect(email).to have_header('Precedence', 'bulk') |
12 | end | 12 | end |
13 | 13 | ||
14 | it "should have Auto-Submitted header" do | 14 | it "should have Auto-Submitted header" do |
15 | - expect(@email).to have_header('Auto-Submitted', 'auto-generated') | 15 | + expect(email).to have_header('Auto-Submitted', 'auto-generated') |
16 | end | 16 | end |
17 | 17 | ||
18 | it "should have X-Auto-Response-Suppress header" do | 18 | it "should have X-Auto-Response-Suppress header" do |
19 | # http://msdn.microsoft.com/en-us/library/ee219609(v=EXCHG.80).aspx | 19 | # http://msdn.microsoft.com/en-us/library/ee219609(v=EXCHG.80).aspx |
20 | - expect(@email).to have_header('X-Auto-Response-Suppress', 'OOF, AutoReply') | 20 | + expect(email).to have_header('X-Auto-Response-Suppress', 'OOF, AutoReply') |
21 | end | 21 | end |
22 | 22 | ||
23 | it "should send the email" do | 23 | it "should send the email" do |
24 | |||
24 | expect(ActionMailer::Base.deliveries.size).to eq 1 | 25 | expect(ActionMailer::Base.deliveries.size).to eq 1 |
25 | end | 26 | end |
26 | end | 27 | end |
@@ -30,44 +31,63 @@ describe Mailer do | @@ -30,44 +31,63 @@ describe Mailer do | ||
30 | include EmailSpec::Helpers | 31 | include EmailSpec::Helpers |
31 | include EmailSpec::Matchers | 32 | include EmailSpec::Matchers |
32 | 33 | ||
33 | - let(:notice) { Fabricate(:notice, :message => "class < ActionController::Base") } | ||
34 | - let!(:user) { Fabricate(:admin) } | 34 | + let(:notice) do |
35 | + n = Fabricate(:notice, message: "class < ActionController::Base") | ||
36 | + n.backtrace.lines.last[:file] = '[PROJECT_ROOT]/path/to/file.js' | ||
37 | + # notice.backtrace.update_attributes(lines: lines) | ||
38 | + n | ||
39 | + end | ||
35 | 40 | ||
36 | - before do | ||
37 | - ActionMailer::Base.deliveries = [] | ||
38 | - notice.backtrace.lines.last.update_attributes(:file => "[PROJECT_ROOT]/path/to/file.js") | ||
39 | - notice.app.update_attributes( | 41 | + let(:app) do |
42 | + a = notice.app | ||
43 | + a.update_attributes( | ||
40 | :asset_host => "http://example.com", | 44 | :asset_host => "http://example.com", |
41 | :notify_all_users => true | 45 | :notify_all_users => true |
42 | ) | 46 | ) |
43 | - notice.problem.update_attributes :notices_count => 3 | ||
44 | - | ||
45 | - @email = Mailer.err_notification(notice).deliver | 47 | + a |
48 | + end | ||
49 | + let(:problem) do | ||
50 | + p = notice.problem | ||
51 | + p.notices_count = 3 | ||
52 | + p | ||
53 | + end | ||
54 | + let!(:user) { Fabricate(:admin) } | ||
55 | + let(:error_report) do | ||
56 | + instance_double( | ||
57 | + 'ErrorReport', | ||
58 | + notice: notice, | ||
59 | + app: app, | ||
60 | + problem: problem | ||
61 | + ) | ||
62 | + end | ||
63 | + let(:email) do | ||
64 | + Mailer.err_notification(error_report).deliver | ||
46 | end | 65 | end |
47 | 66 | ||
48 | - it_should_behave_like "a notification email" | 67 | + before { email } |
49 | 68 | ||
69 | + it_should_behave_like "a notification email" | ||
50 | 70 | ||
51 | it "should html-escape the notice's message for the html part" do | 71 | it "should html-escape the notice's message for the html part" do |
52 | - expect(@email).to have_body_text("class < ActionController::Base") | 72 | + expect(email).to have_body_text("class < ActionController::Base") |
53 | end | 73 | end |
54 | 74 | ||
55 | it "should have inline css" do | 75 | it "should have inline css" do |
56 | - expect(@email).to have_body_text('<p class="backtrace" style="') | 76 | + expect(email).to have_body_text('<p class="backtrace" style="') |
57 | end | 77 | end |
58 | 78 | ||
59 | it "should have links to source files" do | 79 | it "should have links to source files" do |
60 | - expect(@email).to have_body_text('<a href="http://example.com/path/to/file.js" target="_blank">path/to/file.js') | 80 | + expect(email).to have_body_text('<a href="http://example.com/path/to/file.js" target="_blank">path/to/file.js') |
61 | end | 81 | end |
62 | 82 | ||
63 | it "should have the error count in the subject" do | 83 | it "should have the error count in the subject" do |
64 | - expect(@email.subject).to match( /^\(3\) / ) | 84 | + expect(email.subject).to match( /^\(3\) / ) |
65 | end | 85 | end |
66 | 86 | ||
67 | context 'with a very long message' do | 87 | context 'with a very long message' do |
68 | let(:notice) { Fabricate(:notice, :message => 6.times.collect{|a| "0123456789" }.join('')) } | 88 | let(:notice) { Fabricate(:notice, :message => 6.times.collect{|a| "0123456789" }.join('')) } |
69 | it "should truncate the long message" do | 89 | it "should truncate the long message" do |
70 | - expect(@email.subject).to match( / \d{47}\.{3}$/ ) | 90 | + expect(email.subject).to match( / \d{47}\.{3}$/ ) |
71 | end | 91 | end |
72 | end | 92 | end |
73 | end | 93 | end |
spec/models/backtrace_line_spec.rb
@@ -1,10 +0,0 @@ | @@ -1,10 +0,0 @@ | ||
1 | -describe BacktraceLine, type: 'model' do | ||
2 | - subject { described_class.new(raw_line) } | ||
3 | - | ||
4 | - describe "root at the start of decorated filename" do | ||
5 | - let(:raw_line) { { 'number' => rand(999), 'file' => '[PROJECT_ROOT]/app/controllers/pages_controller.rb', 'method' => ActiveSupport.methods.shuffle.first.to_s } } | ||
6 | - it "should leave leading root symbol in filepath" do | ||
7 | - expect(subject.decorated_path).to eq 'app/controllers/' | ||
8 | - end | ||
9 | - end | ||
10 | -end |
spec/models/backtrace_spec.rb
1 | describe Backtrace, type: 'model' do | 1 | describe Backtrace, type: 'model' do |
2 | - subject { described_class.new } | ||
3 | - | ||
4 | - its(:fingerprint) { should be_present } | ||
5 | - | ||
6 | - describe "#similar" do | ||
7 | - context "no similar backtrace" do | ||
8 | - its(:similar) { should be_nil } | 2 | + describe '.find_or_create' do |
3 | + let(:lines) do | ||
4 | + [ | ||
5 | + { 'number' => '123', 'file' => '/some/path/to.rb', 'method' => 'abc' }, | ||
6 | + { 'number' => '345', 'file' => '/path/to.rb', 'method' => 'dowhat' } | ||
7 | + ] | ||
9 | end | 8 | end |
9 | + let(:fingerprint) { Backtrace.generate_fingerprint(lines) } | ||
10 | 10 | ||
11 | - context "similar backtrace exist" do | ||
12 | - let!(:similar_backtrace) { | ||
13 | - b = Fabricate(:backtrace) | ||
14 | - b.fingerprint = fingerprint | ||
15 | - b.save! | ||
16 | - b | ||
17 | - } | ||
18 | - let(:fingerprint) { "fingerprint" } | ||
19 | - | ||
20 | - before { allow(subject).to receive(:fingerprint).and_return(fingerprint) } | ||
21 | - | ||
22 | - its(:similar) { should == similar_backtrace } | ||
23 | - end | ||
24 | - end | ||
25 | - | ||
26 | - describe "find_or_create" do | ||
27 | - subject { described_class.find_or_create(attributes) } | ||
28 | - let(:attributes) { double :attributes } | ||
29 | - let(:backtrace) { double :backtrace } | ||
30 | - | ||
31 | - before { allow(described_class).to receive(:new).and_return(backtrace) } | ||
32 | - | ||
33 | - context "no similar backtrace" do | ||
34 | - before { allow(backtrace).to receive(:similar).and_return(nil) } | ||
35 | - it "create new backtrace" do | ||
36 | - expect(described_class).to receive(:create).with(attributes) | 11 | + it 'create new backtrace' do |
12 | + backtrace = described_class.find_or_create(lines) | ||
37 | 13 | ||
38 | - described_class.find_or_create(attributes) | ||
39 | - end | 14 | + expect(backtrace.lines).to eq(lines) |
15 | + expect(backtrace.fingerprint).to eq(fingerprint) | ||
40 | end | 16 | end |
41 | 17 | ||
42 | - context "similar backtrace exist" do | ||
43 | - let(:similar_backtrace) { double :similar_backtrace } | ||
44 | - before { allow(backtrace).to receive(:similar).and_return(similar_backtrace) } | 18 | + it 'creates one backtrace for two identical ones' do |
19 | + described_class.find_or_create(lines) | ||
20 | + described_class.find_or_create(lines) | ||
45 | 21 | ||
46 | - it { should == similar_backtrace } | 22 | + expect(Backtrace.where(fingerprint: fingerprint).count).to eq(1) |
47 | end | 23 | end |
48 | end | 24 | end |
49 | end | 25 | end |
spec/models/error_report_spec.rb
@@ -21,9 +21,7 @@ describe ErrorReport do | @@ -21,9 +21,7 @@ describe ErrorReport do | ||
21 | Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read | 21 | Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read |
22 | } | 22 | } |
23 | 23 | ||
24 | - let(:error_report) { | ||
25 | - ErrorReport.new(xml) | ||
26 | - } | 24 | + let(:error_report) { ErrorReport.new(xml) } |
27 | 25 | ||
28 | let!(:app) { | 26 | let!(:app) { |
29 | Fabricate( | 27 | Fabricate( |
@@ -210,14 +208,13 @@ describe ErrorReport do | @@ -210,14 +208,13 @@ describe ErrorReport do | ||
210 | end | 208 | end |
211 | 209 | ||
212 | it 'find the correct err for the notice' do | 210 | it 'find the correct err for the notice' do |
213 | - err = Fabricate(:err, :problem => Fabricate(:problem, :resolved => true)) | ||
214 | - | ||
215 | - allow(error_report).to receive(:fingerprint).and_return(err.fingerprint) | 211 | + error_report.generate_notice! |
212 | + error_report.problem.resolve! | ||
216 | 213 | ||
217 | expect { | 214 | expect { |
218 | - error_report.generate_notice! | 215 | + ErrorReport.new(xml).generate_notice! |
219 | }.to change { | 216 | }.to change { |
220 | - error_report.error.resolved? | 217 | + error_report.problem.reload.resolved? |
221 | }.from(true).to(false) | 218 | }.from(true).to(false) |
222 | end | 219 | end |
223 | 220 | ||
@@ -227,6 +224,7 @@ describe ErrorReport do | @@ -227,6 +224,7 @@ describe ErrorReport do | ||
227 | app.watchers.build(:email => 'foo@example.com') | 224 | app.watchers.build(:email => 'foo@example.com') |
228 | app.save | 225 | app.save |
229 | end | 226 | end |
227 | + | ||
230 | it 'send email' do | 228 | it 'send email' do |
231 | notice = error_report.generate_notice! | 229 | notice = error_report.generate_notice! |
232 | email = ActionMailer::Base.deliveries.last | 230 | email = ActionMailer::Base.deliveries.last |
spec/models/fingerprint/md5_spec.rb
1 | describe Fingerprint::MD5, type: 'model' do | 1 | describe Fingerprint::MD5, type: 'model' do |
2 | context 'being created' do | 2 | context 'being created' do |
3 | let(:backtrace) do | 3 | let(:backtrace) do |
4 | - Backtrace.create(:raw => [ | 4 | + Backtrace.find_or_create([ |
5 | { | 5 | { |
6 | "number"=>"17", | 6 | "number"=>"17", |
7 | "file"=>"[GEM_ROOT]/gems/activesupport/lib/active_support/callbacks.rb", | 7 | "file"=>"[GEM_ROOT]/gems/activesupport/lib/active_support/callbacks.rb", |
@@ -14,10 +14,9 @@ describe Fingerprint::MD5, type: 'model' do | @@ -14,10 +14,9 @@ describe Fingerprint::MD5, type: 'model' do | ||
14 | 14 | ||
15 | context "with same backtrace" do | 15 | context "with same backtrace" do |
16 | let(:backtrace_2) do | 16 | let(:backtrace_2) do |
17 | - backtrace | ||
18 | - backtrace.lines.last.method = '_run__FRAGMENT__process_action__FRAGMENT__callbacks' | ||
19 | - backtrace.save | ||
20 | - backtrace | 17 | + new_lines = backtrace.lines.dup |
18 | + new_lines.last[:method] = '_run__FRAGMENT__process_action__FRAGMENT__callbacks' | ||
19 | + Backtrace.find_or_create(new_lines) | ||
21 | end | 20 | end |
22 | 21 | ||
23 | it "normalizes the fingerprint of generated methods" do | 22 | it "normalizes the fingerprint of generated methods" do |
@@ -27,10 +26,9 @@ describe Fingerprint::MD5, type: 'model' do | @@ -27,10 +26,9 @@ describe Fingerprint::MD5, type: 'model' do | ||
27 | 26 | ||
28 | context "with same backtrace where FRAGMENT has not been extracted" do | 27 | context "with same backtrace where FRAGMENT has not been extracted" do |
29 | let(:backtrace_2) do | 28 | let(:backtrace_2) do |
30 | - backtrace | ||
31 | - backtrace.lines.last.method = '_run__998857585768765__process_action__1231231312321313__callbacks' | ||
32 | - backtrace.save | ||
33 | - backtrace | 29 | + new_lines = backtrace.lines.dup |
30 | + new_lines.last[:method] = '_run__998857585768765__process_action__1231231312321313__callbacks' | ||
31 | + Backtrace.find_or_create(new_lines) | ||
34 | end | 32 | end |
35 | 33 | ||
36 | it "normalizes the fingerprint of generated methods" do | 34 | it "normalizes the fingerprint of generated methods" do |
spec/models/fingerprint/sha1_spec.rb
1 | describe Fingerprint::Sha1, type: 'model' do | 1 | describe Fingerprint::Sha1, type: 'model' do |
2 | context '#generate' do | 2 | context '#generate' do |
3 | let(:backtrace) { | 3 | let(:backtrace) { |
4 | - Backtrace.create(:raw => [ | 4 | + Backtrace.find_or_create([ |
5 | {"number"=>"425", "file"=>"[GEM_ROOT]/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb", "method"=>"_run__2115867319__process_action__262109504__callbacks"}, | 5 | {"number"=>"425", "file"=>"[GEM_ROOT]/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb", "method"=>"_run__2115867319__process_action__262109504__callbacks"}, |
6 | {"number"=>"404", "file"=>"[GEM_ROOT]/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb", "method"=>"send"}, | 6 | {"number"=>"404", "file"=>"[GEM_ROOT]/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb", "method"=>"send"}, |
7 | {"number"=>"404", "file"=>"[GEM_ROOT]/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb", "method"=>"_run_process_action_callbacks"} | 7 | {"number"=>"404", "file"=>"[GEM_ROOT]/gems/activesupport-3.0.0.rc/lib/active_support/callbacks.rb", "method"=>"_run_process_action_callbacks"} |
@@ -19,11 +19,9 @@ describe Fingerprint::Sha1, type: 'model' do | @@ -19,11 +19,9 @@ describe Fingerprint::Sha1, type: 'model' do | ||
19 | 19 | ||
20 | context "with different backtrace with only last line change" do | 20 | context "with different backtrace with only last line change" do |
21 | let(:backtrace_2) { | 21 | let(:backtrace_2) { |
22 | - backtrace | ||
23 | - backtrace.lines.last.number = 401 | ||
24 | - backtrace.send(:generate_fingerprint) | ||
25 | - backtrace.save | ||
26 | - backtrace | 22 | + new_lines = backtrace.lines.dup |
23 | + new_lines.last[:number] = 401 | ||
24 | + Backtrace.find_or_create backtrace.lines | ||
27 | } | 25 | } |
28 | it 'should not same fingerprint' do | 26 | it 'should not same fingerprint' do |
29 | expect( | 27 | expect( |
spec/spec_helper.rb
1 | # This file is copied to ~/spec when you run 'ruby script/generate rspec' | 1 | # This file is copied to ~/spec when you run 'ruby script/generate rspec' |
2 | # from the project root directory. | 2 | # from the project root directory. |
3 | ENV["RAILS_ENV"] = 'test' | 3 | ENV["RAILS_ENV"] = 'test' |
4 | -ENV["ERRBIT_LOG_LEVEL"] = 'error' | 4 | +ENV["ERRBIT_LOG_LEVEL"] = 'info' |
5 | 5 | ||
6 | if ENV['COVERAGE'] | 6 | if ENV['COVERAGE'] |
7 | require 'coveralls' | 7 | require 'coveralls' |
spec/views/issue_trackers/issue.md.erb_spec.rb
@@ -6,7 +6,7 @@ describe "issue_trackers/issue.md.erb", type: 'view' do | @@ -6,7 +6,7 @@ describe "issue_trackers/issue.md.erb", type: 'view' do | ||
6 | } | 6 | } |
7 | 7 | ||
8 | before do | 8 | before do |
9 | - allow(view).to receive(:problem).and_return(problem) | 9 | + allow(view).to receive(:problem).and_return(ProblemDecorator.new(problem)) |
10 | end | 10 | end |
11 | 11 | ||
12 | it "has the problem url" do | 12 | it "has the problem url" do |
spec/views/issue_trackers/issue.txt.erb_spec.rb
@@ -6,7 +6,8 @@ describe "issue_trackers/issue.txt.erb", type: 'view' do | @@ -6,7 +6,8 @@ describe "issue_trackers/issue.txt.erb", type: 'view' do | ||
6 | } | 6 | } |
7 | 7 | ||
8 | before do | 8 | before do |
9 | - allow(view).to receive(:problem).and_return(problem) | 9 | + allow(view).to receive(:problem).and_return( |
10 | + ProblemDecorator.new(problem)) | ||
10 | end | 11 | end |
11 | 12 | ||
12 | it "has the problem url" do | 13 | it "has the problem url" do |