copy_tuner_client 0.0.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 (58) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +9 -0
  4. data/Appraisals +15 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +161 -0
  7. data/README.md +4 -0
  8. data/Rakefile +28 -0
  9. data/copy_tuner_client.gemspec +33 -0
  10. data/features/rails.feature +270 -0
  11. data/features/step_definitions/copycopter_server_steps.rb +64 -0
  12. data/features/step_definitions/rails_steps.rb +172 -0
  13. data/features/support/env.rb +11 -0
  14. data/features/support/rails_server.rb +124 -0
  15. data/gemfiles/2.3.gemfile +7 -0
  16. data/gemfiles/2.3.gemfile.lock +105 -0
  17. data/gemfiles/3.0.gemfile +7 -0
  18. data/gemfiles/3.0.gemfile.lock +147 -0
  19. data/gemfiles/3.1.gemfile +11 -0
  20. data/gemfiles/3.1.gemfile.lock +191 -0
  21. data/init.rb +1 -0
  22. data/lib/copy_tuner_client/cache.rb +144 -0
  23. data/lib/copy_tuner_client/client.rb +136 -0
  24. data/lib/copy_tuner_client/configuration.rb +224 -0
  25. data/lib/copy_tuner_client/errors.rb +12 -0
  26. data/lib/copy_tuner_client/i18n_backend.rb +92 -0
  27. data/lib/copy_tuner_client/poller.rb +44 -0
  28. data/lib/copy_tuner_client/prefixed_logger.rb +45 -0
  29. data/lib/copy_tuner_client/process_guard.rb +92 -0
  30. data/lib/copy_tuner_client/rails.rb +21 -0
  31. data/lib/copy_tuner_client/railtie.rb +12 -0
  32. data/lib/copy_tuner_client/request_sync.rb +39 -0
  33. data/lib/copy_tuner_client/version.rb +7 -0
  34. data/lib/copy_tuner_client.rb +75 -0
  35. data/lib/tasks/copy_tuner_client_tasks.rake +20 -0
  36. data/spec/copy_tuner_client/cache_spec.rb +273 -0
  37. data/spec/copy_tuner_client/client_spec.rb +236 -0
  38. data/spec/copy_tuner_client/configuration_spec.rb +305 -0
  39. data/spec/copy_tuner_client/i18n_backend_spec.rb +157 -0
  40. data/spec/copy_tuner_client/poller_spec.rb +108 -0
  41. data/spec/copy_tuner_client/prefixed_logger_spec.rb +37 -0
  42. data/spec/copy_tuner_client/process_guard_spec.rb +118 -0
  43. data/spec/copy_tuner_client/request_sync_spec.rb +47 -0
  44. data/spec/copy_tuner_client_spec.rb +19 -0
  45. data/spec/spec_helper.rb +29 -0
  46. data/spec/support/client_spec_helpers.rb +8 -0
  47. data/spec/support/defines_constants.rb +44 -0
  48. data/spec/support/fake_client.rb +53 -0
  49. data/spec/support/fake_copy_tuner_app.rb +175 -0
  50. data/spec/support/fake_html_safe_string.rb +20 -0
  51. data/spec/support/fake_logger.rb +68 -0
  52. data/spec/support/fake_passenger.rb +27 -0
  53. data/spec/support/fake_resque_job.rb +18 -0
  54. data/spec/support/fake_unicorn.rb +13 -0
  55. data/spec/support/middleware_stack.rb +13 -0
  56. data/spec/support/writing_cache.rb +17 -0
  57. data/tmp/projects.json +1 -0
  58. metadata +389 -0
@@ -0,0 +1,64 @@
1
+ require File.join(PROJECT_ROOT, "spec", "support", "fake_copy_tuner_app")
2
+
3
+ Given /^I have a copy_tuner project with an api key of "([^"]*)"$/ do |api_key|
4
+ FakeCopyTunerApp.add_project api_key
5
+ end
6
+
7
+ Given /^the "([^"]*)" project has the following blurbs:$/ do |api_key, table|
8
+ project = FakeCopyTunerApp.project(api_key)
9
+ table.hashes.each do |blurb_hash|
10
+ key = blurb_hash['key']
11
+ data = { 'draft' => { key => blurb_hash['draft content'] },
12
+ 'published' => { key => blurb_hash['published content'] } }
13
+ project.update(data)
14
+ end
15
+ end
16
+
17
+ When /^the the following blurbs are updated in the "([^"]*)" project:$/ do |api_key, table|
18
+ Given %{the "#{api_key}" project has the following blurbs:}, table
19
+ end
20
+
21
+ Then /^the "([^"]*)" project should have the following blurbs:$/ do |api_key, table|
22
+ project = FakeCopyTunerApp.project(api_key)
23
+ table.hashes.each do |blurb_hash|
24
+ key = blurb_hash['key']
25
+
26
+ if blurb_hash['draft content']
27
+ unless project.draft[key] == blurb_hash['draft content']
28
+ raise "Expected #{blurb_hash['draft content']} for #{key} but got #{project.draft[key]}\nExisting keys: #{project.draft.inspect}"
29
+ end
30
+ end
31
+
32
+ if blurb_hash['published content']
33
+ unless project.published[key] == blurb_hash['published content']
34
+ raise "Expected #{blurb_hash['published content']} for #{key} but got #{project.published[key]}\nExisting keys: #{project.published.inspect}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ Then /^the "([^"]*)" project should have the following error blurbs:$/ do |api_key, table|
41
+ prefix = 'en.activerecord.errors.models'
42
+
43
+ rows = table.hashes.map do |error_blurb|
44
+ "| #{prefix}.#{error_blurb['key']} | #{error_blurb['draft content']} |"
45
+ end
46
+
47
+ steps %{
48
+ Then the "#{api_key}" project should have the following blurbs:
49
+ | key | draft content |
50
+ #{rows.join("\n")}
51
+ }
52
+ end
53
+
54
+ Then /^the "([^"]*)" project should not have the "([^"]*)" blurb$/ do |api_key, blurb_key|
55
+ project = FakeCopyTunerApp.project(api_key)
56
+ project.draft[blurb_key].should be_nil
57
+ end
58
+
59
+ When /^I wait for changes to be synchronized$/ do
60
+ sleep(3)
61
+ end
62
+
63
+ FakeCopyTunerApp.start
64
+ After { FakeCopyTunerApp.reset }
@@ -0,0 +1,172 @@
1
+ When "I generate a rails application" do
2
+ if Rails::VERSION::MAJOR == 3
3
+ subcommand = 'new'
4
+ if Rails::VERSION::MINOR == 0
5
+ options = ''
6
+ else
7
+ options = '--skip-bundle'
8
+ end
9
+ else
10
+ subcommand = ''
11
+ options = ''
12
+ end
13
+
14
+ run_simple("rails _#{Rails::VERSION::STRING}_ #{subcommand} testapp #{options}")
15
+ cd("testapp")
16
+
17
+ if Rails::VERSION::MAJOR == 3
18
+ append_to_file("Gemfile", <<-GEMS)
19
+ gem "thin"
20
+ gem "sham_rack"
21
+ gem "sinatra"
22
+ gem "json"
23
+ GEMS
24
+ run_simple("bundle install --local")
25
+
26
+ When %{I remove lines containing "rjs" from "config/environments/development.rb"}
27
+ end
28
+ end
29
+
30
+ When /^I configure the copy_tuner client with api key "([^"]*)"$/ do |api_key|
31
+ write_file("config/initializers/copy_tuner.rb", <<-RUBY)
32
+ CopyTunerClient.configure do |config|
33
+ config.api_key = "#{api_key}"
34
+ config.polling_delay = 1
35
+ config.host = 'localhost'
36
+ config.secure = false
37
+ config.port = #{FakeCopyTunerApp.port}
38
+ end
39
+ RUBY
40
+
41
+ if Rails::VERSION::MAJOR == 3
42
+ append_to_file("Gemfile", <<-GEMS)
43
+ gem "copy_tuner_client", :path => "../../.."
44
+ GEMS
45
+ else
46
+ in_current_dir { FileUtils.rm_f("vendor/plugins/copy_tuner") }
47
+ run_simple("ln -s #{PROJECT_ROOT} vendor/plugins/copy_tuner")
48
+ end
49
+ end
50
+
51
+ When "I start the application" do
52
+ in_current_dir do
53
+ RailsServer.start(ENV['RAILS_PORT'], @announce_stderr)
54
+ end
55
+ end
56
+
57
+ When /^I start the application in the "([^"]+)" environment$/ do |environment|
58
+ in_current_dir do
59
+ old_environment = ENV['RAILS_ENV']
60
+ begin
61
+ ENV['RAILS_ENV'] = environment
62
+ RailsServer.start(ENV['RAILS_PORT'], @announce_stderr)
63
+ ensure
64
+ ENV['RAILS_ENV'] = old_environment
65
+ end
66
+ end
67
+ end
68
+
69
+ When /^I visit (\/.*)$/ do |path|
70
+ @last_response = RailsServer.get(path)
71
+ end
72
+
73
+ When /^I configure the copy_tuner client to use published data$/ do
74
+ in_current_dir do
75
+ config_path = "config/initializers/copy_tuner.rb"
76
+ contents = IO.read(config_path)
77
+ contents.sub!("end", " config.development_environments = []\nend")
78
+ File.open(config_path, "w") { |file| file.write(contents) }
79
+ end
80
+ end
81
+
82
+ When /^I configure the copy_tuner client to have a polling delay of (\d+) seconds$/ do |polling_delay|
83
+ in_current_dir do
84
+ config_path = "config/initializers/copy_tuner.rb"
85
+ contents = IO.read(config_path)
86
+ contents.sub!(/config.polling_delay = .+/, "config.polling_delay = #{polling_delay}")
87
+ File.open(config_path, "w") { |file| file.write(contents) }
88
+ end
89
+ end
90
+
91
+ Then /^the copy_tuner client version and environment should have been logged$/ do
92
+ client_version = CopyTunerClient::VERSION
93
+ environment_info = "[Ruby: #{RUBY_VERSION}]"
94
+ environment_info << " [Rails: #{Rails::VERSION::STRING}]"
95
+ environment_info << " [Env: development]"
96
+ steps %{
97
+ Then the log should contain "Client #{client_version} ready"
98
+ Then the log should contain "Environment Info: #{environment_info}"
99
+ }
100
+ end
101
+
102
+ Then /^the log should contain "([^"]*)"$/ do |line|
103
+ prefix = "** [CopyTuner] "
104
+ pattern = Regexp.compile([Regexp.escape(prefix), Regexp.escape(line)].join(".*"))
105
+ log_path = "log/development.log"
106
+ in_current_dir do
107
+ File.open(log_path) do |file|
108
+ unless file.readlines.any? { |file_line| file_line =~ pattern }
109
+ raise "In log file:\n#{IO.read(log_path)}\n\nMissing line:\n#{pattern}"
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ Then /^the log should not contain "([^"]*)"$/ do |line|
116
+ log_path = "log/development.log"
117
+ in_current_dir do
118
+ File.open(log_path) do |file|
119
+ if bad_line = file.readlines.detect { |file_line| file_line.include?(line) }
120
+ raise "In log file:\n#{log_path}\n\nGot unexpected line:\n#{bad_line}"
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ When /^I successfully rake "([^"]*)"$/ do |task|
127
+ run_simple("rake #{task}")
128
+ end
129
+
130
+ Then /^the response should contain "([^"]+)"$/ do |text|
131
+ @last_response.body.should include(text)
132
+ end
133
+
134
+ When /^I route the "([^"]+)" resource$/ do |resource|
135
+ if Rails::VERSION::MAJOR == 3
136
+ draw = "Testapp::Application.routes.draw do\n"
137
+ else
138
+ draw = "ActionController::Routing::Routes.draw do |map|\nmap."
139
+ end
140
+
141
+ routes = "#{draw}resources :#{resource}\nend"
142
+
143
+ overwrite_file("config/routes.rb", routes)
144
+ end
145
+
146
+ When /^I run a short lived process that sets the key "([^"]*)" to "([^"]*)"$/ do |key, value|
147
+ if Rails::VERSION::MAJOR == 3
148
+ run_simple %[script/rails runner 'I18n.translate("#{key}", :default => "#{value}")']
149
+ else
150
+ run_simple %[script/runner 'I18n.translate("#{key}", :default => "#{value}")']
151
+ end
152
+ end
153
+
154
+ When /^I remove lines containing "([^"]*)" from "([^"]*)"$/ do |content, filename|
155
+ in_current_dir do
156
+ result = ""
157
+ File.open(filename, "r") do |file|
158
+ file.each_line do |line|
159
+ result << line unless line.include?(content)
160
+ end
161
+ end
162
+
163
+ File.open(filename, "w") do |file|
164
+ file.write(result)
165
+ end
166
+ end
167
+ end
168
+
169
+
170
+ After do
171
+ RailsServer.stop
172
+ end
@@ -0,0 +1,11 @@
1
+ require 'sham_rack'
2
+ require 'aruba/cucumber'
3
+ require 'rails/version'
4
+
5
+ PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
6
+ $LOAD_PATH << File.join(PROJECT_ROOT, 'lib')
7
+ require "copy_tuner_client/version"
8
+
9
+ Before do
10
+ @aruba_timeout_seconds = 15
11
+ end
@@ -0,0 +1,124 @@
1
+ require 'net/http'
2
+
3
+ # Starts a Rails application server in a fork and waits for it to be responsive
4
+ class RailsServer
5
+ HOST = 'localhost'.freeze
6
+
7
+ class << self
8
+ attr_accessor :instance
9
+ end
10
+
11
+ def self.start(port = nil, debug = nil)
12
+ self.instance = new(port, debug)
13
+ self.instance.start
14
+ self.instance
15
+ end
16
+
17
+ def self.stop
18
+ self.instance.stop if instance
19
+ self.instance = nil
20
+ end
21
+
22
+ def self.get(path)
23
+ self.instance.get(path)
24
+ end
25
+
26
+ def self.post(path, data)
27
+ self.instance.post(path, data)
28
+ end
29
+
30
+ def self.run(port, silent)
31
+ if silent
32
+ require 'stringio'
33
+ $stdout = StringIO.new
34
+ $stderr = StringIO.new
35
+ end
36
+
37
+ require './config/environment'
38
+ require 'thin'
39
+
40
+ if Rails::VERSION::MAJOR == 3
41
+ rails = Rails.application
42
+ else
43
+ rails = ActionController::Dispatcher.new
44
+ end
45
+ app = Identify.new(rails)
46
+
47
+ Thin::Logging.silent = silent
48
+ Rack::Handler::Thin.run(app, :Port => port, :AccessLog => [])
49
+ end
50
+
51
+ def self.app_host
52
+ self.instance.app_host
53
+ end
54
+
55
+ def initialize(port, debug)
56
+ @port = (port || 3001).to_i
57
+ @debug = debug
58
+ end
59
+
60
+ def start
61
+ @pid = fork do
62
+ command = "ruby -r#{__FILE__} -e 'RailsServer.run(#{@port}, #{(!@debug).inspect})'"
63
+ puts command if @debug
64
+ exec(command)
65
+ end
66
+ wait_until_responsive
67
+ end
68
+
69
+ def stop
70
+ if @pid
71
+ Process.kill('INT', @pid)
72
+ Process.wait(@pid)
73
+ @pid = nil
74
+ end
75
+ end
76
+
77
+ def get(path)
78
+ puts "GET #{path}" if @debug
79
+ Net::HTTP.start(HOST, @port) { |http| http.get(path) }
80
+ end
81
+
82
+ def post(path, data)
83
+ puts "POST #{path}\n#{data}" if @debug
84
+ Net::HTTP.start(HOST, @port) { |http| http.post(path, data) }
85
+ end
86
+
87
+ def wait_until_responsive
88
+ 20.times do
89
+ if responsive?
90
+ return true
91
+ else
92
+ sleep(0.5)
93
+ end
94
+ end
95
+ raise "Couldn't connect to Rails application server at #{HOST}:#{@port}"
96
+ end
97
+
98
+ def responsive?
99
+ response = Net::HTTP.start(HOST, @port) { |http| http.get('/__identify__') }
100
+ response.is_a?(Net::HTTPSuccess)
101
+ rescue Errno::ECONNREFUSED, Errno::EBADF
102
+ return false
103
+ end
104
+
105
+ def app_host
106
+ "http://#{HOST}:#{@port}"
107
+ end
108
+
109
+ # From Capybara::Server
110
+
111
+ class Identify
112
+ def initialize(app)
113
+ @app = app
114
+ end
115
+
116
+ def call(env)
117
+ if env["PATH_INFO"] == "/__identify__"
118
+ [200, {}, 'OK']
119
+ else
120
+ @app.call(env)
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "rails", "2.3.14"
6
+
7
+ gemspec :path=>"../"
@@ -0,0 +1,105 @@
1
+ PATH
2
+ remote: /Users/mat_aki/gem/copy-tuner-ruby-client
3
+ specs:
4
+ copy_tuner_client (0.0.1)
5
+ i18n (>= 0.5.0)
6
+ json
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ actionmailer (2.3.14)
12
+ actionpack (= 2.3.14)
13
+ actionpack (2.3.14)
14
+ activesupport (= 2.3.14)
15
+ rack (~> 1.1.0)
16
+ activerecord (2.3.14)
17
+ activesupport (= 2.3.14)
18
+ activeresource (2.3.14)
19
+ activesupport (= 2.3.14)
20
+ activesupport (2.3.14)
21
+ addressable (2.2.6)
22
+ appraisal (0.4.0)
23
+ bundler
24
+ rake
25
+ aruba (0.3.7)
26
+ childprocess (>= 0.1.9)
27
+ cucumber (>= 0.10.5)
28
+ rspec (>= 2.6.0)
29
+ bourne (1.0)
30
+ mocha (= 0.9.8)
31
+ builder (3.0.0)
32
+ childprocess (0.2.2)
33
+ ffi (~> 1.0.6)
34
+ crack (0.3.1)
35
+ cucumber (0.10.7)
36
+ builder (>= 2.1.2)
37
+ diff-lcs (>= 1.1.2)
38
+ gherkin (~> 2.4.0)
39
+ json (>= 1.4.6)
40
+ term-ansicolor (>= 1.0.5)
41
+ daemons (1.1.4)
42
+ diff-lcs (1.1.3)
43
+ eventmachine (0.12.10)
44
+ ffi (1.0.11)
45
+ gherkin (2.4.21)
46
+ json (>= 1.4.6)
47
+ i18n (0.6.0)
48
+ json (1.6.1)
49
+ mocha (0.9.8)
50
+ rake
51
+ rack (1.1.2)
52
+ rails (2.3.14)
53
+ actionmailer (= 2.3.14)
54
+ actionpack (= 2.3.14)
55
+ activerecord (= 2.3.14)
56
+ activeresource (= 2.3.14)
57
+ activesupport (= 2.3.14)
58
+ rake (>= 0.8.3)
59
+ rake (0.9.2)
60
+ rspec (2.7.0)
61
+ rspec-core (~> 2.7.0)
62
+ rspec-expectations (~> 2.7.0)
63
+ rspec-mocks (~> 2.7.0)
64
+ rspec-core (2.7.1)
65
+ rspec-expectations (2.7.0)
66
+ diff-lcs (~> 1.1.2)
67
+ rspec-mocks (2.7.0)
68
+ sham_rack (1.3.3)
69
+ rack
70
+ sinatra (1.2.7)
71
+ rack (~> 1.1)
72
+ tilt (>= 1.2.2, < 2.0)
73
+ sqlite3 (1.3.4)
74
+ sqlite3-ruby (1.3.3)
75
+ sqlite3 (>= 1.3.3)
76
+ term-ansicolor (1.0.7)
77
+ thin (1.3.1)
78
+ daemons (>= 1.0.9)
79
+ eventmachine (>= 0.12.6)
80
+ rack (>= 1.0.0)
81
+ tilt (1.3.3)
82
+ webmock (1.7.7)
83
+ addressable (~> 2.2, > 2.2.5)
84
+ crack (>= 0.1.7)
85
+ yard (0.7.3)
86
+
87
+ PLATFORMS
88
+ ruby
89
+
90
+ DEPENDENCIES
91
+ appraisal (~> 0.4)
92
+ aruba (~> 0.3.2)
93
+ bourne
94
+ copy_tuner_client!
95
+ cucumber (~> 0.10.0)
96
+ i18n
97
+ rails (= 2.3.14)
98
+ rake (= 0.9.2)
99
+ rspec (~> 2.3)
100
+ sham_rack
101
+ sinatra
102
+ sqlite3-ruby
103
+ thin
104
+ webmock
105
+ yard