pact_broker 1.3.1 → 1.3.2.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +12 -0
  4. data/db/migrations/07_increase_json_content_length.rb +3 -7
  5. data/db/migrations/15_add_value_to_tag.rb.wip +5 -0
  6. data/db/migrations/15_create_pact_version_content.rb +13 -0
  7. data/db/migrations/16_add_pact_content_foreign_key_to_pacts.rb +10 -0
  8. data/db/migrations/17_migrate_json_content_to_pact_version_content_table.rb +14 -0
  9. data/db/migrations/18_drop_json_content_column_from_pacts.rb +14 -0
  10. data/db/migrations/19_make_pact_version_content_sha_not_nullable.rb +10 -0
  11. data/db/migrations/20_add_pact_version_content_sha_to_all_pacts_view.rb +18 -0
  12. data/db/migrations/21_recreate_latest_pacts_view.rb +21 -0
  13. data/db/migrations/migration_helper.rb +15 -0
  14. data/db/pact_broker_database.sqlite3 +0 -0
  15. data/example/config.ru +5 -1
  16. data/example/pact_broker_database.sqlite3 +0 -0
  17. data/lib/pact_broker/api/decorators/pact_collection_decorator.rb +1 -1
  18. data/lib/pact_broker/api/decorators/pact_pacticipant_decorator.rb +1 -1
  19. data/lib/pact_broker/api/decorators/pacticipant_collection_decorator.rb +1 -1
  20. data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +1 -1
  21. data/lib/pact_broker/api/decorators/relationships_csv_decorator.rb +1 -1
  22. data/lib/pact_broker/api/decorators/webhook_decorator.rb +2 -2
  23. data/lib/pact_broker/api/renderers/html_pact_renderer.rb +1 -1
  24. data/lib/pact_broker/api/resources/pact.rb +8 -1
  25. data/lib/pact_broker/api/resources/pact_webhooks.rb +1 -1
  26. data/lib/pact_broker/api/resources/pacticipants.rb +2 -2
  27. data/lib/pact_broker/db/validate_encoding.rb +22 -0
  28. data/lib/pact_broker/doc/views/pacticipants.markdown +3 -1
  29. data/lib/pact_broker/domain.rb +5 -0
  30. data/lib/pact_broker/{models → domain}/group.rb +1 -1
  31. data/lib/pact_broker/{models → domain}/order_versions.rb +2 -2
  32. data/lib/pact_broker/{models → domain}/pact.rb +1 -1
  33. data/lib/pact_broker/{models → domain}/pacticipant.rb +1 -1
  34. data/lib/pact_broker/{models → domain}/relationship.rb +1 -1
  35. data/lib/pact_broker/{models → domain}/tag.rb +2 -2
  36. data/lib/pact_broker/{models → domain}/version.rb +3 -3
  37. data/lib/pact_broker/{models → domain}/webhook.rb +2 -2
  38. data/lib/pact_broker/{models → domain}/webhook_execution_result.rb +1 -1
  39. data/lib/pact_broker/{models → domain}/webhook_request.rb +3 -3
  40. data/lib/pact_broker/{models → domain}/webhook_request_header.rb +1 -1
  41. data/lib/pact_broker/functions/find_potential_duplicate_pacticipant_names.rb +1 -1
  42. data/lib/pact_broker/functions/groupify.rb +2 -2
  43. data/lib/pact_broker/locale/en.yml +1 -0
  44. data/lib/pact_broker/pacts/all_pacts.rb +82 -0
  45. data/lib/pact_broker/pacts/database_model.rb +35 -0
  46. data/lib/pact_broker/pacts/latest_pacts.rb +11 -0
  47. data/lib/pact_broker/pacts/pact_version_content.rb +11 -0
  48. data/lib/pact_broker/pacts/repository.rb +106 -0
  49. data/lib/pact_broker/repositories.rb +3 -3
  50. data/lib/pact_broker/repositories/pacticipant_repository.rb +6 -6
  51. data/lib/pact_broker/repositories/tag_repository.rb +3 -3
  52. data/lib/pact_broker/repositories/version_repository.rb +5 -5
  53. data/lib/pact_broker/repositories/webhook.rb +89 -0
  54. data/lib/pact_broker/repositories/webhook_repository.rb +9 -94
  55. data/lib/pact_broker/services/pact_service.rb +4 -0
  56. data/lib/pact_broker/services/pacticipant_service.rb +3 -3
  57. data/lib/pact_broker/ui.rb +7 -0
  58. data/lib/pact_broker/ui/controllers/clusters.rb +1 -1
  59. data/lib/pact_broker/ui/controllers/relationships.rb +1 -1
  60. data/lib/pact_broker/ui/view_models/relationship.rb +1 -1
  61. data/lib/pact_broker/ui/view_models/relationships.rb +12 -3
  62. data/lib/pact_broker/ui/views/relationships/show.haml +2 -0
  63. data/lib/pact_broker/version.rb +1 -1
  64. data/public/stylesheets/relationships.css +5 -0
  65. data/spec/features/create_webhook_spec.rb +77 -0
  66. data/spec/features/delete_pact_spec.rb +28 -0
  67. data/spec/features/publish_pact_spec.rb +58 -0
  68. data/spec/features/update_pacticipant_spec.rb +26 -0
  69. data/spec/fixtures/update_pacticipant.json +5 -0
  70. data/spec/fixtures/updated_pacticipant.json +11 -0
  71. data/spec/integration/app_spec.rb +1 -4
  72. data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +1 -1
  73. data/spec/lib/pact_broker/api/decorators/pact_collection_decorator_spec.rb +5 -5
  74. data/spec/lib/pact_broker/api/decorators/pact_decorator_spec.rb +3 -3
  75. data/spec/lib/pact_broker/api/decorators/pact_version_decorator_spec.rb +3 -3
  76. data/spec/lib/pact_broker/api/decorators/pacticipant_decorator_spec.rb +2 -2
  77. data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +6 -6
  78. data/spec/lib/pact_broker/api/decorators/webhook_execution_result_decorator_spec.rb +2 -2
  79. data/spec/lib/pact_broker/api/decorators/webhook_request_decorator_spec.rb +2 -2
  80. data/spec/lib/pact_broker/api/decorators/webhooks_decorator_spec.rb +1 -1
  81. data/spec/lib/pact_broker/api/renderers/html_pact_renderer_spec.rb +1 -1
  82. data/spec/lib/pact_broker/api/resources/pact_spec.rb +34 -1
  83. data/spec/lib/pact_broker/api/resources/pact_webhooks_spec.rb +3 -3
  84. data/spec/lib/pact_broker/api/resources/pacticipants_spec.rb +1 -1
  85. data/spec/lib/pact_broker/api/resources/tag_spec.rb +1 -1
  86. data/spec/lib/pact_broker/db/validate_encoding_spec.rb +66 -0
  87. data/spec/lib/pact_broker/{models → domain}/group_spec.rb +5 -5
  88. data/spec/lib/pact_broker/{models → domain}/order_versions_spec.rb +4 -4
  89. data/spec/lib/pact_broker/{models → domain}/pacticipant_spec.rb +2 -2
  90. data/spec/lib/pact_broker/{models → domain}/webhook_request_spec.rb +2 -2
  91. data/spec/lib/pact_broker/{models → domain}/webhook_spec.rb +3 -3
  92. data/spec/lib/pact_broker/functions/groupify_spec.rb +10 -10
  93. data/spec/lib/pact_broker/{repositories/pact_repository_spec.rb → pacts/repository_spec.rb} +128 -28
  94. data/spec/lib/pact_broker/repositories/webhook_repository_spec.rb +3 -3
  95. data/spec/lib/pact_broker/services/group_service_spec.rb +4 -4
  96. data/spec/lib/pact_broker/services/pact_service_spec.rb +4 -4
  97. data/spec/lib/pact_broker/services/pacticipant_service_spec.rb +11 -11
  98. data/spec/lib/pact_broker/services/webhook_service_spec.rb +5 -5
  99. data/spec/lib/pact_broker/ui/controllers/relationships_spec.rb +3 -3
  100. data/spec/lib/pact_broker/ui/view_models/relationship_spec.rb +8 -8
  101. data/spec/lib/pact_broker/ui/view_models/relationships_spec.rb +28 -5
  102. data/spec/support/provider_state_builder.rb +17 -17
  103. data/tasks/db.rake +1 -2
  104. metadata +59 -35
  105. data/lib/pact_broker/jobs/after_pact_save.rb +0 -13
  106. data/lib/pact_broker/models.rb +0 -5
  107. data/lib/pact_broker/repositories/pact.rb +0 -29
  108. data/lib/pact_broker/repositories/pact_repository.rb +0 -140
  109. data/spec/integration/endpoints/pact_put_spec.rb +0 -59
  110. data/spec/integration/endpoints/pact_webhooks_spec.rb +0 -96
@@ -1,16 +1,16 @@
1
1
  require 'sequel'
2
- require 'pact_broker/models/version'
2
+ require 'pact_broker/domain/version'
3
3
 
4
4
  module PactBroker
5
5
  module Repositories
6
6
  class VersionRepository
7
7
 
8
8
  def find_by_pacticipant_id_and_number pacticipant_id, number
9
- PactBroker::Models::Version.where(number: number, pacticipant_id: pacticipant_id).single_record
9
+ PactBroker::Domain::Version.where(number: number, pacticipant_id: pacticipant_id).single_record
10
10
  end
11
11
 
12
12
  def find_by_pacticipant_name_and_number pacticipant_name, number
13
- PactBroker::Models::Version
13
+ PactBroker::Domain::Version
14
14
  .where(number: number)
15
15
  .join(:pacticipants, {id: :pacticipant_id})
16
16
  .where(name: pacticipant_name)
@@ -19,8 +19,8 @@ module PactBroker
19
19
 
20
20
  def create args
21
21
  PactBroker.logger.info "Creating version #{args[:number]} for pacticipant_id=#{args[:pacticipant_id]}"
22
- version = PactBroker::Models::Version.new(number: args[:number], pacticipant_id: args[:pacticipant_id]).save
23
- PactBroker::Models::Version.find(id: version.id) # Need to reload with populated order
22
+ version = PactBroker::Domain::Version.new(number: args[:number], pacticipant_id: args[:pacticipant_id]).save
23
+ PactBroker::Domain::Version.find(id: version.id) # Need to reload with populated order
24
24
  end
25
25
 
26
26
  def find_by_pacticipant_id_and_number_or_create pacticipant_id, number
@@ -0,0 +1,89 @@
1
+ require 'sequel'
2
+ require 'pact_broker/domain/webhook'
3
+ require 'pact_broker/domain/pacticipant'
4
+
5
+ module PactBroker
6
+ module Repositories
7
+ class Webhook < Sequel::Model
8
+
9
+ set_primary_key :id
10
+ associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
11
+ associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
12
+ one_to_many :headers, :class => "PactBroker::Repositories::WebhookHeader", :reciprocal => :webhook
13
+
14
+ def before_destroy
15
+ WebhookHeader.where(webhook_id: id).destroy
16
+ end
17
+
18
+ def self.from_domain webhook, consumer, provider
19
+ is_json_request_body = !(String === webhook.request.body || webhook.request.body.nil?) # Can't rely on people to set content type
20
+ new(
21
+ uuid: webhook.uuid,
22
+ method: webhook.request.method,
23
+ url: webhook.request.url,
24
+ username: webhook.request.username,
25
+ password: not_plain_text_password(webhook.request.password),
26
+ body: (is_json_request_body ? webhook.request.body.to_json : webhook.request.body),
27
+ is_json_request_body: is_json_request_body
28
+ ).tap do | db_webhook |
29
+ db_webhook.consumer_id = consumer.id
30
+ db_webhook.provider_id = provider.id
31
+ end
32
+ end
33
+
34
+ def self.not_plain_text_password password
35
+ password.nil? ? nil : Base64.strict_encode64(password)
36
+ end
37
+
38
+ def to_domain
39
+ Domain::Webhook.new(
40
+ uuid: uuid,
41
+ consumer: consumer,
42
+ provider: provider,
43
+ request: Domain::WebhookRequest.new(request_attributes),
44
+ created_at: created_at,
45
+ updated_at: updated_at)
46
+ end
47
+
48
+ def request_attributes
49
+ values.merge(headers: parsed_headers, body: parsed_body, password: plain_text_password)
50
+ end
51
+
52
+ def plain_text_password
53
+ password.nil? ? nil : Base64.strict_decode64(password)
54
+ end
55
+
56
+ def parsed_headers
57
+ WebhookHeader.where(webhook_id: id).all.each_with_object({}) do | header, hash |
58
+ hash[header[:name]] = header[:value]
59
+ end
60
+ end
61
+
62
+ def parsed_body
63
+ if body && is_json_request_body
64
+ JSON.parse(body)
65
+ else
66
+ body
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ Webhook.plugin :timestamps, :update_on_create=>true
73
+
74
+ class WebhookHeader < Sequel::Model
75
+
76
+ associate(:many_to_one, :webhook, :class => "PactBroker::Repositories::Webhook", :key => :webhook_id, :primary_key => :id)
77
+
78
+ def self.from_domain name, value, webhook_id
79
+ db_header = new
80
+ db_header.name = name
81
+ db_header.value = value
82
+ db_header.webhook_id = webhook_id
83
+ db_header
84
+ end
85
+
86
+ end
87
+ end
88
+
89
+ end
@@ -1,33 +1,29 @@
1
1
  require 'sequel'
2
- require 'pact_broker/models/webhook'
3
- require 'pact_broker/models/pacticipant'
2
+ require 'pact_broker/domain/webhook'
3
+ require 'pact_broker/domain/pacticipant'
4
4
  require 'pact_broker/db'
5
+ require 'pact_broker/repositories/webhook'
6
+
5
7
 
6
8
  module PactBroker
7
9
  module Repositories
8
10
 
9
11
  class WebhookRepository
10
12
 
11
- # Experimenting with decoupling the model from the database representation.
12
- # Sure makes it messier for saving/retrieving.
13
-
14
13
  include Repositories
15
14
 
16
15
  def create uuid, webhook, consumer, provider
17
- db_webhook = Webhook.from_model webhook, consumer, provider
16
+ db_webhook = Webhook.from_domain webhook, consumer, provider
18
17
  db_webhook.uuid = uuid
19
18
  db_webhook.save
20
19
  webhook.request.headers.each_pair do | name, value |
21
- db_webhook.add_header WebhookHeader.from_model(name, value, db_webhook.id)
20
+ db_webhook.add_header WebhookHeader.from_domain(name, value, db_webhook.id)
22
21
  end
23
-
24
22
  find_by_uuid db_webhook.uuid
25
23
  end
26
24
 
27
25
  def find_by_uuid uuid
28
- db_webhook = Webhook.where(uuid: uuid).single_record
29
- return nil if db_webhook.nil?
30
- db_webhook.to_model
26
+ Webhook.where(uuid: uuid).limit(1).collect(&:to_domain)[0]
31
27
  end
32
28
 
33
29
  def delete_by_uuid uuid
@@ -40,92 +36,11 @@ module PactBroker
40
36
  end
41
37
 
42
38
  def find_all
43
- Webhook.all.collect { | db_webhook| db_webhook.to_model }
39
+ Webhook.all.collect(&:to_domain)
44
40
  end
45
41
 
46
42
  def find_by_consumer_and_provider consumer, provider
47
- Webhook.where(consumer_id: consumer.id, provider_id: provider.id).collect { | db_webhook| db_webhook.to_model }
48
- end
49
-
50
- end
51
-
52
- class Webhook < Sequel::Model
53
-
54
- set_primary_key :id
55
- associate(:many_to_one, :provider, :class => "PactBroker::Models::Pacticipant", :key => :provider_id, :primary_key => :id)
56
- associate(:many_to_one, :consumer, :class => "PactBroker::Models::Pacticipant", :key => :consumer_id, :primary_key => :id)
57
- one_to_many :headers, :class => "PactBroker::Repositories::WebhookHeader", :reciprocal => :webhook
58
-
59
- def before_destroy
60
- WebhookHeader.where(webhook_id: id).destroy
61
- end
62
-
63
- def self.from_model webhook, consumer, provider
64
- is_json_request_body = !(String === webhook.request.body || webhook.request.body.nil?) # Can't rely on people to set content type
65
- new(
66
- uuid: webhook.uuid,
67
- method: webhook.request.method,
68
- url: webhook.request.url,
69
- username: webhook.request.username,
70
- password: not_plain_text_password(webhook.request.password),
71
- body: (is_json_request_body ? webhook.request.body.to_json : webhook.request.body),
72
- is_json_request_body: is_json_request_body
73
- ).tap do | db_webhook |
74
- db_webhook.consumer_id = consumer.id
75
- db_webhook.provider_id = provider.id
76
- end
77
- end
78
-
79
- def self.not_plain_text_password password
80
- password.nil? ? nil : Base64.strict_encode64(password)
81
- end
82
-
83
- def to_model
84
- Models::Webhook.new(
85
- uuid: uuid,
86
- consumer: consumer,
87
- provider: provider,
88
- request: Models::WebhookRequest.new(request_attributes),
89
- created_at: created_at,
90
- updated_at: updated_at)
91
- end
92
-
93
- def request_attributes
94
- values.merge(headers: parsed_headers, body: parsed_body, password: plain_text_password)
95
- end
96
-
97
- def plain_text_password
98
- password.nil? ? nil : Base64.strict_decode64(password)
99
- end
100
-
101
- def parsed_headers
102
- WebhookHeader.where(webhook_id: id).all.each_with_object({}) do | header, hash |
103
- hash[header[:name]] = header[:value]
104
- end
105
- end
106
-
107
- def parsed_body
108
- if body && is_json_request_body
109
- JSON.parse(body)
110
- else
111
- body
112
- end
113
- end
114
-
115
- end
116
-
117
- Webhook.plugin :timestamps, :update_on_create=>true
118
-
119
- class WebhookHeader < Sequel::Model
120
-
121
- associate(:many_to_one, :webhook, :class => "PactBroker::Repositories::Webhook", :key => :webhook_id, :primary_key => :id)
122
-
123
- def self.from_model name, value, webhook_id
124
- db_header = new
125
- db_header.name = name
126
- db_header.value = value
127
- db_header.webhook_id = webhook_id
128
- db_header
43
+ Webhook.where(consumer_id: consumer.id, provider_id: provider.id).collect(&:to_domain)
129
44
  end
130
45
 
131
46
  end
@@ -22,6 +22,10 @@ module PactBroker
22
22
  pact_repository.find_pact(params[:consumer_name], params[:consumer_version_number], params[:provider_name])
23
23
  end
24
24
 
25
+ def delete params
26
+ pact_repository.delete(params)
27
+ end
28
+
25
29
  def create_or_update_pact params
26
30
  provider = pacticipant_repository.find_by_name_or_create params[:provider_name]
27
31
  consumer = pacticipant_repository.find_by_name_or_create params[:consumer_name]
@@ -1,7 +1,7 @@
1
1
  require 'pact_broker/repositories'
2
2
  require 'pact_broker/logging'
3
3
  require 'pact_broker/messages'
4
- require 'pact_broker/models/relationship'
4
+ require 'pact_broker/domain/relationship'
5
5
  require 'pact_broker/functions/find_potential_duplicate_pacticipant_names'
6
6
 
7
7
  module PactBroker
@@ -51,7 +51,7 @@ module PactBroker
51
51
  end
52
52
 
53
53
  def self.find_relationships
54
- pact_repository.find_latest_pacts.collect{ | pact| PactBroker::Models::Relationship.create pact.consumer, pact.provider }
54
+ pact_repository.find_latest_pacts.collect{ | pact| PactBroker::Domain::Relationship.create pact.consumer, pact.provider }
55
55
  end
56
56
 
57
57
  def self.update params
@@ -66,7 +66,7 @@ module PactBroker
66
66
 
67
67
  def self.delete name
68
68
  pacticipant = find_pacticipant_by_name name
69
- connection = PactBroker::Models::Pacticipant.new.db
69
+ connection = PactBroker::Domain::Pacticipant.new.db
70
70
  connection.run("delete from tags where version_id IN (select id from versions where pacticipant_id IN (select id from pacticipants where name = '#{name}'))")
71
71
  connection.run("delete from pacts where version_id IN (select id from versions where pacticipant_id IN (select id from pacticipants where name = '#{name}'))")
72
72
  connection.run("delete from pacts where provider_id IN (select id from pacticipants where name = '#{name}')")
@@ -1,2 +1,9 @@
1
+
2
+ # Stop Padrino creating a log file, as it will try to create it in the gems directory
3
+ # http://www.padrinorb.com/api/Padrino/Logger.html
4
+ unless defined? PADRINO_LOGGER
5
+ PADRINO_LOGGER = { production: { log_level: :warn, stream: :null } }
6
+ end
7
+
1
8
  require 'pact_broker/ui/controllers/relationships'
2
9
  require 'pact_broker/ui/controllers/groups'
@@ -18,7 +18,7 @@ module PactBroker
18
18
  end
19
19
 
20
20
  get "/" do
21
- view_model = ViewModels::Relationships.new(pacticipant_service.find_relationships)
21
+ view_model = ViewDomain::Relationships.new(pacticipant_service.find_relationships)
22
22
  haml 'clusters/show', locals: {relationships: view_model}
23
23
  end
24
24
 
@@ -10,7 +10,7 @@ module PactBroker
10
10
  include PactBroker::Services
11
11
 
12
12
  get "/" do
13
- view_model = ViewModels::Relationships.new(pacticipant_service.find_relationships)
13
+ view_model = ViewDomain::Relationships.new(pacticipant_service.find_relationships)
14
14
 
15
15
  haml :'relationships/show', {locals: {relationships: view_model}}, {layout: 'layouts/main'}
16
16
  end
@@ -3,7 +3,7 @@ require 'pact_broker/ui/helpers/url_helper'
3
3
 
4
4
  module PactBroker
5
5
  module UI
6
- module ViewModels
6
+ module ViewDomain
7
7
  class Relationship
8
8
 
9
9
  include PactBroker::Api::PactBrokerUrls
@@ -2,11 +2,9 @@ require 'pact_broker/ui/view_models/relationship'
2
2
 
3
3
  module PactBroker
4
4
  module UI
5
- module ViewModels
5
+ module ViewDomain
6
6
  class Relationships
7
7
 
8
- attr_reader :relationships
9
-
10
8
  def initialize relationships
11
9
  @relationships = relationships.collect{ |relationship| Relationship.new(relationship) }.sort
12
10
  end
@@ -15,6 +13,17 @@ module PactBroker
15
13
  relationships.each(&block)
16
14
  end
17
15
 
16
+ def size_label
17
+ case relationships.size
18
+ when 1 then "1 pact"
19
+ else
20
+ "#{relationships.size} pacts"
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :relationships
18
27
  end
19
28
  end
20
29
  end
@@ -38,6 +38,8 @@
38
38
  %td.provider
39
39
  %a{:href => relationship.provider_group_url}
40
40
  = relationship.provider_name
41
+ %div.relationships-size
42
+ = relationships.size_label
41
43
 
42
44
  :javascript
43
45
  $(function(){
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '1.3.1'
2
+ VERSION = '1.3.2.rc1'
3
3
  end
@@ -11,6 +11,11 @@
11
11
  border-left: none;
12
12
  }
13
13
 
14
+ .relationships-size {
15
+ text-align: right;
16
+ color: gray;
17
+ }
18
+
14
19
  .relationships-sort {
15
20
  padding-left:10px;
16
21
  }
@@ -0,0 +1,77 @@
1
+ require 'support/provider_state_builder'
2
+
3
+ describe "Creating a webhook" do
4
+
5
+ before do
6
+ ProviderStateBuilder.new.create_pact_with_hierarchy("Some Consumer", "1", "Some Provider")
7
+ end
8
+
9
+ let(:path) { "/webhooks/provider/Some%20Provider/consumer/Some%20Consumer" }
10
+ let(:headers) { {'CONTENT_TYPE' => 'application/json'} }
11
+ let(:response_body) { JSON.parse(last_response.body, symbolize_names: true)}
12
+ let(:webhook_json) { webhook_hash.to_json }
13
+
14
+ subject { post path, webhook_json, headers }
15
+
16
+ context "with invalid attributes" do
17
+
18
+ let(:webhook_hash) { {} }
19
+
20
+ it "returns a 400" do
21
+ subject
22
+ expect(last_response.status).to be 400
23
+ end
24
+
25
+ it "returns a JSON content type" do
26
+ subject
27
+ expect(last_response.headers['Content-Type']).to eq 'application/json'
28
+ end
29
+
30
+ it "returns the validation errors" do
31
+ subject
32
+ expect(response_body[:errors]).to_not be_empty
33
+ end
34
+
35
+ end
36
+
37
+ context "with valid attributes" do
38
+
39
+ let(:webhook_hash) do
40
+ {
41
+ request: {
42
+ method: 'POST',
43
+ url: 'http://example.org',
44
+ headers: {
45
+ :"Content-Type" => "application/json"
46
+ },
47
+ body: {
48
+ a: 'body'
49
+ }
50
+ }
51
+ }
52
+ end
53
+
54
+ let(:webhook_json) { webhook_hash.to_json }
55
+
56
+ it "returns a 201 response" do
57
+ subject
58
+ expect(last_response.status).to be 201
59
+ end
60
+
61
+ it "returns the Location header" do
62
+ subject
63
+ expect(last_response.headers['Location']).to match(%r{http://example.org/webhooks/.+})
64
+ end
65
+
66
+ it "returns a JSON Content Type" do
67
+ subject
68
+ expect(last_response.headers['Content-Type']).to eq 'application/hal+json'
69
+ end
70
+
71
+ it "returns the newly created webhook" do
72
+ subject
73
+ expect(response_body).to include webhook_hash
74
+ end
75
+ end
76
+
77
+ end