minitel 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 65b9eb7da885c09645279a948daa4a61dfe74d7b
4
- data.tar.gz: f9f45910ae96e042306d4d900ecb6a849802c3b3
3
+ metadata.gz: 1a746a71bce4fb28ed51a555f0669724e7bfd133
4
+ data.tar.gz: 2981f18e075b1d60d55cc82cf9ca46eb07e3c60b
5
5
  SHA512:
6
- metadata.gz: 874a4d581a8c49727c1f54fd480d609d8af262c643eac4883c3ddeba794ec3188e3887614db1c54993b6ecd7658a37e0514a6fd1d672bd4b4a0aa3dfa3ab22b6
7
- data.tar.gz: bc4f9e8a874b86b7ca4199267ce1eaaad762d3d5c172b61e55ba80bb12055887bfc309f21b2bfbc313bddeac1458b00403625dd4be4ba9a76672053ad246cba4
6
+ metadata.gz: 056e50f9fe5f3793f9eb9833051c6aa9a50f9cfe10e8effb6ff07da42410513e6fecc4ec01928595c0307c128f64ae592338a793c54a5e5e98e95e93137572c2
7
+ data.tar.gz: b9b491b75dee0c22f75d96ebc5d808bd4716b3aefc332d73440378f07a371603c8ab2ed8defa2a958d1a2a2b937b83828810357b6d081143ca709b03835d91d4
checksums.yaml.gz.sig CHANGED
@@ -1,2 +1 @@
1
- D�(���D}TN}w�B'.Cb��i��U��_�K���6��a[/7��ؽKG��=� f9����:`�7��
2
- '�g�k���]�L<�Y��vR��ӵ��=Q"?�s�E�;���:^�Q��o�)��#ͣ����hޏ#;���g&sy��_��<�us�Y�3�VX(o*�g�8Q�� Ao5�p�cNGkGK��t)�[�׊��}ȃ=�T�j��e.�L�\�FZ?Lh��8m��|�����Z\BTWr�
1
+ ��C“�Q��AfV<3��!(����81/�'_�ag͒�HQ�]�Y�~��Ӝ�]��c��с��p�C�;��|\�k���Y�����E��Xӊ�U:S�&iJaR(>��#+:�)�k�\��5&q+�i�B��Q~��jΎ�.� �O�ֿK]���͕3|����V���tOcۧ����J��GiiY���� �\�%�=���/��mM*H��r�8b'q5mbS��|�\�@?v
data.tar.gz.sig CHANGED
Binary file
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+
data/.travis.yml CHANGED
@@ -1,14 +1,13 @@
1
1
  cache: bundler
2
2
  language: ruby
3
3
  rvm:
4
- - 2.1.3
5
- - 2.1.2
6
- - 2.1.1
7
- - 2.1.0
4
+ - 2.2.0
5
+ - 2.1.5
8
6
  - 2.0.0
9
7
  - 1.9.3
10
8
  - ruby-head
11
9
  script: bundle exec rspec
12
10
  notifications:
13
11
  email: false
12
+ sudo: false
14
13
 
data/Readme.md CHANGED
@@ -11,14 +11,21 @@ require 'minitel'
11
11
  # create a client
12
12
  client = Minitel::Client.new("https://user:pass@telex.heroku.com")
13
13
 
14
- # send a notifcation to the owner and collaborators of an app
15
- client.notify_app(app_uuid: '...', title: 'Something happened', body: 'here are the details')
14
+ # send a notification to the owner and collaborators of an app
15
+ client.notify_app(app_uuid: '...', title: 'Your database is on fire!', body: 'Sorry.')
16
16
  # => {"id"=>"uuid of message"}
17
17
 
18
- # send a notifcation to a user
19
- client.notify_user(user_uuid: '...', title: 'Something happened', body: 'here are the details')
18
+ # send a notification to a user
19
+ client.notify_user(user_uuid: '...', title: 'Here is your invoice', body: 'You owe us 65k.')
20
20
  # => {"id"=>"uuid of message"}
21
21
 
22
- # add folloup to a previous notificaiton
23
- client.notify_user(message_uuid: '...', body: 'here are even more details')
22
+ # send a notification with an email action
23
+ # see: https://developers.google.com/gmail/markup/reference/go-to-action
24
+ client.notify_user(user_uuid: '...',
25
+ title: 'Here is your invoice',
26
+ body: 'You owe us 65k.',
27
+ action: { label: 'View Invoice', url: 'https://heroku.com/invoices/12345-12-98765'})
28
+
29
+ # add folloup to a previous notification
30
+ client.add_followup(message_uuid: '...', body: 'here are even more details')
24
31
  ```
@@ -17,31 +17,40 @@ module Minitel
17
17
  end
18
18
 
19
19
  def notify_app(args)
20
- StrictArgs.enforce(args, [:app_uuid, :body, :title], :app_uuid)
21
- post_message('app', args[:app_uuid], args[:title], args[:body])
20
+ StrictArgs.enforce(args, [:app_uuid, :body, :title], [:action], :app_uuid)
21
+ if action = args[:action]
22
+ StrictArgs.enforce(action, [:label, :url])
23
+ end
24
+ post_message('app', args[:app_uuid], args[:title], args[:body], action)
22
25
  end
23
26
 
24
27
  def notify_user(args)
25
- StrictArgs.enforce(args, [:user_uuid, :body, :title], :user_uuid)
26
- post_message('user', args[:user_uuid], args[:title], args[:body])
28
+ StrictArgs.enforce(args, [:user_uuid, :body, :title], [:action], :user_uuid)
29
+ if action = args[:action]
30
+ StrictArgs.enforce(action, [:label, :url])
31
+ end
32
+ post_message('user', args[:user_uuid], args[:title], args[:body], action)
27
33
  end
28
34
 
29
35
  def add_followup(args)
30
- StrictArgs.enforce(args, [:message_uuid, :body], :message_uuid)
36
+ StrictArgs.enforce(args, [:message_uuid, :body], [], :message_uuid)
31
37
  followup = { body: args[:body] }
32
-
33
38
  post("/producer/messages/#{args[:message_uuid]}/followups", followup)
34
39
  end
35
40
 
36
41
  private
37
42
 
38
- def post_message(type, id, title, body)
43
+ def post_message(type, id, title, body, action)
39
44
  message = {
40
45
  title: title,
41
46
  body: body,
42
47
  target: {type: type, id: id}
43
48
  }
44
49
 
50
+ if action
51
+ message.merge!(action: action)
52
+ end
53
+
45
54
  post("/producer/messages", message)
46
55
  end
47
56
 
@@ -1,17 +1,21 @@
1
1
  module Minitel
2
2
  module StrictArgs
3
3
  extend self
4
- def enforce(args, keywords, uuid_field)
5
- ensure_strict_args(args.keys, keywords)
6
- ensure_no_nils(args, keywords)
7
- ensure_is_uuid(args[uuid_field])
4
+ def enforce(args, required, allowed=[], uuid_field=nil)
5
+ ensure_strict_args(args.keys, required, allowed)
6
+ ensure_no_nils(args, required)
7
+ ensure_is_uuid(args[uuid_field]) if uuid_field
8
8
  end
9
9
 
10
10
  # A Ruby 2.1 required keyword argument sorta backport
11
- def ensure_strict_args(keys, accept_keys)
12
- if keys.sort != accept_keys.sort
13
- delta = accept_keys - keys
14
- raise ArgumentError, "missing or extra keywords: #{delta.join(', ')}"
11
+ def ensure_strict_args(keys, required, allowed)
12
+ missing = required - keys
13
+ unless missing.empty?
14
+ raise ArgumentError, "missing keywords: #{missing.join(', ')}"
15
+ end
16
+ unknown = keys - (required + allowed)
17
+ unless unknown.empty?
18
+ raise ArgumentError, "extra keywords: #{unknown.join(', ')}"
15
19
  end
16
20
  end
17
21
 
@@ -1,3 +1,3 @@
1
1
  module Minitel
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
data/minitel.gemspec CHANGED
@@ -23,4 +23,5 @@ Gem::Specification.new do |gem|
23
23
  gem.add_development_dependency 'guard', '~> 2.6'
24
24
  gem.add_development_dependency 'guard-rspec', '~> 4.3'
25
25
  gem.add_development_dependency 'rspec', '~> 3.0'
26
+ gem.add_development_dependency 'webmock', '~> 1.20'
26
27
  end
@@ -30,25 +30,30 @@ end
30
30
  describe Minitel::Client, '#notify_app' do
31
31
  describe 'action' do
32
32
  let(:defaults) { {title: 'a title', body: 'a body', app_uuid: SecureRandom.uuid} }
33
- let(:client) { Minitel::Client.new('https://u:p@h.com') }
33
+ let(:client) { Minitel::Client.new('https://telex.com') }
34
34
 
35
35
  before do
36
- request = {path: '/producer/messages', method: :post}
37
- response = {status: 201, body: MultiJson.dump({'success' => true})}
38
- body = MultiJson.dump({
39
- title: 'a title',
40
- body: 'a body',
41
- target: {type: 'app', id: defaults[:app_uuid]}
42
- })
43
-
44
- Excon.stub(request.merge(body: body), response)
36
+ @stub = stub_request(:post, 'https://telex.com/producer/messages').
37
+ to_return(status: 201, body: MultiJson.encode(success: true))
45
38
  end
46
39
 
47
40
  it 'posts a proper json body to the producer messages endpoint' do
48
- expect{ client.notify_app(defaults) }.to_not raise_error
41
+ client.notify_app(defaults)
42
+ body = MultiJson.encode(
43
+ title: 'a title',
44
+ body: 'a body',
45
+ target: {type: 'app', id: defaults[:app_uuid]})
46
+ expect(@stub.with(body: body)).to have_been_requested
47
+ end
49
48
 
50
- unstubbed_body = defaults.merge({title: 'bad title'})
51
- expect{ client.notify_app(unstubbed_body) }.to raise_error(Excon::Errors::StubNotFound)
49
+ it 'supports actions' do
50
+ action = { label: 'omg', url: 'https://foo' }
51
+ client.notify_app(defaults.merge(action: action))
52
+ post_with_action = @stub.with do |req|
53
+ body = MultiJson.decode(req.body, symbolize_keys: true)
54
+ body[:action] == action
55
+ end
56
+ expect(post_with_action).to have_been_requested
52
57
  end
53
58
 
54
59
  it 'returns a parsed json response' do
@@ -61,25 +66,30 @@ end
61
66
 
62
67
  describe Minitel::Client, '#notify_user' do
63
68
  let(:defaults) { {title: 'a title', body: 'a body', user_uuid: SecureRandom.uuid} }
64
- let(:client) { Minitel::Client.new('https://u:p@h.com') }
69
+ let(:client) { Minitel::Client.new('https://telex.com') }
65
70
 
66
71
  before do
67
- request = {path: '/producer/messages', method: :post}
68
- response = {status: 201, body: MultiJson.dump({'success' => true})}
69
- body = MultiJson.dump({
70
- title: 'a title',
71
- body: 'a body',
72
- target: {type: 'user', id: defaults[:user_uuid]}
73
- })
74
-
75
- Excon.stub(request.merge(body: body), response)
72
+ @stub = stub_request(:post, 'https://telex.com/producer/messages').
73
+ to_return(status: 201, body: MultiJson.encode(success: true))
76
74
  end
77
75
 
78
76
  it 'posts a proper json body to the producer messages endpoint' do
79
- expect{ client.notify_user(defaults) }.to_not raise_error
77
+ client.notify_user(defaults)
78
+ body = MultiJson.encode(
79
+ title: 'a title',
80
+ body: 'a body',
81
+ target: {type: 'user', id: defaults[:user_uuid]})
82
+ expect(@stub.with(body: body)).to have_been_requested
83
+ end
80
84
 
81
- unstubbed_body = defaults.merge({title: 'bad title'})
82
- expect{ client.notify_user(unstubbed_body) }.to raise_error(Excon::Errors::StubNotFound)
85
+ it 'supports actions' do
86
+ action = { label: 'omg', url: 'https://foo' }
87
+ client.notify_user(defaults.merge(action: action))
88
+ post_with_action = @stub.with do |req|
89
+ body = MultiJson.decode(req.body, symbolize_keys: true)
90
+ body[:action] == action
91
+ end
92
+ expect(post_with_action).to have_been_requested
83
93
  end
84
94
 
85
95
  it 'returns a parsed json response' do
@@ -90,23 +100,17 @@ end
90
100
 
91
101
  describe Minitel::Client, '#add_followup' do
92
102
  let(:defaults) { {body: 'a body', message_uuid: SecureRandom.uuid} }
93
- let(:client) { Minitel::Client.new('https://u:p@h.com') }
103
+ let(:client) { Minitel::Client.new('https://telex.com') }
94
104
 
95
105
  before do
96
- request = {path: "/producer/messages/#{defaults[:message_uuid]}/followups", method: :post}
97
- response = {status: 201, body: MultiJson.dump({'success' => true})}
98
- body = MultiJson.dump({
99
- body: 'a body',
100
- })
101
-
102
- Excon.stub(request.merge(body: body), response)
106
+ @stub = stub_request(:post, "https://telex.com/producer/messages/#{defaults[:message_uuid]}/followups").
107
+ to_return(status: 201, body: MultiJson.encode(success: true))
103
108
  end
104
109
 
105
110
  it 'posts a proper json body to the producer messages endpoint' do
106
- expect{ client.add_followup(defaults) }.to_not raise_error
107
-
108
- unstubbed_body = defaults.merge({message_uuid: SecureRandom.uuid})
109
- expect{ client.add_followup(unstubbed_body) }.to raise_error(Excon::Errors::StubNotFound)
111
+ client.add_followup(defaults)
112
+ body = MultiJson.encode(body: 'a body')
113
+ expect(@stub.with(body: body)).to have_been_requested
110
114
  end
111
115
 
112
116
  it 'returns a parsed json response' do
@@ -4,31 +4,37 @@ describe Minitel::StrictArgs, '.enforce' do
4
4
  describe 'arguments' do
5
5
  before do
6
6
  @hash = {one: 1, two: 2, uuid: SecureRandom.uuid}
7
- @keys = @hash.keys
7
+ @required = [:one, :uuid]
8
+ @optional = [:two]
8
9
  end
9
10
 
10
11
  it 'works when all listed args are present' do
11
- expect { Minitel::StrictArgs.enforce(@hash, @keys, :uuid) }.to_not raise_error
12
+ expect { Minitel::StrictArgs.enforce(@hash, @required, @optional, :uuid) }.to_not raise_error
13
+ end
14
+
15
+ it 'works when optional args are omitted' do
16
+ @hash.delete(:two)
17
+ expect { Minitel::StrictArgs.enforce(@hash, @required, @optional, :uuid) }.to_not raise_error
12
18
  end
13
19
 
14
20
  it "fails when a key is missing from the arg hash" do
15
21
  @hash.delete(:one)
16
- expect { Minitel::StrictArgs.enforce(@hash, @keys, :uuid) }.to raise_error(ArgumentError)
22
+ expect { Minitel::StrictArgs.enforce(@hash, @required, @optional, :uuid) }.to raise_error(ArgumentError)
17
23
  end
18
24
 
19
25
  it "fails when a key is nil" do
20
26
  @hash[:one] = nil
21
- expect { Minitel::StrictArgs.enforce(@hash, @keys, :uuid) }.to raise_error(ArgumentError)
27
+ expect { Minitel::StrictArgs.enforce(@hash, @required, @optional, :uuid) }.to raise_error(ArgumentError)
22
28
  end
23
29
 
24
30
  it 'fails if the uuid column uuid is not a uuid' do
25
31
  @hash[:uuid] = "not a uuid"
26
- expect { Minitel::StrictArgs.enforce(@hash, @keys, :uuid) }.to raise_error(ArgumentError)
32
+ expect { Minitel::StrictArgs.enforce(@hash, @required, @optional, :uuid) }.to raise_error(ArgumentError)
27
33
  end
28
34
 
29
35
  it 'fails if there is an extra key' do
30
36
  @hash.merge!( {foo: 3} )
31
- expect { Minitel::StrictArgs.enforce(@hash, @keys, :uuid) }.to raise_error(ArgumentError)
37
+ expect { Minitel::StrictArgs.enforce(@hash, @required, @optional, :uuid) }.to raise_error(ArgumentError)
32
38
  end
33
39
  end
34
40
  end
data/spec/spec_helper.rb CHANGED
@@ -1,13 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'rspec'
3
+ require 'webmock/rspec'
3
4
  require 'minitel'
4
5
 
5
6
  RSpec.configure do |config|
6
- config.before(:all) do
7
- Excon.defaults[:mock] = true
8
- end
9
-
10
- config.after(:each) do
11
- Excon.stubs.clear
12
- end
13
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: minitel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Will Leinweber
@@ -28,7 +28,7 @@ cert_chain:
28
28
  5bkhRfJHSD/uX/cHbjmopLRbPlHrGbZTDIP4VEC5l0QLPiZ1nhKQnf3+U0+FSy2o
29
29
  CCngcLCR6q+mLf+A4L54VxmyrtFpcBfmkU72QYyf3vJ9QipL3XbvJvbpPkWSn1DX
30
30
  -----END CERTIFICATE-----
31
- date: 2014-10-21 00:00:00.000000000 Z
31
+ date: 2015-02-13 00:00:00.000000000 Z
32
32
  dependencies:
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: excon
@@ -100,6 +100,20 @@ dependencies:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
102
  version: '3.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: webmock
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '1.20'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '1.20'
103
117
  description: "\U0001D54B\U0001D53C\U0001D543\U0001D53C\U0001D54F client"
104
118
  email:
105
119
  - will@bitfission.com
@@ -108,6 +122,7 @@ extensions: []
108
122
  extra_rdoc_files: []
109
123
  files:
110
124
  - ".gitignore"
125
+ - ".rspec"
111
126
  - ".travis.yml"
112
127
  - Gemfile
113
128
  - Guardfile
@@ -143,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
158
  version: '0'
144
159
  requirements: []
145
160
  rubyforge_project:
146
- rubygems_version: 2.2.2
161
+ rubygems_version: 2.4.5
147
162
  signing_key:
148
163
  specification_version: 4
149
164
  summary: "\U0001D54B\U0001D53C\U0001D543\U0001D53C\U0001D54F client: see https://github.com/heroku/telex"
metadata.gz.sig CHANGED
Binary file