copycopter_client 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.textile +71 -0
  3. data/Rakefile +38 -0
  4. data/features/rails.feature +267 -0
  5. data/features/step_definitions/copycopter_server_steps.rb +65 -0
  6. data/features/step_definitions/rails_steps.rb +134 -0
  7. data/features/support/env.rb +8 -0
  8. data/features/support/rails_server.rb +118 -0
  9. data/init.rb +2 -0
  10. data/lib/copycopter_client/client.rb +117 -0
  11. data/lib/copycopter_client/configuration.rb +197 -0
  12. data/lib/copycopter_client/errors.rb +13 -0
  13. data/lib/copycopter_client/helper.rb +40 -0
  14. data/lib/copycopter_client/i18n_backend.rb +100 -0
  15. data/lib/copycopter_client/prefixed_logger.rb +41 -0
  16. data/lib/copycopter_client/rails.rb +31 -0
  17. data/lib/copycopter_client/railtie.rb +13 -0
  18. data/lib/copycopter_client/sync.rb +145 -0
  19. data/lib/copycopter_client/version.rb +8 -0
  20. data/lib/copycopter_client.rb +58 -0
  21. data/lib/tasks/copycopter_client_tasks.rake +6 -0
  22. data/spec/copycopter_client/client_spec.rb +208 -0
  23. data/spec/copycopter_client/configuration_spec.rb +252 -0
  24. data/spec/copycopter_client/helper_spec.rb +86 -0
  25. data/spec/copycopter_client/i18n_backend_spec.rb +133 -0
  26. data/spec/copycopter_client/prefixed_logger_spec.rb +25 -0
  27. data/spec/copycopter_client/sync_spec.rb +295 -0
  28. data/spec/spec.opts +2 -0
  29. data/spec/spec_helper.rb +30 -0
  30. data/spec/support/client_spec_helpers.rb +9 -0
  31. data/spec/support/defines_constants.rb +38 -0
  32. data/spec/support/fake_client.rb +42 -0
  33. data/spec/support/fake_copycopter_app.rb +136 -0
  34. data/spec/support/fake_html_safe_string.rb +20 -0
  35. data/spec/support/fake_logger.rb +68 -0
  36. data/spec/support/fake_passenger.rb +27 -0
  37. data/spec/support/fake_unicorn.rb +14 -0
  38. metadata +121 -0
@@ -0,0 +1,136 @@
1
+ require 'sinatra/base'
2
+ require 'json'
3
+ require 'thin'
4
+
5
+ class FakeCopycopterApp < Sinatra::Base
6
+ def self.start
7
+ Thread.new do
8
+ Thin::Logging.silent = true
9
+ Rack::Handler::Thin.run(self, :Port => port)
10
+ end
11
+ end
12
+
13
+ def self.port
14
+ (ENV['COPYCOPTER_PORT'] || 3002).to_i
15
+ end
16
+
17
+ def self.add_project(api_key)
18
+ Project.create(api_key)
19
+ end
20
+
21
+ def self.reset
22
+ Project.delete_all
23
+ end
24
+
25
+ def self.project(api_key)
26
+ Project.find(api_key)
27
+ end
28
+
29
+ def with_project(api_key)
30
+ if api_key == 'raise_error'
31
+ halt 500, { :error => "Blah ha" }.to_json
32
+ elsif project = Project.find(api_key)
33
+ yield(project)
34
+ else
35
+ halt 404, { :error => "No such project" }.to_json
36
+ end
37
+ end
38
+
39
+ get "/api/v2/projects/:api_key/published_blurbs" do |api_key|
40
+ with_project(api_key) { |project| project.published.to_json }
41
+ end
42
+
43
+ get "/api/v2/projects/:api_key/draft_blurbs" do |api_key|
44
+ with_project(api_key) { |project| project.draft.to_json }
45
+ end
46
+
47
+ post "/api/v2/projects/:api_key/draft_blurbs" do |api_key|
48
+ with_project(api_key) do |project|
49
+ data = JSON.parse(request.body.read)
50
+ project.update('draft' => data)
51
+ 201
52
+ end
53
+ end
54
+
55
+ post "/api/v2/projects/:api_key/deploys" do |api_key|
56
+ with_project(api_key) do |project|
57
+ project.deploy
58
+ 201
59
+ end
60
+ end
61
+
62
+ class Project
63
+ attr_reader :draft, :published, :api_key
64
+
65
+ def initialize(attrs)
66
+ @api_key = attrs['api_key']
67
+ @draft = attrs['draft'] || {}
68
+ @published = attrs['published'] || {}
69
+ end
70
+
71
+ def to_hash
72
+ { 'api_key' => @api_key,
73
+ 'draft' => @draft,
74
+ 'published' => @published }
75
+ end
76
+
77
+ def update(attrs)
78
+ @draft. update(attrs['draft']) if attrs['draft']
79
+ @published.update(attrs['published']) if attrs['published']
80
+ self.class.save(self)
81
+ end
82
+
83
+ def reload
84
+ self.class.find(api_key)
85
+ end
86
+
87
+ def deploy
88
+ @published.update(@draft)
89
+ self.class.save(self)
90
+ end
91
+
92
+ def self.create(api_key)
93
+ project = Project.new('api_key' => api_key)
94
+ save(project)
95
+ project
96
+ end
97
+
98
+ def self.find(api_key)
99
+ open_project_data do |data|
100
+ if project_hash = data[api_key]
101
+ Project.new(project_hash.dup)
102
+ else
103
+ nil
104
+ end
105
+ end
106
+ end
107
+
108
+ def self.delete_all
109
+ open_project_data do |data|
110
+ data.clear
111
+ end
112
+ end
113
+
114
+ def self.save(project)
115
+ open_project_data do |data|
116
+ data[project.api_key] = project.to_hash
117
+ end
118
+ end
119
+
120
+ def self.open_project_data
121
+ project_file = File.expand_path('/../../../tmp/projects.json', __FILE__)
122
+ if File.exist?(project_file)
123
+ data = JSON.parse(IO.read(project_file))
124
+ else
125
+ data = {}
126
+ end
127
+
128
+ result = yield(data)
129
+
130
+ File.open(project_file, "w") { |file| file.write(data.to_json) }
131
+
132
+ result
133
+ end
134
+ end
135
+ end
136
+
@@ -0,0 +1,20 @@
1
+ class FakeHtmlSafeString < String
2
+ def initialize(*args)
3
+ super(*args)
4
+ @html_safe = false
5
+ end
6
+
7
+ def html_safe
8
+ dup.html_safe!
9
+ end
10
+
11
+ def html_safe!
12
+ @html_safe = true
13
+ self
14
+ end
15
+
16
+ def html_safe?
17
+ @html_safe
18
+ end
19
+ end
20
+
@@ -0,0 +1,68 @@
1
+ class FakeLogger
2
+ def initialize
3
+ @entries = {
4
+ :info => [],
5
+ :debug => [],
6
+ :warn => [],
7
+ :error => [],
8
+ :fatal => [],
9
+ }
10
+ end
11
+
12
+ def info(message = nil, &block)
13
+ log(:info, message, &block)
14
+ end
15
+
16
+ def debug(message = nil, &block)
17
+ log(:debug, message, &block)
18
+ end
19
+
20
+ def warn(message = nil, &block)
21
+ log(:warn, message, &block)
22
+ end
23
+
24
+ def error(message = nil, &block)
25
+ log(:error, message, &block)
26
+ end
27
+
28
+ def fatal(message = nil, &block)
29
+ log(:fatal, message, &block)
30
+ end
31
+
32
+ def log(severity, message = nil, &block)
33
+ message ||= block.call
34
+ @entries[severity] << message
35
+ end
36
+
37
+ def has_entry?(level, expected_entry)
38
+ @entries[level].any? { |actual_entry| actual_entry.include?(expected_entry) }
39
+ end
40
+
41
+ attr_reader :entries
42
+ end
43
+
44
+ Spec::Matchers.define :have_entry do |severity, entry|
45
+ match do |logger|
46
+ @logger = logger
47
+ logger.has_entry?(severity, entry)
48
+ end
49
+
50
+ failure_message_for_should do
51
+ "Expected #{severity}(#{entry.inspect}); got entries:\n\n#{entries}"
52
+ end
53
+
54
+ failure_message_for_should_not do
55
+ "Unexpected #{severity}(#{entry.inspect}); got entries:\n\n#{entries}"
56
+ end
57
+
58
+ def entries
59
+ lines = @logger.entries.inject([]) do |result, (severity, entries)|
60
+ if entries.empty?
61
+ result
62
+ else
63
+ result << "#{severity}:\n#{entries.join("\n")}"
64
+ end
65
+ end
66
+ lines.join("\n\n")
67
+ end
68
+ end
@@ -0,0 +1,27 @@
1
+ class FakePassenger
2
+ def initialize
3
+ @handlers = {}
4
+ end
5
+
6
+ def on_event(name, &handler)
7
+ @handlers[name] ||= []
8
+ @handlers[name] << handler
9
+ end
10
+
11
+ def call_event(name, *args)
12
+ if @handlers[name]
13
+ @handlers[name].each do |handler|
14
+ handler.call(*args)
15
+ end
16
+ end
17
+ end
18
+
19
+ def become_master
20
+ $0 = "PassengerApplicationSpawner"
21
+ end
22
+
23
+ def spawn
24
+ $0 = "PassengerFork"
25
+ call_event(:starting_worker_process, true)
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ class FakeUnicornServer
2
+ def become_master
3
+ $0 = "unicorn master"
4
+ end
5
+
6
+ def spawn
7
+ $0 = "PassengerFork"
8
+ worker_loop(nil)
9
+ end
10
+
11
+ def worker_loop(worker)
12
+ end
13
+ end
14
+
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: copycopter_client
3
+ version: !ruby/object:Gem::Version
4
+ hash: 62196353
5
+ prerelease: 6
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ - beta
11
+ - 1
12
+ version: 1.0.0.beta1
13
+ platform: ruby
14
+ authors:
15
+ - thoughtbot
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2010-06-04 00:00:00 -04:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ name: i18n
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ hash: 3
32
+ segments:
33
+ - 0
34
+ version: "0"
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description:
38
+ email: support@thoughtbot.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files:
44
+ - README.textile
45
+ files:
46
+ - MIT-LICENSE
47
+ - Rakefile
48
+ - init.rb
49
+ - lib/copycopter_client/client.rb
50
+ - lib/copycopter_client/configuration.rb
51
+ - lib/copycopter_client/errors.rb
52
+ - lib/copycopter_client/helper.rb
53
+ - lib/copycopter_client/i18n_backend.rb
54
+ - lib/copycopter_client/prefixed_logger.rb
55
+ - lib/copycopter_client/rails.rb
56
+ - lib/copycopter_client/railtie.rb
57
+ - lib/copycopter_client/sync.rb
58
+ - lib/copycopter_client/version.rb
59
+ - lib/copycopter_client.rb
60
+ - lib/tasks/copycopter_client_tasks.rake
61
+ - spec/copycopter_client/client_spec.rb
62
+ - spec/copycopter_client/configuration_spec.rb
63
+ - spec/copycopter_client/helper_spec.rb
64
+ - spec/copycopter_client/i18n_backend_spec.rb
65
+ - spec/copycopter_client/prefixed_logger_spec.rb
66
+ - spec/copycopter_client/sync_spec.rb
67
+ - spec/spec.opts
68
+ - spec/spec_helper.rb
69
+ - spec/support/client_spec_helpers.rb
70
+ - spec/support/defines_constants.rb
71
+ - spec/support/fake_client.rb
72
+ - spec/support/fake_copycopter_app.rb
73
+ - spec/support/fake_html_safe_string.rb
74
+ - spec/support/fake_logger.rb
75
+ - spec/support/fake_passenger.rb
76
+ - spec/support/fake_unicorn.rb
77
+ - features/rails.feature
78
+ - features/step_definitions/copycopter_server_steps.rb
79
+ - features/step_definitions/rails_steps.rb
80
+ - features/support/env.rb
81
+ - features/support/rails_server.rb
82
+ - README.textile
83
+ has_rdoc: true
84
+ homepage: http://github.com/thoughtbot/copycopter_client
85
+ licenses: []
86
+
87
+ post_install_message:
88
+ rdoc_options:
89
+ - --line-numbers
90
+ - --main
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">"
106
+ - !ruby/object:Gem::Version
107
+ hash: 25
108
+ segments:
109
+ - 1
110
+ - 3
111
+ - 1
112
+ version: 1.3.1
113
+ requirements: []
114
+
115
+ rubyforge_project: copycopter_client
116
+ rubygems_version: 1.4.1
117
+ signing_key:
118
+ specification_version: 3
119
+ summary: Client for the Copycopter content management service
120
+ test_files: []
121
+