pact_broker 2.22.0 → 2.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/README.md +1 -0
  4. data/db/migrations/20180611_make_webhook_pacticipant_ids_optional.rb +11 -0
  5. data/example/config.ru +2 -0
  6. data/lib/pact_broker/api.rb +9 -3
  7. data/lib/pact_broker/api/contracts/webhook_contract.rb +36 -0
  8. data/lib/pact_broker/api/decorators/pact_decorator.rb +22 -1
  9. data/lib/pact_broker/api/decorators/pact_webhooks_status_decorator.rb +1 -26
  10. data/lib/pact_broker/api/decorators/triggered_webhook_decorator.rb +33 -0
  11. data/lib/pact_broker/api/decorators/triggered_webhooks_decorator.rb +19 -0
  12. data/lib/pact_broker/api/decorators/verification_decorator.rb +6 -0
  13. data/lib/pact_broker/api/decorators/webhook_decorator.rb +32 -18
  14. data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +27 -0
  15. data/lib/pact_broker/api/decorators/{webhook_request_decorator.rb → webhook_request_template_decorator.rb} +1 -1
  16. data/lib/pact_broker/api/pact_broker_urls.rb +21 -1
  17. data/lib/pact_broker/api/resources/all_webhooks.rb +82 -0
  18. data/lib/pact_broker/api/resources/base_resource.rb +18 -0
  19. data/lib/pact_broker/api/resources/error_handler.rb +5 -1
  20. data/lib/pact_broker/api/resources/pact_triggered_webhooks.rb +41 -0
  21. data/lib/pact_broker/api/resources/pact_webhooks.rb +2 -15
  22. data/lib/pact_broker/api/resources/pact_webhooks_status.rb +1 -1
  23. data/lib/pact_broker/api/resources/verification_triggered_webhooks.rb +45 -0
  24. data/lib/pact_broker/api/resources/webhook_execution.rb +1 -5
  25. data/lib/pact_broker/api/resources/webhooks.rb +69 -6
  26. data/lib/pact_broker/configuration.rb +5 -2
  27. data/lib/pact_broker/doc/controllers/app.rb +1 -2
  28. data/lib/pact_broker/doc/views/pact-webhooks.markdown +3 -0
  29. data/lib/pact_broker/doc/views/webhooks.markdown +53 -33
  30. data/lib/pact_broker/domain/pact.rb +4 -0
  31. data/lib/pact_broker/domain/webhook.rb +19 -3
  32. data/lib/pact_broker/domain/webhook_execution_result.rb +6 -1
  33. data/lib/pact_broker/domain/webhook_request.rb +87 -65
  34. data/lib/pact_broker/locale/en.yml +1 -0
  35. data/lib/pact_broker/matrix/repository.rb +3 -1
  36. data/lib/pact_broker/pacts/placeholder_pact.rb +17 -0
  37. data/lib/pact_broker/pacts/repository.rb +14 -0
  38. data/lib/pact_broker/pacts/service.rb +6 -2
  39. data/lib/pact_broker/ui/view_models/index_item.rb +1 -1
  40. data/lib/pact_broker/verifications/placeholder_verification.rb +23 -0
  41. data/lib/pact_broker/verifications/repository.rb +9 -0
  42. data/lib/pact_broker/verifications/service.rb +5 -1
  43. data/lib/pact_broker/version.rb +1 -1
  44. data/lib/pact_broker/webhooks/repository.rb +54 -4
  45. data/lib/pact_broker/webhooks/service.rb +37 -2
  46. data/lib/pact_broker/webhooks/webhook.rb +4 -3
  47. data/lib/pact_broker/webhooks/webhook_event.rb +8 -0
  48. data/lib/pact_broker/webhooks/webhook_request_template.rb +72 -0
  49. data/pact_broker.gemspec +1 -1
  50. data/script/seed.rb +32 -51
  51. data/spec/features/create_webhook_spec.rb +85 -36
  52. data/spec/features/execute_webhook_spec.rb +9 -18
  53. data/spec/features/get_triggered_webhooks_for_pact_spec.rb +20 -0
  54. data/spec/features/get_triggered_webhooks_for_verification_spec.rb +21 -0
  55. data/spec/fixtures/webhook_valid_with_pacticipants.json +23 -0
  56. data/spec/integration/webhooks/certificate_spec.rb +2 -2
  57. data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +98 -2
  58. data/spec/lib/pact_broker/api/decorators/triggered_webhook_decorator_spec.rb +64 -0
  59. data/spec/lib/pact_broker/api/decorators/triggered_webhooks_decorator_spec.rb +28 -0
  60. data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +8 -0
  61. data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +37 -1
  62. data/spec/lib/pact_broker/api/decorators/webhook_execution_result_decorator_spec.rb +34 -1
  63. data/spec/lib/pact_broker/api/decorators/{webhook_request_decorator_spec.rb → webhook_request_template_decorator_spec.rb} +7 -9
  64. data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +22 -0
  65. data/spec/lib/pact_broker/api/resources/{pact_webhooks_spec.rb → all_webhooks_spec.rb} +46 -80
  66. data/spec/lib/pact_broker/api/resources/error_handler_spec.rb +34 -0
  67. data/spec/lib/pact_broker/api/resources/pact_triggered_webhooks_spec.rb +54 -0
  68. data/spec/lib/pact_broker/api/resources/pacticipant_spec.rb +1 -6
  69. data/spec/lib/pact_broker/api/resources/tag_spec.rb +1 -6
  70. data/spec/lib/pact_broker/api/resources/verification_triggered_webhooks_spec.rb +68 -0
  71. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +2 -8
  72. data/spec/lib/pact_broker/api/resources/webhooks_spec.rb +216 -21
  73. data/spec/lib/pact_broker/configuration_spec.rb +30 -0
  74. data/spec/lib/pact_broker/domain/webhook_request_spec.rb +20 -64
  75. data/spec/lib/pact_broker/domain/webhook_spec.rb +40 -11
  76. data/spec/lib/pact_broker/matrix/repository_spec.rb +33 -0
  77. data/spec/lib/pact_broker/pacts/pact_version_spec.rb +1 -0
  78. data/spec/lib/pact_broker/pacts/repository_spec.rb +39 -1
  79. data/spec/lib/pact_broker/ui/view_models/index_item_spec.rb +1 -1
  80. data/spec/lib/pact_broker/verifications/repository_spec.rb +37 -0
  81. data/spec/lib/pact_broker/verifications/service_spec.rb +2 -2
  82. data/spec/lib/pact_broker/webhooks/render_spec.rb +15 -0
  83. data/spec/lib/pact_broker/webhooks/repository_spec.rb +149 -30
  84. data/spec/lib/pact_broker/webhooks/service_spec.rb +84 -7
  85. data/spec/lib/pact_broker/webhooks/webhook_request_template_spec.rb +81 -0
  86. data/spec/service_consumers/pact_helper.rb +2 -0
  87. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +8 -0
  88. data/spec/service_consumers/provider_states_for_pact_ruby.rb +132 -0
  89. data/spec/support/test_data_builder.rb +30 -7
  90. metadata +37 -9
@@ -6,74 +6,123 @@ describe "Creating a webhook" do
6
6
  TestDataBuilder.new.create_pact_with_hierarchy("Some Consumer", "1", "Some Provider")
7
7
  end
8
8
 
9
- let(:path) { "/webhooks/provider/Some%20Provider/consumer/Some%20Consumer" }
10
9
  let(:headers) { {'CONTENT_TYPE' => 'application/json'} }
11
10
  let(:response_body) { JSON.parse(last_response.body, symbolize_names: true)}
12
11
  let(:webhook_json) { webhook_hash.to_json }
12
+ let(:webhook_hash) do
13
+ {
14
+ events: [{
15
+ name: 'something_happened'
16
+ }],
17
+ request: {
18
+ method: 'POST',
19
+ url: 'https://example.org',
20
+ headers: {
21
+ :"Content-Type" => "application/json"
22
+ },
23
+ body: {
24
+ a: 'body'
25
+ }
26
+ }
27
+ }
28
+ end
13
29
 
14
- subject { post path, webhook_json, headers }
30
+ subject { post(path, webhook_json, headers) }
15
31
 
16
- context "with invalid attributes" do
32
+ context "for a consumer and provider" do
33
+ let(:path) { "/webhooks/provider/Some%20Provider/consumer/Some%20Consumer" }
17
34
 
18
- let(:webhook_hash) { {} }
35
+ context "with invalid attributes" do
36
+ let(:webhook_hash) { {} }
19
37
 
20
- it "returns a 400" do
21
- subject
22
- expect(last_response.status).to be 400
23
- end
38
+ it "returns a 400" do
39
+ subject
40
+ expect(last_response.status).to be 400
41
+ end
24
42
 
25
43
  it "returns a JSON content type" do
26
44
  subject
27
45
  expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
28
46
  end
29
47
 
30
- it "returns the validation errors" do
31
- subject
32
- expect(response_body[:errors]).to_not be_empty
48
+ it "returns the validation errors" do
49
+ subject
50
+ expect(response_body[:errors]).to_not be_empty
51
+ end
33
52
  end
34
53
 
54
+ context "with valid attributes" do
55
+ it "returns a 201 response" do
56
+ subject
57
+ expect(last_response.status).to be 201
58
+ end
59
+
60
+ it "returns the Location header" do
61
+ subject
62
+ expect(last_response.headers['Location']).to match(%r{http://example.org/webhooks/.+})
63
+ end
64
+
65
+ it "returns a JSON Content Type" do
66
+ subject
67
+ expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
68
+ end
69
+
70
+ it "returns the newly created webhook" do
71
+ subject
72
+ expect(response_body).to include webhook_hash
73
+ end
74
+ end
35
75
  end
36
76
 
37
- context "with valid attributes" do
38
-
39
- let(:webhook_hash) do
40
- {
41
- events: [{
42
- name: 'something_happened'
43
- }],
44
- request: {
45
- method: 'POST',
46
- url: 'https://example.org',
47
- headers: {
48
- :"Content-Type" => "application/json"
49
- },
50
- body: {
51
- a: 'body'
52
- }
53
- }
54
- }
77
+ context "for a provider" do
78
+ let(:path) { "/webhooks" }
79
+
80
+ before do
81
+ webhook_hash[:provider] = { name: "Some Provider" }
55
82
  end
56
83
 
57
- let(:webhook_json) { webhook_hash.to_json }
84
+ it "returns a 201 response" do
85
+ subject
86
+ expect(last_response.status).to be 201
87
+ end
88
+
89
+ it "creates a webhook without a consumer" do
90
+ subject
91
+ expect(PactBroker::Webhooks::Webhook.first.provider).to_not be nil
92
+ expect(PactBroker::Webhooks::Webhook.first.consumer).to be nil
93
+ end
94
+ end
95
+
96
+ context "for a consumer" do
97
+ let(:path) { "/webhooks" }
98
+ before do
99
+ webhook_hash[:consumer] = { name: "Some Consumer" }
100
+ end
58
101
 
59
102
  it "returns a 201 response" do
60
103
  subject
61
104
  expect(last_response.status).to be 201
62
105
  end
63
106
 
64
- it "returns the Location header" do
107
+ it "creates a webhook without a provider" do
65
108
  subject
66
- expect(last_response.headers['Location']).to match(%r{http://example.org/webhooks/.+})
109
+ expect(PactBroker::Webhooks::Webhook.first.consumer).to_not be nil
110
+ expect(PactBroker::Webhooks::Webhook.first.provider).to be nil
67
111
  end
112
+ end
113
+
114
+ context "with no consumer or provider" do
115
+ let(:path) { "/webhooks" }
68
116
 
69
- it "returns a JSON Content Type" do
117
+ it "returns a 201 response" do
70
118
  subject
71
- expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
119
+ expect(last_response.status).to be 201
72
120
  end
73
121
 
74
- it "returns the newly created webhook" do
122
+ it "creates a webhook without a provider" do
75
123
  subject
76
- expect(response_body).to include webhook_hash
124
+ expect(PactBroker::Webhooks::Webhook.first.consumer).to be nil
125
+ expect(PactBroker::Webhooks::Webhook.first.provider).to be nil
77
126
  end
78
127
  end
79
128
  end
@@ -25,6 +25,7 @@ describe "Execute a webhook" do
25
25
  let!(:request) do
26
26
  stub_request(:post, /http/).with(body: 'http://example.org/pacts/provider/Bar/consumer/Foo/version/1').to_return(:status => 200, body: response_body)
27
27
  end
28
+
28
29
  let(:response_body) { "webhook-response-body" }
29
30
 
30
31
  it "performs the HTTP request" do
@@ -36,12 +37,12 @@ describe "Execute a webhook" do
36
37
  expect(subject.status).to be 200
37
38
  end
38
39
 
39
- it "saves a TriggeredWebhook" do
40
- expect { subject }.to change { PactBroker::Webhooks::TriggeredWebhook.count }.by(1)
40
+ it "does not save a TriggeredWebhook" do
41
+ expect { subject }.to_not change { PactBroker::Webhooks::TriggeredWebhook.count }
41
42
  end
42
43
 
43
- it "saves a WebhookExecution" do
44
- expect { subject }.to change { PactBroker::Webhooks::Execution.count }.by(1)
44
+ it "does not save a WebhookExecution" do
45
+ expect { subject }.to_not change { PactBroker::Webhooks::Execution.count }
45
46
  end
46
47
 
47
48
  context "when a webhook host whitelist is not configured" do
@@ -52,11 +53,6 @@ describe "Execute a webhook" do
52
53
  it "does not show any response details" do
53
54
  expect(subject.body).to_not include response_body
54
55
  end
55
-
56
- it "does not log any response details" do
57
- subject
58
- expect(PactBroker::Webhooks::Execution.order(:id).last.logs).to_not include response_body
59
- end
60
56
  end
61
57
 
62
58
  context "when a webhook host whitelist is configured" do
@@ -67,11 +63,6 @@ describe "Execute a webhook" do
67
63
  it "includes response details" do
68
64
  expect(subject.body).to include response_body
69
65
  end
70
-
71
- it "logs the response details" do
72
- subject
73
- expect(PactBroker::Webhooks::Execution.order(:id).last.logs).to include response_body
74
- end
75
66
  end
76
67
  end
77
68
 
@@ -98,12 +89,12 @@ describe "Execute a webhook" do
98
89
  expect(subject.status).to be 500
99
90
  end
100
91
 
101
- it "saves a TriggeredWebhook" do
102
- expect { subject }.to change { PactBroker::Webhooks::TriggeredWebhook.count }.by(1)
92
+ it "does not save a TriggeredWebhook" do
93
+ expect { subject }.to_not change { PactBroker::Webhooks::TriggeredWebhook.count }
103
94
  end
104
95
 
105
- it "saves a WebhookExecution" do
106
- expect { subject }.to change { PactBroker::Webhooks::Execution.count }.by(1)
96
+ it "does not save a WebhookExecution" do
97
+ expect { subject }.to_not change { PactBroker::Webhooks::Execution.count }
107
98
  end
108
99
  end
109
100
  end
@@ -0,0 +1,20 @@
1
+ RSpec.describe "Get triggered webhooks for pact" do
2
+ before do
3
+ td.create_pact_with_hierarchy
4
+ .create_webhook
5
+ .create_triggered_webhook
6
+ .create_webhook_execution
7
+ end
8
+
9
+ let(:td) { TestDataBuilder.new }
10
+ let(:path) { PactBroker::Api::PactBrokerUrls.pact_triggered_webhooks_url(td.pact) }
11
+ let(:json_response_body) { JSON.parse(subject.body) }
12
+
13
+ subject { get(path); last_response }
14
+
15
+ it { is_expected.to be_a_hal_json_success_response }
16
+
17
+ it "contains a list of triggered webhooks" do
18
+ expect(json_response_body['_embedded']['triggeredWebhooks'].size).to be 1
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ RSpec.describe "Get triggered webhooks for verification" do
2
+ before do
3
+ td.create_pact_with_hierarchy
4
+ .create_verification_webhook
5
+ .create_verification
6
+ .create_triggered_webhook
7
+ .create_webhook_execution
8
+ end
9
+
10
+ let(:td) { TestDataBuilder.new }
11
+ let(:path) { PactBroker::Api::PactBrokerUrls.verification_triggered_webhooks_url(td.verification) }
12
+ let(:json_response_body) { JSON.parse(subject.body) }
13
+
14
+ subject { get(path); last_response }
15
+
16
+ it { is_expected.to be_a_hal_json_success_response }
17
+
18
+ it "contains a list of triggered webhooks" do
19
+ expect(json_response_body['_embedded']['triggeredWebhooks'].size).to be 1
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ {
2
+ "events": [{
3
+ "name": "something_happened"
4
+ }],
5
+ "consumer": {
6
+ "name": "Foo"
7
+ },
8
+ "provider": {
9
+ "name": "Bar"
10
+ },
11
+ "request": {
12
+ "method": "POST",
13
+ "url": "HTTPS://some.url",
14
+ "username": "username",
15
+ "password": "password",
16
+ "headers": {
17
+ "Accept": "application/json"
18
+ },
19
+ "body": {
20
+ "a" : "body"
21
+ }
22
+ }
23
+ }
@@ -11,12 +11,12 @@ describe "executing a webhook to a server with a self signed certificate" do
11
11
  let(:webhook_request) do
12
12
  PactBroker::Domain::WebhookRequest.new(
13
13
  method: 'get',
14
- url: 'https://localhost:4444')
14
+ url: 'https://localhost:4444/')
15
15
  end
16
16
 
17
17
  let(:pact) { td.create_pact_with_hierarchy.and_return(:pact) }
18
18
 
19
- subject { webhook_request.execute(pact, nil) }
19
+ subject { webhook_request.execute({}) }
20
20
 
21
21
  context "without the correct cacert" do
22
22
  it "fails" do
@@ -6,14 +6,16 @@ module PactBroker
6
6
  module Api
7
7
  module Contracts
8
8
  describe WebhookContract do
9
- let(:json) { load_fixture 'webhook_valid.json' }
9
+ let(:json) { load_fixture 'webhook_valid_with_pacticipants.json' }
10
10
  let(:hash) { JSON.parse(json) }
11
11
  let(:webhook) { PactBroker::Api::Decorators::WebhookDecorator.new(Domain::Webhook.new).from_json(json) }
12
12
  let(:subject) { WebhookContract.new(webhook) }
13
13
  let(:matching_hosts) { ['foo'] }
14
+ let(:consumer) { double("consumer") }
15
+ let(:provider) { double("provider") }
14
16
 
15
17
  def valid_webhook_with
16
- hash = load_json_fixture 'webhook_valid.json'
18
+ hash = load_json_fixture 'webhook_valid_with_pacticipants.json'
17
19
  yield hash
18
20
  hash.to_json
19
21
  end
@@ -23,6 +25,8 @@ module PactBroker
23
25
  PactBroker.configuration.webhook_http_method_whitelist = webhook_http_method_whitelist
24
26
  PactBroker.configuration.webhook_host_whitelist = webhook_host_whitelist
25
27
  allow(PactBroker::Webhooks::CheckHostWhitelist).to receive(:call).and_return(whitelist_matches)
28
+ allow(PactBroker::Pacticipants::Service).to receive(:find_pacticipant_by_name).with("Foo").and_return(consumer)
29
+ allow(PactBroker::Pacticipants::Service).to receive(:find_pacticipant_by_name).with("Bar").and_return(provider)
26
30
  subject.validate(hash)
27
31
  end
28
32
 
@@ -36,6 +40,98 @@ module PactBroker
36
40
  end
37
41
  end
38
42
 
43
+ context "with a nil consumer name" do
44
+ let(:json) do
45
+ valid_webhook_with do |hash|
46
+ hash['consumer']['name'] = nil
47
+ end
48
+ end
49
+
50
+ it "contains an error" do
51
+ expect(subject.errors[:'consumer.name']).to eq ["can't be blank"]
52
+ end
53
+ end
54
+
55
+ context "with no consumer name key" do
56
+ let(:json) do
57
+ valid_webhook_with do |hash|
58
+ hash['consumer'].delete('name')
59
+ end
60
+ end
61
+
62
+ # I'd prefer this to be "is missing". Isn't the whole point of dry validation
63
+ # that you can distingush between keys being missing and values being missing? FFS.
64
+ it "contains an error" do
65
+ expect(subject.errors[:'consumer.name']).to eq ["can't be blank"]
66
+ end
67
+ end
68
+
69
+ context "with no consumer" do
70
+ let(:json) do
71
+ valid_webhook_with do |hash|
72
+ hash.delete('consumer')
73
+ end
74
+ end
75
+
76
+ it "contains no errors" do
77
+ expect(subject.errors).to be_empty
78
+ end
79
+ end
80
+
81
+ context "with a consumer name that doesn't match any existing consumer" do
82
+ let(:consumer) { nil }
83
+
84
+ it "contains no errors" do
85
+ expect(subject.errors[:'consumer.name']).to eq ["does not match an existing pacticipant"]
86
+ end
87
+ end
88
+
89
+ context "with a nil provider name" do
90
+ let(:json) do
91
+ valid_webhook_with do |hash|
92
+ hash['provider']['name'] = nil
93
+ end
94
+ end
95
+
96
+ it "contains an error" do
97
+ expect(subject.errors[:'provider.name']).to eq ["can't be blank"]
98
+ end
99
+ end
100
+
101
+ context "with no provider name key" do
102
+ let(:json) do
103
+ valid_webhook_with do |hash|
104
+ hash['provider'].delete('name')
105
+ end
106
+ end
107
+
108
+ # I'd prefer this to be "is missing". Isn't the whole point of dry validation
109
+ # that you can distingush between keys being missing and values being missing? FFS.
110
+ it "contains an error" do
111
+ expect(subject.errors[:'provider.name']).to eq ["can't be blank"]
112
+ end
113
+ end
114
+
115
+ context "with no provider" do
116
+ let(:json) do
117
+ valid_webhook_with do |hash|
118
+ hash.delete('provider')
119
+ end
120
+ end
121
+
122
+ it "contains no errors" do
123
+ expect(subject.errors).to be_empty
124
+ end
125
+ end
126
+
127
+ context "with a provider name that doesn't match any existing provider" do
128
+ let(:provider) { nil }
129
+
130
+ it "contains no errors" do
131
+ expect(subject.errors[:'provider.name']).to eq ["does not match an existing pacticipant"]
132
+ end
133
+ end
134
+
39
135
  context "with no request defined" do
40
136
  let(:json) { {}.to_json }
41
137
 
@@ -0,0 +1,64 @@
1
+ require 'pact_broker/api/decorators/triggered_webhook_decorator'
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Decorators
6
+ describe TriggeredWebhookDecorator do
7
+ let(:triggered_webhook) do
8
+ double('PactBroker::Webhooks::TriggeredWebhook',
9
+ trigger_type: PactBroker::Webhooks::TriggeredWebhook::TRIGGER_TYPE_RESOURCE_CREATION,
10
+ status: status,
11
+ failure?: failure,
12
+ retrying?: retrying,
13
+ trigger_uuid: '1234',
14
+ webhook_uuid: '4321',
15
+ request_description: "GET http://foo",
16
+ pact_publication: pact,
17
+ number_of_attempts_made: 1,
18
+ number_of_attempts_remaining: 2,
19
+ created_at: DateTime.new(2017),
20
+ updated_at: DateTime.new(2017)
21
+ )
22
+ end
23
+
24
+ let(:pact) do
25
+ double('pact',
26
+ provider: double(name: 'provider'),
27
+ consumer: double(name: 'consumer'),
28
+ consumer_version_number: '1',
29
+ name: 'foo '
30
+ )
31
+ end
32
+
33
+ let(:failure) { false }
34
+ let(:retrying) { false }
35
+ let(:status) { PactBroker::Webhooks::TriggeredWebhook::STATUS_SUCCESS }
36
+ let(:logs_url) { "http://example.org/webhooks/4321/trigger/1234/logs" }
37
+ let(:user_options) { { base_url: "http://example.org" } }
38
+
39
+ let(:json) do
40
+ TriggeredWebhookDecorator.new(triggered_webhook).to_json(user_options: user_options)
41
+ end
42
+
43
+ subject { JSON.parse(json, symbolize_names: true) }
44
+
45
+ it "includes a link to the logs" do
46
+ expect(subject[:_links][:logs][:href]).to eq logs_url
47
+ end
48
+
49
+ it "includes a link to the webhook" do
50
+ expect(subject[:_links][:'pb:webhook'][:href]).to eq "http://example.org/webhooks/4321"
51
+ end
52
+
53
+ it "includes the triggered webhooks properties" do
54
+ expect(subject).to include(
55
+ status: 'success',
56
+ triggerType: 'resource_creation',
57
+ attemptsMade: 1,
58
+ attemptsRemaining: 2
59
+ )
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end