projectlocker_pulse 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
+