projectlocker_pulse 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. data/CHANGELOG +26 -0
  2. data/Gemfile +3 -0
  3. data/Guardfile +6 -0
  4. data/INSTALL +20 -0
  5. data/MIT-LICENSE +23 -0
  6. data/README.md +439 -0
  7. data/README_FOR_HEROKU_ADDON.md +89 -0
  8. data/Rakefile +223 -0
  9. data/SUPPORTED_RAILS_VERSIONS +38 -0
  10. data/TESTING.md +41 -0
  11. data/features/metal.feature +18 -0
  12. data/features/rack.feature +60 -0
  13. data/features/rails.feature +272 -0
  14. data/features/rails_with_js_notifier.feature +97 -0
  15. data/features/rake.feature +27 -0
  16. data/features/sinatra.feature +29 -0
  17. data/features/step_definitions/file_steps.rb +10 -0
  18. data/features/step_definitions/metal_steps.rb +23 -0
  19. data/features/step_definitions/rack_steps.rb +23 -0
  20. data/features/step_definitions/rails_application_steps.rb +478 -0
  21. data/features/step_definitions/rake_steps.rb +17 -0
  22. data/features/support/env.rb +18 -0
  23. data/features/support/matchers.rb +35 -0
  24. data/features/support/projectlocker_pulse_shim.rb.template +16 -0
  25. data/features/support/rails.rb +201 -0
  26. data/features/support/rake/Rakefile +68 -0
  27. data/features/support/terminal.rb +107 -0
  28. data/features/user_informer.feature +63 -0
  29. data/generators/pulse/lib/insert_commands.rb +34 -0
  30. data/generators/pulse/lib/rake_commands.rb +24 -0
  31. data/generators/pulse/pulse_generator.rb +94 -0
  32. data/generators/pulse/templates/capistrano_hook.rb +6 -0
  33. data/generators/pulse/templates/initializer.rb +6 -0
  34. data/generators/pulse/templates/pulse_tasks.rake +25 -0
  35. data/install.rb +1 -0
  36. data/lib/projectlocker_pulse.rb +159 -0
  37. data/lib/pulse/backtrace.rb +108 -0
  38. data/lib/pulse/capistrano.rb +43 -0
  39. data/lib/pulse/configuration.rb +305 -0
  40. data/lib/pulse/notice.rb +390 -0
  41. data/lib/pulse/rack.rb +54 -0
  42. data/lib/pulse/rails/action_controller_catcher.rb +30 -0
  43. data/lib/pulse/rails/controller_methods.rb +85 -0
  44. data/lib/pulse/rails/error_lookup.rb +33 -0
  45. data/lib/pulse/rails/javascript_notifier.rb +47 -0
  46. data/lib/pulse/rails/middleware/exceptions_catcher.rb +33 -0
  47. data/lib/pulse/rails.rb +40 -0
  48. data/lib/pulse/rails3_tasks.rb +99 -0
  49. data/lib/pulse/railtie.rb +49 -0
  50. data/lib/pulse/rake_handler.rb +65 -0
  51. data/lib/pulse/sender.rb +128 -0
  52. data/lib/pulse/shared_tasks.rb +47 -0
  53. data/lib/pulse/tasks.rb +83 -0
  54. data/lib/pulse/user_informer.rb +27 -0
  55. data/lib/pulse/utils/blank.rb +53 -0
  56. data/lib/pulse/version.rb +3 -0
  57. data/lib/pulse_tasks.rb +64 -0
  58. data/lib/rails/generators/pulse/pulse_generator.rb +100 -0
  59. data/lib/templates/javascript_notifier.erb +15 -0
  60. data/lib/templates/rescue.erb +91 -0
  61. data/pulse.gemspec +39 -0
  62. data/rails/init.rb +1 -0
  63. data/resources/README.md +34 -0
  64. data/resources/ca-bundle.crt +3376 -0
  65. data/script/integration_test.rb +38 -0
  66. data/test/backtrace_test.rb +162 -0
  67. data/test/capistrano_test.rb +34 -0
  68. data/test/catcher_test.rb +333 -0
  69. data/test/configuration_test.rb +236 -0
  70. data/test/helper.rb +263 -0
  71. data/test/javascript_notifier_test.rb +51 -0
  72. data/test/logger_test.rb +79 -0
  73. data/test/notice_test.rb +490 -0
  74. data/test/notifier_test.rb +276 -0
  75. data/test/projectlocker_pulse_tasks_test.rb +170 -0
  76. data/test/pulse.xsd +88 -0
  77. data/test/rack_test.rb +58 -0
  78. data/test/rails_initializer_test.rb +36 -0
  79. data/test/recursion_test.rb +10 -0
  80. data/test/sender_test.rb +288 -0
  81. data/test/user_informer_test.rb +29 -0
  82. metadata +432 -0
@@ -0,0 +1,97 @@
1
+ Feature: Install the Gem in a Rails application and enable the JavaScript notifier
2
+
3
+ Background:
4
+ Given I have built and installed the "projectlocker-pulse" gem
5
+
6
+ Scenario: Include the Javascript notifier when enabled
7
+ When I generate a new Rails application
8
+ And I configure the Pulse shim
9
+ And I configure my application to require the "projectlocker-pulse" gem
10
+ When I configure the notifier to use the following configuration lines:
11
+ """
12
+ config.api_key = "myapikey"
13
+ """
14
+ And I define a response for "TestController#index":
15
+ """
16
+ render :inline => '<html><head profile="http://example.com"><%= pulse_javascript_notifier %></head><body></body></html>'
17
+ """
18
+ And I route "/test/index" to "test#index"
19
+ And I perform a request to "http://example.com:123/test/index"
20
+ Then I should see the notifier JavaScript for the following:
21
+ | api_key | environment | host |
22
+ | myapikey | production | api.pulse.io |
23
+ And the notifier JavaScript should provide the following errorDefaults:
24
+ | url | component | action |
25
+ | http://example.com:123/test/index | test | index |
26
+
27
+ Scenario: Include the Javascript notifier when enabled using custom configuration settings
28
+ When I generate a new Rails application
29
+ And I configure the Pulse shim
30
+ And I configure my application to require the "projectlocker-pulse" gem
31
+ When I configure the notifier to use the following configuration lines:
32
+ """
33
+ config.api_key = "myapikey!"
34
+ config.host = "mypulse.com"
35
+ config.port = 3001
36
+ """
37
+ And I define a response for "TestController#index":
38
+ """
39
+ render :inline => '<html><head><%= pulse_javascript_notifier %></head><body></body></html>'
40
+ """
41
+ And I route "/test/index" to "test#index"
42
+ And I perform a request to "http://example.com:123/test/index"
43
+ Then I should see the notifier JavaScript for the following:
44
+ | api_key | environment | host |
45
+ | myapikey! | production | mypulse.com:3001 |
46
+
47
+ Scenario: Don't include the Javascript notifier by default
48
+ When I generate a new Rails application
49
+ And I configure the Pulse shim
50
+ And I configure my application to require the "projectlocker-pulse" gem
51
+ When I configure the notifier to use the following configuration lines:
52
+ """
53
+ config.api_key = "myapikey!"
54
+ """
55
+ And I define a response for "TestController#index":
56
+ """
57
+ render :inline => "<html><head></head><body></body></html>"
58
+ """
59
+ And I route "/test/index" to "test#index"
60
+ And I perform a request to "http://example.com:123/test/index"
61
+ Then I should not see notifier JavaScript
62
+
63
+ Scenario: Don't include the Javascript notifier when enabled in non-public environments
64
+ When I generate a new Rails application
65
+ And I configure the Pulse shim
66
+ And I configure my application to require the "projectlocker-pulse" gem
67
+ When I configure the notifier to use the following configuration lines:
68
+ """
69
+ config.api_key = "myapikey!"
70
+ config.environment_name = 'test'
71
+ """
72
+ And I define a response for "TestController#index":
73
+ """
74
+ render :inline => '<html><head><%= pulse_javascript_notifier %></head><body></body></html>'
75
+ """
76
+ And I route "/test/index" to "test#index"
77
+ And I perform a request to "http://example.com:123/test/index" in the "test" environment
78
+ Then I should not see notifier JavaScript
79
+
80
+ Scenario: Include the Javascript notifier with a custom api key
81
+ When I generate a new Rails application
82
+ And I configure the Pulse shim
83
+ And I configure my application to require the "projectlocker-pulse" gem
84
+ When I configure the notifier to use the following configuration lines:
85
+ """
86
+ config.api_key = "myapikey!"
87
+ config.js_api_key = "myjsapikey!"
88
+ """
89
+ And I define a response for "TestController#index":
90
+ """
91
+ render :inline => '<html><head><%= pulse_javascript_notifier %></head><body></body></html>'
92
+ """
93
+ And I route "/test/index" to "test#index"
94
+ And I perform a request to "http://example.com:123/test/index"
95
+ Then I should see the notifier JavaScript for the following:
96
+ | api_key | environment | host |
97
+ | myjsapikey! | production | api.pulse.io |
@@ -0,0 +1,27 @@
1
+ Feature: Use the Gem to catch errors in a Rake application
2
+ Background:
3
+ Given I have built and installed the "projectlocker-pulse" gem
4
+
5
+ Scenario: Catching exceptions in Rake
6
+ When I run rake with pulse
7
+ Then Pulse should catch the exception
8
+
9
+ Scenario: Falling back to default handler before Pulse is configured
10
+ When I run rake with pulse not yet configured
11
+ Then Pulse should not catch the exception
12
+
13
+ Scenario: Disabling Rake exception catcher
14
+ When I run rake with pulse disabled
15
+ Then Pulse should not catch the exception
16
+
17
+ Scenario: Autodetect, running from terminal
18
+ When I run rake with pulse autodetect from terminal
19
+ Then Pulse should not catch the exception
20
+
21
+ Scenario: Autodetect, not running from terminal
22
+ When I run rake with pulse autodetect not from terminal
23
+ Then Pulse should catch the exception
24
+
25
+ Scenario: Sending the correct component name
26
+ When I run rake with pulse
27
+ Then Pulse should send the rake command line as the component name
@@ -0,0 +1,29 @@
1
+ Feature: Use the notifier in a Sinatra app
2
+
3
+ Background:
4
+ Given I have built and installed the "projectlocker-pulse" gem
5
+
6
+ Scenario: Rescue an exception in a Sinatra app
7
+ Given the following Rack app:
8
+ """
9
+ require 'sinatra/base'
10
+ require 'projectlocker_pulse'
11
+
12
+ Pulse.configure do |config|
13
+ config.api_key = 'my_api_key'
14
+ end
15
+
16
+ class FontaneApp < Sinatra::Base
17
+ use Pulse::Rack
18
+ enable :raise_errors
19
+
20
+ get "/test/index" do
21
+ raise "Sinatra has left the building"
22
+ end
23
+ end
24
+
25
+ app = FontaneApp
26
+ """
27
+ When I perform a Rack request to "http://example.com:123/test/index?param=value"
28
+ Then I should receive a Pulse notification
29
+
@@ -0,0 +1,10 @@
1
+ Then /^"([^\"]*)" should not contain text of "([^\"]*)"$/ do |target_file, contents_file|
2
+ notifier_root = File.join(File.dirname(__FILE__), '..', '..')
3
+ full_path_contents = File.join(notifier_root, contents_file)
4
+ contents_text = File.open(full_path_contents).read
5
+
6
+ full_path_target = File.join(rails_root, target_file)
7
+ target_text = File.open(full_path_target).read
8
+
9
+ target_text.should_not include(contents_text)
10
+ end
@@ -0,0 +1,23 @@
1
+ When /^I define a Metal endpoint called "([^\"]*)":$/ do |class_name, definition|
2
+ FileUtils.mkdir_p(File.join(rails_root, 'app', 'metal'))
3
+ file_name = File.join(rails_root, 'app', 'metal', "#{class_name.underscore}.rb")
4
+ File.open(file_name, "w") do |file|
5
+ file.puts "class #{class_name}"
6
+ file.puts definition
7
+ file.puts "end"
8
+ end
9
+ When %{the metal endpoint "#{class_name}" is mounted in the Rails 3 routes.rb} if rails3?
10
+ end
11
+
12
+ When /^the metal endpoint "([^\"]*)" is mounted in the Rails 3 routes.rb$/ do |class_name|
13
+ routesrb = File.join(rails_root, "config", "routes.rb")
14
+ routes = IO.readlines(routesrb)
15
+ rack_route = "match '/metal(/*other)' => #{class_name}"
16
+ routes = routes[0..-2] + [rack_route, routes[-1]]
17
+ File.open(routesrb, "w") do |f|
18
+ f.puts "require 'app/metal/#{class_name.underscore}'"
19
+ routes.each do |route_line|
20
+ f.puts route_line
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ Given /^the following Rack app:$/ do |definition|
2
+ File.open(RACK_FILE, 'w') { |file| file.write(definition) }
3
+ end
4
+
5
+ When /^I perform a Rack request to "([^\"]*)"$/ do |url|
6
+ shim_file = File.join(PROJECT_ROOT, 'features', 'support', 'airbrake_shim.rb.template')
7
+ request_file = File.join(TEMP_DIR, 'rack_request.rb')
8
+ File.open(request_file, 'w') do |file|
9
+ file.puts "require 'rubygems'"
10
+ file.puts IO.read(shim_file)
11
+ file.puts IO.read(RACK_FILE)
12
+ file.puts "env = Rack::MockRequest.env_for(#{url.inspect})"
13
+ file.puts "status, headers, body = app.call(env)"
14
+ file.puts %{puts "HTTP \#{status}"}
15
+ file.puts %{headers.each { |key, value| puts "\#{key}: \#{value}"}}
16
+ file.puts "body.each { |part| print part }"
17
+ end
18
+ @terminal.run("ruby #{request_file}")
19
+ end
20
+
21
+ Then /^I should receive a Pulse notification for rack$/ do
22
+ Then %{I should see "You have accessed a deleted account."}
23
+ end
@@ -0,0 +1,478 @@
1
+ require 'uri'
2
+ require 'active_support/core_ext/string/inflections'
3
+
4
+ Given /^I have built and installed the "([^\"]*)" gem$/ do |gem_name|
5
+ @terminal.build_and_install_gem(File.join(PROJECT_ROOT, "#{gem_name}.gemspec"))
6
+ end
7
+
8
+ Given /^PENDING/ do
9
+ pending
10
+ end
11
+
12
+ Given /^Pulse server is not responding$/ do
13
+ bundle_gem("sham_rack")
14
+ content = <<-CONTENT
15
+ require 'sham_rack'
16
+
17
+ Pulse.configuration.logger = Logger.new STDOUT
18
+
19
+ ShamRack.at("errors.projectlocker.com") {["500", { "Content-type" => "text/xml" }, ["Internal server error"]]}
20
+
21
+ CONTENT
22
+ target = File.join(rails_root, 'config', 'initializers', 'pulse_shim.rb')
23
+ File.open(target,"w") { |f| f.write content }
24
+ end
25
+
26
+ When /^I generate a new Rails application$/ do
27
+ @terminal.cd(TEMP_DIR)
28
+
29
+ rails3 = version_string =~ /^3/
30
+
31
+ if rails3
32
+ rails_create_command = 'new'
33
+ else
34
+ rails_create_command = ''
35
+ end
36
+
37
+ load_rails = <<-RUBY
38
+ gem 'rails', '#{version_string}'; \
39
+ load Gem.bin_path('#{version_string >= "3.2.0" ? "railties" : "rails"}', 'rails', '#{version_string}')
40
+ RUBY
41
+
42
+ @terminal.run(%{ruby -rrubygems -rthread -e "#{load_rails.strip!}" #{rails_create_command} rails_root})
43
+ if rails_root_exists?
44
+ @terminal.echo("Generated a Rails #{version_string.strip} application")
45
+ else
46
+ raise "Unable to generate a Rails application:\n#{@terminal.output}"
47
+ end
48
+ require_thread
49
+ if version_string >= "3.1.0"
50
+ When %{I configure my application to require the "therubyracer" gem with version "0.10.1"}
51
+ elsif version_string =~ /2.3.14/
52
+ monkeypatch_old_version
53
+ end
54
+ config_gem_dependencies unless rails3
55
+ end
56
+
57
+ When /^I run the pulse generator with "([^\"]*)"$/ do |generator_args|
58
+ if rails3?
59
+ When %{I run "./script/rails generate pulse #{generator_args}"}
60
+ else
61
+ When %{I run "./script/generate pulse #{generator_args}"}
62
+ end
63
+ end
64
+
65
+ When /^I print the console output$/ do
66
+ puts @terminal.output
67
+ end
68
+
69
+ Given /^I have installed the "([^\"]*)" gem$/ do |gem_name|
70
+ @terminal.install_gem(gem_name)
71
+ end
72
+
73
+
74
+ When /^I configure my application to require the "capistrano" gem if necessary$/ do
75
+ When %{I configure my application to require the "capistrano" gem} if version_string >= "3.0.0"
76
+ end
77
+
78
+ When /^I configure my application to require the "([^\"]*)" gem(?: with version "(.+)")?$/ do |gem_name, version|
79
+ if rails_manages_gems?
80
+ config_gem(gem_name, version)
81
+ elsif bundler_manages_gems?
82
+ bundle_gem(gem_name, version)
83
+ else
84
+ File.open(environment_path, 'a') do |file|
85
+ file.puts
86
+ file.puts("require 'projectlocker_pulse'")
87
+ file.puts("require 'pulse/rails'")
88
+ end
89
+
90
+ unless rails_finds_generators_in_gems?
91
+ FileUtils.cp_r(File.join(PROJECT_ROOT, 'generators'), File.join(rails_root, 'lib'))
92
+ end
93
+ end
94
+ end
95
+
96
+ When /^I run "([^\"]*)"$/ do |command|
97
+ @terminal.cd(rails_root)
98
+ @terminal.run(command)
99
+ end
100
+
101
+ Then /^I should( not)? receive a Pulse notification$/ do |or_should_not|
102
+ Then %{I should#{or_should_not} see "** [Pulse] Response from Pulse:"}
103
+ And %{I should#{or_should_not} see "b6817316-9c45-ed26-45eb-780dbb86aadb"}
104
+ And %{I should#{or_should_not} see "http://errors.projectlocker.com/locate/b6817316-9c45-ed26-45eb-780dbb86aadb"}
105
+ end
106
+
107
+ Then /^I should receive two Pulse notifications$/ do
108
+ @terminal.output.scan(/\[Pulse\] Response from Pulse:/).size.should == 2
109
+ end
110
+
111
+ When /^I configure the Pulse shim$/ do
112
+ if bundler_manages_gems?
113
+ bundle_gem("sham_rack")
114
+ end
115
+ shim_file = File.join(PROJECT_ROOT, 'features', 'support', 'pulse_shim.rb.template')
116
+ if rails_supports_initializers?
117
+ target = File.join(rails_root, 'config', 'initializers', 'pulse_shim.rb')
118
+ FileUtils.cp(shim_file, target)
119
+ else
120
+ File.open(environment_path, 'a') do |file|
121
+ file.puts
122
+ file.write IO.read(shim_file)
123
+ end
124
+ end
125
+ target = File.join(rails_root, 'config', 'initializers', 'pulse_shim.rb')
126
+ FileUtils.cp(shim_file, target)
127
+ end
128
+
129
+ When /^I configure the notifier to use "([^\"]*)" as an API key$/ do |api_key|
130
+ steps %{
131
+ When I configure the notifier to use the following configuration lines:
132
+ """
133
+ config.api_key = #{api_key.inspect}
134
+ """
135
+ }
136
+ end
137
+
138
+ When /^I configure the notifier to use the following configuration lines:$/ do |configuration_lines|
139
+ if rails_manages_gems?
140
+ requires = ''
141
+ else
142
+ requires = "require 'projectlocker_pulse'"
143
+ end
144
+
145
+ initializer_code = <<-EOF
146
+ #{requires}
147
+ Pulse.configure do |config|
148
+ #{configuration_lines}
149
+ end
150
+ EOF
151
+
152
+ if rails_supports_initializers?
153
+ File.open(rails_initializer_file, 'w') { |file| file.write(initializer_code) }
154
+ else
155
+ File.open(environment_path, 'a') do |file|
156
+ file.puts
157
+ file.puts initializer_code
158
+ end
159
+ end
160
+
161
+ end
162
+
163
+ def rails_initializer_file
164
+ File.join(rails_root, 'config', 'initializers', 'pulse.rb')
165
+ end
166
+
167
+ def rails_non_initializer_pulse_config_file
168
+ File.join(rails_root, 'config', 'pulse.rb')
169
+ end
170
+
171
+ Then /^I should see "([^\"]*)"$/ do |expected_text|
172
+ unless @terminal.output.include?(expected_text)
173
+ raise("Got terminal output:\n#{@terminal.output}\n\nExpected output:\n#{expected_text}")
174
+ end
175
+ end
176
+
177
+ Then /^I should not see "([^\"]*)"$/ do |unexpected_text|
178
+ if @terminal.output.include?(unexpected_text)
179
+ raise("Got terminal output:\n#{@terminal.output}\n\nDid not expect the following output:\n#{unexpected_text}")
180
+ end
181
+ end
182
+
183
+ When /^I uninstall the "([^\"]*)" gem$/ do |gem_name|
184
+ @terminal.uninstall_gem(gem_name)
185
+ end
186
+
187
+ When /^I unpack the "([^\"]*)" gem$/ do |gem_name|
188
+ if bundler_manages_gems?
189
+ @terminal.cd(rails_root)
190
+ @terminal.run("bundle pack")
191
+ elsif rails_manages_gems?
192
+ @terminal.cd(rails_root)
193
+ @terminal.run("rake gems:unpack GEM=#{gem_name}")
194
+ else
195
+ vendor_dir = File.join(rails_root, 'vendor', 'gems')
196
+ FileUtils.mkdir_p(vendor_dir)
197
+ @terminal.cd(vendor_dir)
198
+ @terminal.run("gem unpack #{gem_name}")
199
+ gem_path =
200
+ Dir.glob(File.join(rails_root, 'vendor', 'gems', "#{gem_name}-*", 'lib')).first
201
+ File.open(environment_path, 'a') do |file|
202
+ file.puts
203
+ file.puts("$: << #{gem_path.inspect}")
204
+ end
205
+ end
206
+ end
207
+
208
+ When /^I install cached gems$/ do
209
+ if bundler_manages_gems?
210
+ Then %{I run "bundle install"}
211
+ end
212
+ end
213
+
214
+ When /^I install the "([^\"]*)" plugin$/ do |plugin_name|
215
+ FileUtils.mkdir_p("#{rails_root}/vendor/plugins/#{plugin_name}")
216
+ end
217
+
218
+ When /^I define a response for "([^\"]*)":$/ do |controller_and_action, definition|
219
+ controller_class_name, action = controller_and_action.split('#')
220
+ controller_name = controller_class_name.underscore
221
+ controller_file_name = File.join(rails_root, 'app', 'controllers', "#{controller_name}.rb")
222
+ File.open(controller_file_name, "w") do |file|
223
+ file.puts "class #{controller_class_name} < ApplicationController"
224
+ file.puts "def consider_all_requests_local; false; end"
225
+ file.puts "def local_request?; false; end"
226
+ file.puts "def #{action}"
227
+ file.puts definition
228
+ file.puts "end"
229
+ file.puts "end"
230
+ end
231
+ end
232
+
233
+ When /^I perform a request to "([^\"]*)"$/ do |uri|
234
+ perform_request(uri)
235
+ end
236
+
237
+ When /^I perform a request to "([^\"]*)" in the "([^\"]*)" environment$/ do |uri, environment|
238
+ perform_request(uri, environment)
239
+ end
240
+
241
+ Given /^the response page for a "([^\"]*)" error is$/ do |error, html|
242
+ File.open(File.join(rails_root, "public", "#{error}.html"), "w") do |file|
243
+ file.write(html)
244
+ end
245
+ end
246
+
247
+ Then /^I should receive the following Pulse notification:$/ do |table|
248
+ exceptions = @terminal.output.scan(%r{Recieved the following exception:\n([^\n]*)\n}m)
249
+ exceptions.should_not be_empty
250
+
251
+ xml = exceptions.last[0]
252
+ doc = Nokogiri::XML.parse(xml)
253
+
254
+ hash = table.transpose.hashes.first
255
+
256
+ doc.should have_content('//error/message', hash['error message'])
257
+ doc.should have_content('//error/class', hash['error class'])
258
+ doc.should have_content('//request/url', hash['url'])
259
+
260
+ doc.should have_content('//component', hash['component']) if hash['component']
261
+ doc.should have_content('//action', hash['action']) if hash['action']
262
+ doc.should have_content('//server-environment/project-root', hash['project-root']) if hash['project-root']
263
+
264
+ if hash['session']
265
+ session_key, session_value = hash['session'].split(': ')
266
+ doc.should have_content('//request/session/var/@key', session_key)
267
+ doc.should have_content('//request/session/var', session_value)
268
+ end
269
+
270
+ if hash['parameters']
271
+ param_key, param_value = hash['parameters'].split(': ')
272
+ doc.should have_content('//request/params/var/@key', param_key)
273
+ doc.should have_content('//request/params/var', param_value)
274
+ end
275
+ end
276
+
277
+ Then /^I should see the Rails version$/ do
278
+ Then %{I should see "[Rails: #{rails_version}]"}
279
+ end
280
+
281
+ Then /^I should see that "([^\"]*)" is not considered a framework gem$/ do |gem_name|
282
+ Then %{I should not see "[R] #{gem_name}"}
283
+ end
284
+
285
+ Then /^the command should have run successfully$/ do
286
+ @terminal.status.exitstatus.should == 0
287
+ end
288
+
289
+ When /^I route "([^\"]*)" to "([^\"]*)"$/ do |path, controller_action_pair|
290
+ route = if rails3?
291
+ %(match "#{path}", :to => "#{controller_action_pair}")
292
+ else
293
+ controller, action = controller_action_pair.split('#')
294
+ %(map.connect "#{path}", :controller => "#{controller}", :action => "#{action}")
295
+ end
296
+ routes_file = File.join(rails_root, "config", "routes.rb")
297
+ File.open(routes_file, "r+") do |file|
298
+ content = file.read
299
+ content.gsub!(/^end$/, " #{route}\nend")
300
+ file.rewind
301
+ file.write(content)
302
+ end
303
+ end
304
+
305
+ Then /^"([^\"]*)" should not contain "([^\"]*)"$/ do |file_path, text|
306
+ actual_text = IO.read(File.join(rails_root, file_path))
307
+ if actual_text.include?(text)
308
+ raise "Didn't expect text:\n#{actual_text}\nTo include:\n#{text}"
309
+ end
310
+ end
311
+
312
+ Then /^my Pulse configuration should contain the following line:$/ do |line|
313
+ configuration_file = if rails_supports_initializers?
314
+ rails_initializer_file
315
+ else
316
+ rails_non_initializer_pulse_config_file
317
+ # environment_path
318
+ end
319
+
320
+ configuration = File.read(configuration_file)
321
+ if ! configuration.include?(line.strip)
322
+ raise "Expected text:\n#{configuration}\nTo include:\n#{line}\nBut it didn't."
323
+ end
324
+ end
325
+
326
+ When /^I set the environment variable "([^\"]*)" to "([^\"]*)"$/ do |environment_variable, value|
327
+ @terminal.environment_variables[environment_variable] = value
328
+ end
329
+
330
+ When /^I configure the Heroku rake shim$/ do
331
+ @terminal.invoke_heroku_rake_tasks_locally = true
332
+ end
333
+
334
+ When /^I configure the Heroku gem shim with "([^\"]*)"( and multiple app support)?$/ do |api_key, multi_app|
335
+ heroku_script_bin = File.join(TEMP_DIR, "bin")
336
+ FileUtils.mkdir_p(heroku_script_bin)
337
+ heroku_script = File.join(heroku_script_bin, "heroku")
338
+ heroku_env_vars = <<-VARS
339
+ PROJECTLOCKER_ERRATA_API_KEY => myapikey
340
+ APP_NAME => cold-moon-2929
341
+ BUNDLE_WITHOUT => development:test
342
+ COMMIT_HASH => lj32j42ss9332jfa2
343
+ DATABASE_URL => postgres://fchovwjcyb:QLPVWmBBbf4hCG_YMrtV@ec3-107-28-193-23.compute-1.amazonaws.com/fhcvojwwcyb
344
+ LANG => en_US.UTF-8
345
+ LAST_GIT_BY => kensa
346
+ RACK_ENV => production
347
+ SHARED_DATABASE_URL => postgres://fchovwjcyb:QLPVwMbbbF8Hcg_yMrtV@ec2-94-29-181-224.compute-1.amazonaws.com/fhcvojcwwyb
348
+ STACK => bamboo-mri-1.9.2
349
+ URL => cold-moon-2929.heroku.com
350
+ VARS
351
+ single_app_script = <<-SINGLE
352
+ #!/bin/bash
353
+ if [ $1 == 'config' ]
354
+ then
355
+ echo "#{heroku_env_vars}"
356
+ fi
357
+ SINGLE
358
+
359
+ multi_app_script = <<-MULTI
360
+ #!/bin/bash
361
+ if [[ $1 == 'config' && $2 == '--app' ]]
362
+ then
363
+ echo "#{heroku_env_vars}"
364
+ fi
365
+ MULTI
366
+
367
+ File.open(heroku_script, "w") do |f|
368
+ if multi_app
369
+ f.puts multi_app_script
370
+ else
371
+ f.puts single_app_script
372
+ end
373
+ end
374
+ FileUtils.chmod(0755, heroku_script)
375
+ @terminal.prepend_path(heroku_script_bin)
376
+ end
377
+
378
+ When /^I configure the application to filter parameter "([^\"]*)"$/ do |parameter|
379
+ if rails3?
380
+ application_filename = File.join(rails_root, 'config', 'application.rb')
381
+ application_lines = File.open(application_filename).readlines
382
+
383
+ application_definition_line = application_lines.detect { |line| line =~ /Application/ }
384
+ application_definition_line_index = application_lines.index(application_definition_line)
385
+
386
+ application_lines.insert(application_definition_line_index + 1,
387
+ " config.filter_parameters += [#{parameter.inspect}]")
388
+
389
+ File.open(application_filename, "w") do |file|
390
+ file.puts application_lines.join("\n")
391
+ end
392
+ else
393
+ controller_filename = application_controller_filename
394
+ controller_lines = File.open(controller_filename).readlines
395
+
396
+ controller_definition_line = controller_lines.detect { |line| line =~ /ApplicationController/ }
397
+ controller_definition_line_index = controller_lines.index(controller_definition_line)
398
+
399
+ controller_lines.insert(controller_definition_line_index + 1,
400
+ " filter_parameter_logging #{parameter.inspect}")
401
+
402
+ File.open(controller_filename, "w") do |file|
403
+ file.puts controller_lines.join("\n")
404
+ end
405
+ end
406
+ end
407
+
408
+ Then /^I should see the notifier JavaScript for the following:$/ do |table|
409
+ hash = table.hashes.first
410
+ host = hash['host'] || 'errors.projectlocker.com'
411
+ secure = hash['secure'] || false
412
+ api_key = hash['api_key']
413
+ environment = hash['environment'] || 'production'
414
+
415
+ document_body = '<html>' + @terminal.output.split('<html>').last
416
+ document_body.should include("#{host}/javascripts/notifier.js")
417
+
418
+ response = Nokogiri::HTML.parse(document_body)
419
+ response.css("script[type='text/javascript']:last-child").each do |element|
420
+ content = element.content
421
+ content.should include("Pulse.setKey('#{api_key}');")
422
+ content.should include("Pulse.setHost('#{host}');")
423
+ content.should include("Pulse.setEnvironment('#{environment}');")
424
+ end
425
+ end
426
+
427
+ Then "the notifier JavaScript should provide the following errorDefaults:" do |table|
428
+ hash = table.hashes.first
429
+
430
+ document_body = '<html>' + @terminal.output.split('<html>').last
431
+
432
+ response = Nokogiri::HTML.parse(document_body)
433
+ response.css("script[type='text/javascript']:last-child").each do |element|
434
+ content = element.content
435
+
436
+ hash.each do |key, value|
437
+ content.should =~ %r{Pulse\.setErrorDefaults.*#{key}: "#{value}}m
438
+ end
439
+ end
440
+ end
441
+
442
+ Then /^I should not see notifier JavaScript$/ do
443
+ response = Nokogiri::HTML.parse('<html>' + @terminal.output.split('<html>').last)
444
+ response.at_css("script[type='text/javascript'][src$='/javascripts/notifier.js']").should be_nil
445
+ end
446
+
447
+
448
+ When /^I configure usage of Pulse$/ do
449
+ When %{I configure my application to require the "projectlocker-pulse" gem}
450
+ When %{I run the pulse generator with "-k myapikey"}
451
+ @terminal.flush! # flush the results of setting up Pulse (generates notification)
452
+ end
453
+
454
+
455
+ When /^I have set up authentication system in my app that uses "([^\"]*)"$/ do |current_user|
456
+ application_controller = File.join(rails_root, 'app', 'controllers', "application_controller.rb")
457
+ definition =
458
+ """
459
+ class ApplicationController < ActionController::Base
460
+ def consider_all_requests_local; false; end
461
+ def local_request?; false; end
462
+
463
+ # this is the ultimate authentication system, devise is history
464
+ def #{current_user}
465
+ Struct.new(:attributes).new({:id => 1,:name => 'Bender',:email => 'bender@beer.com',:username => 'b3nd0r'})
466
+ end
467
+ end
468
+ """
469
+ File.open(application_controller, "w") {|file| file.puts definition }
470
+ end
471
+
472
+ Then /^the Pulse notification should contain user details$/ do
473
+ Then %{I should see "Bender"}
474
+ And %{I should see "bender@beer.com"}
475
+ And %{I should see "<id>1</id>"}
476
+ And %{I should see "b3nd0r"}
477
+ end
478
+