contentful-webhook-listener 0.1.0 → 0.2.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +6 -3
- data/CHANGELOG.md +4 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +1 -1
- data/README.md +55 -5
- data/contentful-webhook-listener.gemspec +2 -0
- data/lib/contentful/webhook/listener.rb +1 -0
- data/lib/contentful/webhook/listener/controllers.rb +1 -0
- data/lib/contentful/webhook/listener/controllers/base.rb +1 -1
- data/lib/contentful/webhook/listener/controllers/wait.rb +1 -0
- data/lib/contentful/webhook/listener/controllers/webhook_aware.rb +50 -0
- data/lib/contentful/webhook/listener/support/null_logger.rb +3 -1
- data/lib/contentful/webhook/listener/version.rb +1 -1
- data/lib/contentful/webhook/listener/webhooks.rb +80 -0
- data/spec/contentful/webhook/listener/controllers/wait_spec.rb +1 -17
- data/spec/contentful/webhook/listener/controllers/webhook_aware_spec.rb +26 -0
- data/spec/contentful/webhook/listener/webhooks_spec.rb +142 -0
- data/spec/spec_helper.rb +35 -1
- metadata +38 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ead87c79c6faa39c84983c279db131c1968c03ae
|
|
4
|
+
data.tar.gz: 78d9920ce209f081d38328df7d36d6f199981746
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2e5111ccd3751dda799a590371247f919933d2aed6f4604fe5bd459f54582825b40a78e23a25240f3a424a574fa6296cd6662c5d824b6d8ac8b0e0e31b0f68e4
|
|
7
|
+
data.tar.gz: ff31507c823c30180b93ad98fe4cd2985f4ba44fb956acd6d73a33c8438765d83c885ae9622f444c5f410a862c97eed7e5d05a1992cdcd069f8e28d313b3ab34
|
data/.travis.yml
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
rvm:
|
|
2
|
-
- 1.9.3
|
|
3
2
|
- 2.0.0
|
|
4
|
-
-
|
|
5
|
-
|
|
3
|
+
- 2.1.0
|
|
4
|
+
- 2.2.3
|
|
5
|
+
- 2.3.0
|
|
6
6
|
env: TEST=true
|
|
7
|
+
notifications:
|
|
8
|
+
slack:
|
|
9
|
+
secure: SJn1oaxNBtYfT3vDMY82Q4l8m2QlDfiLGwY4/N+5RNdw5u03ebAjoiuGrzcbWGRxt7eiFQjH/EyApq4f1WkB1jARdOg7I45IOIH1PEcks2U5PEqtRidNR/7ySm8UjAkDnXviZPhhBaUOCgQNNIl4zvLUnGKAJYTUvub2owWkGzT1pamewFq4JznPPpdzHW3BcAk/lo5a+vvLTIIeHwwYfcsRZYf+C3Q/Ii+S8RgXn8uAQ+TIv2uRR3o/whnnGXPghEUkBraS+KAdd46k9iEuL1D2DvogwGbPg0Rvd+g3LzpIKhVAvV1lIPiwBDXGeUYGgM5b2GcPVbpI/ktEeHKokIdKn9LpBQ1d63KQ2Sx23ggP2mXoF+0UIDZWiS9mG7UYyrf2YAps8/EPvist1AIJuu9UCs7Wxi+r3MaeBM/CM5vMLToTq3uWaBtbctIQl8DUslnC6m1kL4vPwKureMYQX1DssIZ5kyOkHNEHwKdre3j7R/9tWdWOgPotozACUNovOHh9a3DZusYZcFx+H56/SKIEnD50TNY3DguJbNwEdGHqhwQ/aql04qg/4jXfT5hnPNqLVzq+T+wu85t53CQP/+0PP/Rt7JZo9/CE9n1jEF7UrQbJRuyBCqkJU5+mkjVYM3wVgs9m1TFG+Y6sJyBrMd+W5aG0BM1QZ7QofX/pQN0=
|
data/CHANGELOG.md
CHANGED
data/Guardfile
ADDED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
|
@@ -30,24 +30,23 @@ Or install it yourself as:
|
|
|
30
30
|
|
|
31
31
|
## Usage
|
|
32
32
|
|
|
33
|
-
Require gem:
|
|
33
|
+
* Require gem:
|
|
34
34
|
|
|
35
35
|
```ruby
|
|
36
36
|
require 'contentful/webhook/listener'
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Create your own Controllers:
|
|
39
|
+
* Create your own Controllers:
|
|
40
40
|
|
|
41
41
|
```ruby
|
|
42
|
-
class MyController < Contentful::Webhook::Listener::Controllers::
|
|
42
|
+
class MyController < Contentful::Webhook::Listener::Controllers::Base
|
|
43
43
|
def perform(request, response)
|
|
44
|
-
super(request, response)
|
|
45
44
|
"do your process..." # This will run on a brackground Thread
|
|
46
45
|
end
|
|
47
46
|
end
|
|
48
47
|
```
|
|
49
48
|
|
|
50
|
-
Configure and start your Webhook Listener
|
|
49
|
+
* Configure and start your Webhook Listener
|
|
51
50
|
|
|
52
51
|
```ruby
|
|
53
52
|
require 'logger'
|
|
@@ -68,6 +67,57 @@ end
|
|
|
68
67
|
|
|
69
68
|
You can add multiple endpoints, each with it's own Controller.
|
|
70
69
|
|
|
70
|
+
### Webhook Aware Controllers
|
|
71
|
+
|
|
72
|
+
You can create controllers that can respond on specific Webhook events.
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
class MyController < Contentful::Webhook::Listener::Controllers::WebhookAware
|
|
76
|
+
def publish
|
|
77
|
+
# Do stuff on publish
|
|
78
|
+
if webhook.entry?
|
|
79
|
+
logger.info "published Entry ID: #{webhook.id} for Space: #{webhook.space_id}"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def unpublish
|
|
84
|
+
# Do stuff on unpublish
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def archive
|
|
88
|
+
# Do stuff on archive
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def unarchive
|
|
92
|
+
# Do stuff on unarchive
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def create
|
|
96
|
+
# Do stuff on create
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def save
|
|
100
|
+
# Do stuff on save
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def delete
|
|
104
|
+
# Do stuff on delete
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The controller has a `webhook` object bound when invoked, that has a few helpers:
|
|
110
|
+
|
|
111
|
+
* `webhook.entry?` will return if the webhook was fired for an Entry
|
|
112
|
+
* `webhook.asset?` will return if the webhook was fired for an Asset
|
|
113
|
+
* `webhook.content_type?` will return if the webhook was fired for a Content Type
|
|
114
|
+
|
|
115
|
+
* `webhook.id` will return the Resource (Entry/Asset/Content Type) ID
|
|
116
|
+
* `webhook.space_id` will return the Space ID
|
|
117
|
+
|
|
118
|
+
* `webhook.sys` will include the metadata for the resource
|
|
119
|
+
* `webhook.fields` will include the resource fields (not included on Unpublish)
|
|
120
|
+
|
|
71
121
|
## Contributing
|
|
72
122
|
|
|
73
123
|
1. Fork it ( https://github.com/[my-github-username]/contentful-webhook-listener/fork )
|
|
@@ -21,4 +21,6 @@ Gem::Specification.new do |spec|
|
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.6"
|
|
22
22
|
spec.add_development_dependency "rake"
|
|
23
23
|
spec.add_development_dependency "rspec"
|
|
24
|
+
spec.add_development_dependency "guard"
|
|
25
|
+
spec.add_development_dependency "guard-rspec"
|
|
24
26
|
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'contentful/webhook/listener/controllers/wait'
|
|
2
|
+
require 'contentful/webhook/listener/webhooks'
|
|
3
|
+
|
|
4
|
+
module Contentful
|
|
5
|
+
module Webhook
|
|
6
|
+
module Listener
|
|
7
|
+
module Controllers
|
|
8
|
+
class WebhookAware < Wait
|
|
9
|
+
attr_reader :webhook
|
|
10
|
+
|
|
11
|
+
def publish
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def unpublish
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def archive
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def unarchive
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def save
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def auto_save
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def create
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def delete
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
protected
|
|
36
|
+
|
|
37
|
+
def perform(request, response)
|
|
38
|
+
@webhook = WebhookFactory.new(request).create
|
|
39
|
+
super(request, response)
|
|
40
|
+
logger.debug "Webhook Data: {id: #{webhook.id}, space_id: #{webhook.space_id}, kind: #{webhook.kind}, event: #{webhook.event}}"
|
|
41
|
+
send(webhook.event)
|
|
42
|
+
rescue
|
|
43
|
+
response.body = "Not a Webhook"
|
|
44
|
+
response.status = 400
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -4,7 +4,7 @@ module Contentful
|
|
|
4
4
|
module Support
|
|
5
5
|
# NullLogger will silence any call to the :logger instance
|
|
6
6
|
class NullLogger
|
|
7
|
-
def write(
|
|
7
|
+
def write(*)
|
|
8
8
|
nil
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -12,6 +12,8 @@ module Contentful
|
|
|
12
12
|
alias_method :debug, :write
|
|
13
13
|
alias_method :warn, :write
|
|
14
14
|
alias_method :error, :write
|
|
15
|
+
alias_method :fatal, :write
|
|
16
|
+
alias_method :debug?, :write
|
|
15
17
|
end
|
|
16
18
|
end
|
|
17
19
|
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
module Contentful
|
|
4
|
+
module Webhook
|
|
5
|
+
module Listener
|
|
6
|
+
module WebhookConstants
|
|
7
|
+
WEBHOOK_TOPIC = 'X-Contentful-Topic'
|
|
8
|
+
WEBHOOK_NAME = 'X-Contentful-Webhook-Name'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class WebhookFactory
|
|
12
|
+
def initialize(request)
|
|
13
|
+
@headers = {}
|
|
14
|
+
request.each { |header, value| @headers[header] = value }
|
|
15
|
+
@body = JSON.load(request.body)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create
|
|
19
|
+
webhook_class.new(@headers, @body)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def webhook_class
|
|
25
|
+
Object.const_get(webhook_class_name)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def webhook_class_name
|
|
29
|
+
event_name = @headers[::Contentful::Webhook::Listener::WebhookConstants::WEBHOOK_TOPIC].split('.')[-1].split('_').collect(&:capitalize).join
|
|
30
|
+
"Contentful::Webhook::Listener::#{event_name}Webhook"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
class BaseWebhook
|
|
35
|
+
attr_reader :origin, :kind, :event, :raw_topic, :raw_headers, :raw_body, :id, :name, :space_id, :sys
|
|
36
|
+
|
|
37
|
+
def initialize(headers, body)
|
|
38
|
+
@raw_topic = headers[::Contentful::Webhook::Listener::WebhookConstants::WEBHOOK_TOPIC]
|
|
39
|
+
@name = headers[::Contentful::Webhook::Listener::WebhookConstants::WEBHOOK_NAME]
|
|
40
|
+
@origin, @kind, @event = @raw_topic.split('.')
|
|
41
|
+
@raw_body = body
|
|
42
|
+
@raw_headers = headers
|
|
43
|
+
@sys = body['sys']
|
|
44
|
+
@id = sys['id']
|
|
45
|
+
@space_id = sys['space']['sys']['id']
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def entry?
|
|
49
|
+
kind == 'Entry'
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def asset?
|
|
53
|
+
kind == 'Asset'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def content_type?
|
|
57
|
+
kind == 'ContentType'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class FieldWebhook < BaseWebhook
|
|
62
|
+
attr_reader :fields
|
|
63
|
+
|
|
64
|
+
def initialize(headers, body)
|
|
65
|
+
super(headers, body)
|
|
66
|
+
@fields = body['fields']
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class PublishWebhook < FieldWebhook; end
|
|
71
|
+
class SaveWebhook < FieldWebhook; end
|
|
72
|
+
class AutoSaveWebhook < FieldWebhook; end
|
|
73
|
+
class CreateWebhook < FieldWebhook; end
|
|
74
|
+
class ArchiveWebhook < FieldWebhook; end
|
|
75
|
+
class UnarchiveWebhook < FieldWebhook; end
|
|
76
|
+
class UnpublishWebhook < BaseWebhook; end
|
|
77
|
+
class DeleteWebhook < BaseWebhook; end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -1,19 +1,5 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
class Contentful::Webhook::Listener::Controllers::Wait
|
|
4
|
-
@@sleeping = false
|
|
5
|
-
|
|
6
|
-
def sleep(time)
|
|
7
|
-
@@sleeping = true
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def self.sleeping
|
|
11
|
-
value = @@sleeping
|
|
12
|
-
@@sleeping = false
|
|
13
|
-
value
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
3
|
describe Contentful::Webhook::Listener::Controllers::Wait do
|
|
18
4
|
let(:server) { MockServer.new }
|
|
19
5
|
let(:logger) { Contentful::Webhook::Listener::Support::NullLogger.new }
|
|
@@ -31,9 +17,7 @@ describe Contentful::Webhook::Listener::Controllers::Wait do
|
|
|
31
17
|
# This spec requires to read/erase a Class Variable
|
|
32
18
|
# because RSpec doesn't know how to test within spawned Threads
|
|
33
19
|
it "##{name} wait on background" do
|
|
34
|
-
wait.send(name, MockRequest.new, MockResponse.new)
|
|
35
|
-
|
|
36
|
-
sleep(0.1) # Wait for Thread to actually run
|
|
20
|
+
wait.send(name, MockRequest.new, MockResponse.new).join
|
|
37
21
|
|
|
38
22
|
expect(wait.class.sleeping).to be_truthy
|
|
39
23
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Contentful::Webhook::Listener::Controllers::WebhookAware do
|
|
4
|
+
let(:server) { MockServer.new }
|
|
5
|
+
let(:logger) { Contentful::Webhook::Listener::Support::NullLogger.new }
|
|
6
|
+
let(:timeout) { 10 }
|
|
7
|
+
let(:body) { {sys: { id: 'foo', space: { sys: { id: 'space_foo' } } }, fields: {} } }
|
|
8
|
+
subject { described_class.new(server, logger, timeout) }
|
|
9
|
+
|
|
10
|
+
describe 'event methods called for corresponding webhook event type' do
|
|
11
|
+
[:publish, :unpublish, :archive, :unarchive, :save, :auto_save, :create, :delete].each do |event|
|
|
12
|
+
it "calls ##{event}" do
|
|
13
|
+
expect(subject).to receive(event)
|
|
14
|
+
subject.respond(RequestDummy.new({'X-Contentful-Topic' => "ContentfulManagement.Entry.#{event}"}, body), MockResponse.new).join
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'returns 400 Bad Request on non-webhook call' do
|
|
20
|
+
response = MockResponse.new
|
|
21
|
+
subject.respond(RequestDummy.new(nil, "foo"), response).join
|
|
22
|
+
|
|
23
|
+
expect(response.status).to eq(400)
|
|
24
|
+
expect(response.body).to eq('Not a Webhook')
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Contentful::Webhook::Listener::WebhookFactory do
|
|
4
|
+
let(:body) { {sys: { id: 'foo', space: { sys: { id: 'space_foo' } } }, fields: {} } }
|
|
5
|
+
let(:topic) { 'ContentfulManagement.Entry.publish' }
|
|
6
|
+
let(:name) { 'WebhookName' }
|
|
7
|
+
let(:request) { RequestDummy.new({'X-Contentful-Topic' => topic, 'X-Contentful-Webhook-Name' => name}, body) }
|
|
8
|
+
subject { described_class.new(request) }
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
describe 'instance methods' do
|
|
12
|
+
describe '#create' do
|
|
13
|
+
describe 'retrieves an instance of the correct webhook type' do
|
|
14
|
+
it 'publish event creates a PublishWebhook' do
|
|
15
|
+
webhook = described_class.new(RequestDummy.new({'X-Contentful-Topic' => 'ContentfulManagement.Entry.publish'}, body)).create
|
|
16
|
+
expect(webhook).to be_a Contentful::Webhook::Listener::PublishWebhook
|
|
17
|
+
end
|
|
18
|
+
it 'save event creates a SaveWebhook' do
|
|
19
|
+
webhook = described_class.new(RequestDummy.new({'X-Contentful-Topic' => 'ContentfulManagement.Entry.save'}, body)).create
|
|
20
|
+
expect(webhook).to be_a Contentful::Webhook::Listener::SaveWebhook
|
|
21
|
+
end
|
|
22
|
+
it 'auto_save event creates an AutoSaveWebhook' do
|
|
23
|
+
webhook = described_class.new(RequestDummy.new({'X-Contentful-Topic' => 'ContentfulManagement.Entry.auto_save'}, body)).create
|
|
24
|
+
expect(webhook).to be_a Contentful::Webhook::Listener::AutoSaveWebhook
|
|
25
|
+
end
|
|
26
|
+
it 'create event creates a CreateWebhook' do
|
|
27
|
+
webhook = described_class.new(RequestDummy.new({'X-Contentful-Topic' => 'ContentfulManagement.Entry.create'}, body)).create
|
|
28
|
+
expect(webhook).to be_a Contentful::Webhook::Listener::CreateWebhook
|
|
29
|
+
end
|
|
30
|
+
it 'archive event creates a ArchiveWebhook' do
|
|
31
|
+
webhook = described_class.new(RequestDummy.new({'X-Contentful-Topic' => 'ContentfulManagement.Entry.archive'}, body)).create
|
|
32
|
+
expect(webhook).to be_a Contentful::Webhook::Listener::ArchiveWebhook
|
|
33
|
+
end
|
|
34
|
+
it 'unarchive event creates a UnarchiveWebhook' do
|
|
35
|
+
webhook = described_class.new(RequestDummy.new({'X-Contentful-Topic' => 'ContentfulManagement.Entry.unarchive'}, body)).create
|
|
36
|
+
expect(webhook).to be_a Contentful::Webhook::Listener::UnarchiveWebhook
|
|
37
|
+
end
|
|
38
|
+
it 'unpublish event creates a UnpublishWebhook' do
|
|
39
|
+
webhook = described_class.new(RequestDummy.new({'X-Contentful-Topic' => 'ContentfulManagement.Entry.unpublish'}, body)).create
|
|
40
|
+
expect(webhook).to be_a Contentful::Webhook::Listener::UnpublishWebhook
|
|
41
|
+
end
|
|
42
|
+
it 'delete event creates a DeleteWebhook' do
|
|
43
|
+
webhook = described_class.new(RequestDummy.new({'X-Contentful-Topic' => 'ContentfulManagement.Entry.delete'}, body)).create
|
|
44
|
+
expect(webhook).to be_a Contentful::Webhook::Listener::DeleteWebhook
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe Contentful::Webhook::Listener::BaseWebhook do
|
|
52
|
+
let(:body) { {'sys' => { 'id' => 'foo', 'space' => { 'sys' => { 'id' => 'space_foo' } } }, 'fields' => {} } }
|
|
53
|
+
let(:topic) { 'ContentfulManagement.Entry.publish' }
|
|
54
|
+
let(:name) { 'WebhookName' }
|
|
55
|
+
let(:headers) { {'X-Contentful-Topic' => topic, 'X-Contentful-Webhook-Name' => name} }
|
|
56
|
+
subject { described_class.new(headers, body) }
|
|
57
|
+
|
|
58
|
+
describe 'attributes' do
|
|
59
|
+
it ':origin' do
|
|
60
|
+
expect(subject.origin).to eq 'ContentfulManagement'
|
|
61
|
+
end
|
|
62
|
+
it ':kind' do
|
|
63
|
+
expect(subject.kind).to eq 'Entry'
|
|
64
|
+
end
|
|
65
|
+
it ':event' do
|
|
66
|
+
expect(subject.event).to eq 'publish'
|
|
67
|
+
end
|
|
68
|
+
it ':raw_topic' do
|
|
69
|
+
expect(subject.raw_topic).to eq 'ContentfulManagement.Entry.publish'
|
|
70
|
+
end
|
|
71
|
+
it ':raw_body' do
|
|
72
|
+
expect(subject.raw_body).to eq body
|
|
73
|
+
end
|
|
74
|
+
it ':id' do
|
|
75
|
+
expect(subject.id).to eq 'foo'
|
|
76
|
+
end
|
|
77
|
+
it ':name' do
|
|
78
|
+
expect(subject.name).to eq 'WebhookName'
|
|
79
|
+
end
|
|
80
|
+
it ':space_id' do
|
|
81
|
+
expect(subject.space_id).to eq 'space_foo'
|
|
82
|
+
end
|
|
83
|
+
it ':sys' do
|
|
84
|
+
expect(subject.sys).to eq body['sys']
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe 'instance methods' do
|
|
89
|
+
describe 'kind methods' do
|
|
90
|
+
describe '#entry?' do
|
|
91
|
+
it 'true when kind == Entry' do
|
|
92
|
+
expect(described_class.new(headers, body).entry?).to be_truthy
|
|
93
|
+
end
|
|
94
|
+
it 'false when kind != Entry' do
|
|
95
|
+
headers['X-Contentful-Topic'] = 'ContentfulManagement.Asset.publish'
|
|
96
|
+
expect(described_class.new(headers, body).entry?).to be_falsey
|
|
97
|
+
|
|
98
|
+
headers['X-Contentful-Topic'] = 'ContentfulManagement.ContentType.publish'
|
|
99
|
+
expect(described_class.new(headers, body).entry?).to be_falsey
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
describe '#asset?' do
|
|
103
|
+
it 'true when kind == Asset' do
|
|
104
|
+
headers['X-Contentful-Topic'] = 'ContentfulManagement.Asset.publish'
|
|
105
|
+
expect(described_class.new(headers, body).asset?).to be_truthy
|
|
106
|
+
end
|
|
107
|
+
it 'false when kind != Asset' do
|
|
108
|
+
expect(described_class.new(headers, body).asset?).to be_falsey
|
|
109
|
+
|
|
110
|
+
headers['X-Contentful-Topic'] = 'ContentfulManagement.ContentType.publish'
|
|
111
|
+
expect(described_class.new(headers, body).asset?).to be_falsey
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
describe '#content_type?' do
|
|
115
|
+
it 'true when kind == ContentType' do
|
|
116
|
+
headers['X-Contentful-Topic'] = 'ContentfulManagement.ContentType.publish'
|
|
117
|
+
expect(described_class.new(headers, body).content_type?).to be_truthy
|
|
118
|
+
end
|
|
119
|
+
it 'false when kind != ContentType' do
|
|
120
|
+
expect(described_class.new(headers, body).content_type?).to be_falsey
|
|
121
|
+
|
|
122
|
+
headers['X-Contentful-Topic'] = 'ContentfulManagement.Asset.publish'
|
|
123
|
+
expect(described_class.new(headers, body).content_type?).to be_falsey
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe Contentful::Webhook::Listener::FieldWebhook do
|
|
131
|
+
let(:body) { {'sys' => { 'id' => 'foo', 'space' => { 'sys' => { 'id' => 'space_foo' } } }, 'fields' => {} } }
|
|
132
|
+
let(:topic) { 'ContentfulManagement.Entry.publish' }
|
|
133
|
+
let(:name) { 'WebhookName' }
|
|
134
|
+
let(:headers) { {'X-Contentful-Topic' => topic, 'X-Contentful-Webhook-Name' => name} }
|
|
135
|
+
subject { described_class.new(headers, body) }
|
|
136
|
+
|
|
137
|
+
describe 'attributes' do
|
|
138
|
+
it ':fields' do
|
|
139
|
+
expect(subject.fields).to eq body['fields']
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
$LOAD_PATH.unshift File.expand_path('lib', __FILE__)
|
|
2
2
|
|
|
3
|
-
require 'contentful/webhook/listener'
|
|
4
3
|
require 'rspec'
|
|
5
4
|
require 'rspec/mocks'
|
|
5
|
+
require 'contentful/webhook/listener'
|
|
6
|
+
require 'json'
|
|
6
7
|
|
|
7
8
|
class MockServer
|
|
8
9
|
def [](key)
|
|
@@ -16,3 +17,36 @@ end
|
|
|
16
17
|
class MockResponse
|
|
17
18
|
attr_accessor :status, :body
|
|
18
19
|
end
|
|
20
|
+
|
|
21
|
+
class RequestDummy
|
|
22
|
+
attr_reader :headers, :body
|
|
23
|
+
|
|
24
|
+
def initialize(headers, body)
|
|
25
|
+
@headers = headers || {}
|
|
26
|
+
@body = JSON.dump(body)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def [](key)
|
|
30
|
+
headers[key]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def each
|
|
34
|
+
headers.each do |h, v|
|
|
35
|
+
yield(h, v)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class Contentful::Webhook::Listener::Controllers::Wait
|
|
41
|
+
@@sleeping = false
|
|
42
|
+
|
|
43
|
+
def sleep(time)
|
|
44
|
+
@@sleeping = true
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.sleeping
|
|
48
|
+
value = @@sleeping
|
|
49
|
+
@@sleeping = false
|
|
50
|
+
value
|
|
51
|
+
end
|
|
52
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: contentful-webhook-listener
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Contentful GmbH (David Litvak Bruno)
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2016-04-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -52,6 +52,34 @@ dependencies:
|
|
|
52
52
|
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: guard
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: guard-rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
55
83
|
description: A Simple HTTP Webserver with pluggable behavior for listening to Contentful
|
|
56
84
|
API Webhooks
|
|
57
85
|
email:
|
|
@@ -65,6 +93,7 @@ files:
|
|
|
65
93
|
- CHANGELOG.md
|
|
66
94
|
- CONTRIBUTING.md
|
|
67
95
|
- Gemfile
|
|
96
|
+
- Guardfile
|
|
68
97
|
- LICENSE
|
|
69
98
|
- LICENSE.txt
|
|
70
99
|
- README.md
|
|
@@ -74,14 +103,18 @@ files:
|
|
|
74
103
|
- lib/contentful/webhook/listener/controllers.rb
|
|
75
104
|
- lib/contentful/webhook/listener/controllers/base.rb
|
|
76
105
|
- lib/contentful/webhook/listener/controllers/wait.rb
|
|
106
|
+
- lib/contentful/webhook/listener/controllers/webhook_aware.rb
|
|
77
107
|
- lib/contentful/webhook/listener/server.rb
|
|
78
108
|
- lib/contentful/webhook/listener/support.rb
|
|
79
109
|
- lib/contentful/webhook/listener/support/null_logger.rb
|
|
80
110
|
- lib/contentful/webhook/listener/version.rb
|
|
111
|
+
- lib/contentful/webhook/listener/webhooks.rb
|
|
81
112
|
- spec/contentful/webhook/listener/controllers/base_spec.rb
|
|
82
113
|
- spec/contentful/webhook/listener/controllers/wait_spec.rb
|
|
114
|
+
- spec/contentful/webhook/listener/controllers/webhook_aware_spec.rb
|
|
83
115
|
- spec/contentful/webhook/listener/server_spec.rb
|
|
84
116
|
- spec/contentful/webhook/listener/support/null_logger_spec.rb
|
|
117
|
+
- spec/contentful/webhook/listener/webhooks_spec.rb
|
|
85
118
|
- spec/spec_helper.rb
|
|
86
119
|
homepage: https://github.com/contentful/contentful-webhook-listener.rb
|
|
87
120
|
licenses:
|
|
@@ -103,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
103
136
|
version: '0'
|
|
104
137
|
requirements: []
|
|
105
138
|
rubyforge_project:
|
|
106
|
-
rubygems_version: 2.
|
|
139
|
+
rubygems_version: 2.5.0
|
|
107
140
|
signing_key:
|
|
108
141
|
specification_version: 4
|
|
109
142
|
summary: A Simple HTTP Webserver with pluggable behavior for listening to Contentful
|
|
@@ -111,6 +144,8 @@ summary: A Simple HTTP Webserver with pluggable behavior for listening to Conten
|
|
|
111
144
|
test_files:
|
|
112
145
|
- spec/contentful/webhook/listener/controllers/base_spec.rb
|
|
113
146
|
- spec/contentful/webhook/listener/controllers/wait_spec.rb
|
|
147
|
+
- spec/contentful/webhook/listener/controllers/webhook_aware_spec.rb
|
|
114
148
|
- spec/contentful/webhook/listener/server_spec.rb
|
|
115
149
|
- spec/contentful/webhook/listener/support/null_logger_spec.rb
|
|
150
|
+
- spec/contentful/webhook/listener/webhooks_spec.rb
|
|
116
151
|
- spec/spec_helper.rb
|