pushover 1.0.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
1
  module Pushover
2
- # The current version of Pushover.
3
- VERSION = "1.0.4"
2
+ # The current version of Pushover.
3
+ VERSION = "2.0.0".freeze
4
4
  end
@@ -1,33 +1,46 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/pushover/version', __FILE__)
3
-
4
- Gem::Specification.new do |gem|
5
- gem.name = "pushover"
6
- gem.authors = ["Ernie Brodeur"]
7
- gem.email = ["ebrodeur@ujami.net"]
8
- gem.date = Time.now.strftime('%Y-%m-%d')
9
- gem.version = Pushover::VERSION
10
- gem.platform = Gem::Platform::RUBY
11
- gem.license = "Beerware v42"
1
+ require File.expand_path('lib/pushover/version', __dir__)
2
+ Gem::Specification.new do |spec|
3
+ spec.name = 'pushover'
4
+ spec.authors = ['Ernie Brodeur']
5
+ spec.email = ['ebrodeur@ujami.net']
6
+ spec.date = Time.now.strftime('%Y-%m-%d')
7
+ spec.version = Pushover::VERSION
8
+ spec.platform = Gem::Platform::RUBY
9
+ spec.license = 'MIT'
12
10
 
13
11
  # descriptions
14
- gem.description = "Api (and CLI) to interface with pushover.net"
15
- gem.summary = "This gem provides both an API and CLI interface to pushover.net."
16
- gem.homepage = "https://github.com/erniebrodeur/pushover"
12
+ spec.description = 'Api (and CLI) to interface with pushover.net'
13
+ spec.summary = 'This spec provides both an API and CLI interface to pushover.net.'
14
+ spec.homepage = 'https://github.com/erniebrodeur/pushover'
17
15
 
18
- #files
19
- gem.files = `git ls-files`.split($\)
20
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
21
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
- gem.require_paths = ["lib"]
16
+ # files
17
+ spec.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
18
+ spec.executables = spec.files.grep(%r{^bin/}).map { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
23
21
 
24
22
  # documentation
25
- gem.extra_rdoc_files = Dir.glob("*.md")
26
- gem.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Pushover", "--main", "README.md", "--encoding=UTF-8"]
27
- gem.has_rdoc = 'yard'
23
+ spec.extra_rdoc_files = Dir.glob('*.md')
24
+ spec.rdoc_options = ['--line-numbers', '--inline-source', '--title', 'Pushover', '--main', 'README.md', '--encoding=UTF-8']
25
+ spec.has_rdoc = 'yard'
28
26
 
29
27
  # dependencies.
30
- gem.add_runtime_dependency 'yajl-ruby', "= 1.1.0"
31
- gem.add_runtime_dependency 'httparty', "= 0.11.0"
32
- gem.add_runtime_dependency 'bini', "= 0.7.0"
28
+ spec.add_runtime_dependency 'creatable'
29
+ spec.add_runtime_dependency 'excon'
30
+ spec.add_runtime_dependency 'oj'
31
+
32
+ spec.add_development_dependency 'bundler'
33
+ spec.add_development_dependency 'guard'
34
+ spec.add_development_dependency 'guard-bundler'
35
+ spec.add_development_dependency 'guard-rspec'
36
+ spec.add_development_dependency 'guard-rubocop'
37
+ spec.add_development_dependency 'guard-yard'
38
+ spec.add_development_dependency 'pry'
39
+ spec.add_development_dependency 'rake'
40
+ spec.add_development_dependency 'rspec'
41
+ spec.add_development_dependency 'rubocop'
42
+ spec.add_development_dependency 'rubocop-rspec'
43
+ spec.add_development_dependency 'simplecov'
44
+ spec.add_development_dependency 'simplecov-console'
45
+ spec.add_development_dependency 'yard'
33
46
  end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ module Pushover
4
+ describe Api do
5
+ it { expect(described_class).to respond_to(:endpoints).with(0).argument }
6
+ it { expect(described_class).to respond_to(:connection).with(0).argument }
7
+ it { expect(described_class).to respond_to(:url).with(0).argument }
8
+ it { expect(described_class).to respond_to(:sounds).with(0).argument }
9
+ it { expect(described_class).to respond_to(:initialize).with(0).argument }
10
+
11
+ describe '::initialize' do
12
+ before { described_class.initialize }
13
+
14
+ it "is expected to set excon default Headers Content-Type to 'application/json'" do
15
+ expect(Excon.defaults[:headers]).to include('Content-Type' => 'application/json')
16
+ end
17
+
18
+ it "is expected to set excon default Headers User-Agent to 'pushover (ruby gem) v#{Pushover::VERSION}'" do
19
+ expect(Excon.defaults[:headers]).to include('User-Agent' => "pushover (ruby gem) v#{Pushover::VERSION}")
20
+ end
21
+ end
22
+
23
+ describe '::endpoints' do
24
+ it { expect(described_class.endpoints).to be_a_kind_of(Array) & include(a_kind_of(Symbol)) }
25
+ end
26
+
27
+ describe '::connection' do
28
+ it "is expected to return an excon connection" do
29
+ expect(described_class.connection).to be_a_kind_of Excon::Connection
30
+ end
31
+ end
32
+
33
+ describe '::sounds' do
34
+ it { expect(described_class.sounds).to be_a_kind_of(Array) & include(a_kind_of(Symbol)) }
35
+ end
36
+
37
+ describe '::url' do
38
+ it { expect(described_class.url).to eq 'https://api.pushover.net' }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ module Pushover
4
+ describe Message do
5
+ describe "Attributes" do
6
+ it { is_expected.to have_attributes(attachment: nil) }
7
+ it { is_expected.to have_attributes(device: nil) }
8
+ it { is_expected.to have_attributes(html: nil) }
9
+ it { is_expected.to have_attributes(message: nil) }
10
+ it { is_expected.to have_attributes(priority: nil) }
11
+ it { is_expected.to have_attributes(response: nil) }
12
+ it { is_expected.to have_attributes(sound: nil) }
13
+ it { is_expected.to have_attributes(timestamp: a_kind_of(Numeric)) }
14
+ it { is_expected.to have_attributes(title: nil) }
15
+ it { is_expected.to have_attributes(token: nil) }
16
+ it { is_expected.to have_attributes(url_title: nil) }
17
+ it { is_expected.to have_attributes(url: nil) }
18
+ it { is_expected.to have_attributes(user: nil) }
19
+ end
20
+
21
+ it { expect(described_class).to be_a_kind_of(Class) }
22
+ it { is_expected.to be_a_kind_of Creatable }
23
+
24
+ describe "Instance Signatures" do
25
+ it { is_expected.to respond_to(:push).with(0).argument }
26
+ end
27
+
28
+ describe "::push" do
29
+ let(:body) { { "status": 1, "request": "647d2300-702c-4b38-8b2f-d56326ae460b" } }
30
+ let(:excon_connection) { Excon.new Api.url }
31
+ let(:excon_response) { Excon::Response.new(body: Oj.dump(body), status: 200) }
32
+ let(:params) { { user: '1234', token: '1234', message: 'abcd' } }
33
+ let(:request) { Request.create }
34
+ let(:response) { Response.create original: excon_response }
35
+ let(:working_message) { described_class.create params }
36
+
37
+ before do
38
+ allow(Api).to receive(:connection).and_return excon_connection
39
+ allow(excon_connection).to receive(:post).and_return excon_response
40
+ allow(Response).to receive(:create).and_return response
41
+ end
42
+
43
+ shared_examples 'required_param' do |param|
44
+ context "when #{param} is not set" do
45
+ before { working_message.instance_variable_set "@#{param}".to_sym, nil }
46
+
47
+ it { expect { working_message.push }.to raise_error ArgumentError, /#{param} is a required parameter/ }
48
+ end
49
+ end
50
+
51
+ shared_examples 'extra_param' do |param|
52
+ context "when a #{param} is provided" do
53
+ before { working_message.instance_variable_set "@#{param}".to_sym, 'not_nil' }
54
+
55
+ it "is expected to add the #{param} to the query" do
56
+ working_message.push
57
+ expect(excon_connection).to have_received(:post).with(query: a_hash_including(param.to_s => 'not_nil'), path: '1/messages.json')
58
+ end
59
+ end
60
+ end
61
+
62
+ %i[message token user].each do |param|
63
+ include_examples 'required_param', param
64
+ end
65
+
66
+ %i[attachment device html priority sound title url_title url].each do |param|
67
+ include_examples 'extra_param', param
68
+ end
69
+
70
+ it "is expected to call Request.create with ..." do
71
+ allow(Request).to receive(:create).and_return(request)
72
+ working_message.push
73
+ expect(Request).to have_received(:create).with(no_args)
74
+ end
75
+
76
+ it "is expected to return response" do
77
+ expect(working_message.push).to eq response
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+ module Pushover
4
+ describe Receipt do
5
+ end
6
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ module Pushover
4
+ describe Request do
5
+
6
+ let(:endpoint) { :messages }
7
+ let(:excon_connection) { Excon.new Api.url }
8
+ let(:params) { { user: '1234', token: '1234', message: 'abcd' } }
9
+ let(:request) { described_class.create }
10
+ let(:excon_response) { Excon::Response.new(body: Oj.dump(body), status: 200, headers: headers) }
11
+ let(:body) { { "status" => 1, "request" => "647d2300-702c-4b38-8b2f-d56326ae460b" } }
12
+ let(:request) { Request.new }
13
+ let(:response) { Response.create original: excon_response }
14
+ let(:headers) do
15
+ {
16
+ "X-Limit-App-Limit": 7500,
17
+ "X-Limit-App-Remaining": 7496,
18
+ "X-Limit-App-Reset": 1_393_653_600
19
+ }
20
+ end
21
+
22
+ it { expect(described_class).to be_a_kind_of(Class) }
23
+ it { is_expected.to be_a_kind_of Creatable }
24
+
25
+ describe "Instance Signatures" do
26
+ it { is_expected.to respond_to(:push).with(2).argument }
27
+ end
28
+
29
+ describe "::push" do
30
+ before do
31
+ allow(Api).to receive(:connection).and_return excon_connection
32
+ allow(excon_connection).to receive(:post).and_return excon_response
33
+ allow(Response).to receive(:create).and_return response
34
+ allow(response).to receive(:process).and_call_original
35
+ end
36
+
37
+
38
+ let(:request) { described_class.new }
39
+
40
+ it 'is expected to call Api.connection.get with query set to the second argument' do
41
+ request.push endpoint, params
42
+ expect(excon_connection).to have_received(:post).with(query: a_kind_of(Hash), path: '1/messages.json')
43
+ end
44
+
45
+ it "is expected to call Response.create with the response set to original" do
46
+ request.push endpoint, params
47
+ expect(Response).to have_received(:create).with(original: a_kind_of(Excon::Response))
48
+ end
49
+
50
+ it "is expected to call response.process to populate the object" do
51
+ request.push endpoint, params
52
+ expect(response).to have_received(:process)
53
+ end
54
+
55
+ it "is expected to return request" do
56
+ expect(request.push endpoint, params).to eq response
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+
3
+ module Pushover
4
+ describe Response do
5
+ let(:body) { { "status" => 1, "request" => "647d2300-702c-4b38-8b2f-d56326ae460b" } }
6
+ let(:receipt_body) { { "status" => 1, "request" => "647d2300-702c-4b38-8b2f-d56326ae460b", "receipt" => 'abcdefg' } }
7
+ let(:error_body) { { "user" => "invalid", "errors" => ["user identifier is invalid"], "status" => 0, "request" => "5042853c-402d-4a18-abcb-168734a801de" } }
8
+ let(:headers) do
9
+ {
10
+ "X-Limit-App-Limit": 7500,
11
+ "X-Limit-App-Remaining": 7496,
12
+ "X-Limit-App-Reset": 1_393_653_600
13
+ }
14
+ end
15
+ let(:excon_response) { Excon::Response.new(body: Oj.dump(body), status: 200, headers: headers) }
16
+ let(:response) { described_class.create original: excon_response }
17
+
18
+ it { is_expected.to be_a_kind_of Creatable }
19
+
20
+ it { expect(described_class).to be_a_kind_of(Class) }
21
+
22
+ describe "Attributes" do
23
+ it { is_expected.to have_attributes(errors: []) }
24
+ it { is_expected.to have_attributes(limit: nil) }
25
+ it { is_expected.to have_attributes(original: nil) }
26
+ it { is_expected.to have_attributes(receipt: nil) }
27
+ it { is_expected.to have_attributes(remaining: nil) }
28
+ it { is_expected.to have_attributes(request: nil) }
29
+ it { is_expected.to have_attributes(reset: nil) }
30
+ it { is_expected.to have_attributes(status: a_kind_of(Numeric)) }
31
+ end
32
+
33
+ describe "Instance Signatures" do
34
+ it { is_expected.to respond_to(:process).with(0).argument }
35
+ it { is_expected.to respond_to(:process_body).with(0).argument }
36
+ it { is_expected.to respond_to(:process_headers).with(0).argument }
37
+ end
38
+
39
+ describe '::process' do
40
+ shared_examples 'process_verb' do |verb|
41
+ it "is expected to call process_#{verb}" do
42
+ allow(response).to receive("process_#{verb}".to_sym)
43
+ response.process
44
+ expect(response).to have_received("process_#{verb}".to_sym)
45
+ end
46
+ end
47
+
48
+ include_examples 'process_verb', 'body'
49
+ include_examples 'process_verb', 'headers'
50
+ end
51
+
52
+ describe '::process_body' do
53
+ context "when a receipt is provided" do
54
+ let(:body) { receipt_body }
55
+
56
+ it "is expected to set receipt" do
57
+ expect { response.process_body }.to change(response, :receipt).to body["receipt"]
58
+ end
59
+ end
60
+
61
+ context "when a errors is provided" do
62
+ let(:body) { error_body }
63
+
64
+ it "is expected to set errors" do
65
+ expect { response.process_body }.to change(response, :errors).to body["errors"]
66
+ end
67
+ end
68
+
69
+ it "is expected to call Oj.load" do
70
+ allow(Oj).to receive(:load).and_call_original
71
+ response.process_body
72
+ expect(Oj).to have_received(:load)
73
+ end
74
+
75
+ it "is expected to set status" do
76
+ expect { response.process_body }.to change(response, :status).to body["status"]
77
+ end
78
+
79
+ it "is expected to set request" do
80
+ expect { response.process_body }.to change(response, :request).to body["request"]
81
+ end
82
+ end
83
+
84
+ describe '::process_headers' do
85
+ it "is expected to set limit to X-Limit-App-Limit" do
86
+ expect { response.process_headers }.to change(response, :limit).to headers[:'X-Limit-App-Limit']
87
+ end
88
+
89
+ it "is expected to set remaing to X-Limit-App-Remaining" do
90
+ expect { response.process_headers }.to change(response, :remaining).to headers[:'X-Limit-App-Remaining']
91
+ end
92
+
93
+ it "is expected to set reset to X-Limit-App-Reset" do
94
+ expect { response.process_headers }.to change(response, :reset).to headers[:'X-Limit-App-Reset']
95
+ end
96
+ end
97
+ end
98
+ end
@@ -1,119 +1,4 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Pushover" do
4
- before :all do
5
- Bini.cache_dir = "tmp/cache_dir"
6
- Bini.data_dir = "tmp/data_dir"
7
- Bini.config_dir = "tmp/config_dir"
8
- end
9
- before :each do
10
- App.current_app = nil
11
- User.current_user = nil
12
- Pushover.clear
13
- end
14
-
15
- describe "#clear" do
16
- it "will erase all the attributes in Pushover" do
17
- Pushover.send("#{keys.first}=", "something")
18
- Pushover.clear
19
- parameters.each {|k,v| v.should be_nil}
20
- end
21
- end
22
-
23
- describe "#parameters?" do
24
- it 'will return true only if every key is set to something.' do
25
- keys.each do |k|
26
- if k == :timestamp
27
- Pushover.send("timestamp=", '1970-01-01 00:00:01 UTC')
28
- else
29
- Pushover.send("#{k}=", 'ladeda')
30
- end
31
- end
32
- parameters?.should eq true
33
- end
34
- it 'will return false otherwise.' do
35
- Pushover.send("#{keys.first}=", "something")
36
- parameters?.should eq false
37
- end
38
- end
39
-
40
- describe "#configure" do
41
- Pushover.keys.each do |key|
42
- it "#{key} can be configured via .configure" do
43
- r = "acdfef"
44
- Pushover.configure do |c|
45
- c.instance_variable_set "@#{key}", r
46
- end
47
- Pushover.send(key).should eq r
48
- end
49
- end
50
- end
51
-
52
- describe "#notification" do
53
- it "can send a notification" do
54
- setup_webmocks
55
- Pushover.notification message:'a message', token:'good_token', user:'good_user'
56
- WebMock.should have_requested(:post, /.*api.pushover.net.*/).with do |req|
57
- puts req.body hash_including(priority:'ajkasdfj')
58
- end
59
- end
60
-
61
- it "can send a notification with preconfigured user and token" do
62
- setup_webmocks
63
- Pushover.configure do |c|
64
- c.user = 'good_user'
65
- c.token = 'good_token'
66
- end
67
- Pushover.notification message:'a message'
68
- WebMock.should have_requested(:post, /.*api.pushover.net.*/).with do |req|
69
- puts req.body hash_including(priority:'ajkasdfj')
70
- end
71
- end
72
- end
73
-
74
- describe "extra behavior" do
75
- describe "Priority" do
76
- it "can be set by text" do
77
- setup_webmocks
78
- Pushover.notification message:'a message', token:'good_token', user:'good_user', priority:'low'
79
- WebMock.should have_requested(:post, /.*api.pushover.net.*/).with { |req| req.body.include? 'priority=-1'}
80
- setup_webmocks
81
- Pushover.notification message:'a message', token:'good_token', user:'good_user', priority:'high'
82
- WebMock.should have_requested(:post, /.*api.pushover.net.*/).with { |req| req.body.include? 'priority=1'}
83
- end
84
- it "falls back to normal" do
85
- setup_webmocks
86
- Pushover.notification message:'a message', token:'good_token', user:'good_user', priority:'kwkru'
87
- WebMock.should have_requested(:post, /api.pushover.net/).with { |req| req.body.include? 'priority=0' }
88
- end
89
- end
90
-
91
- describe "Time" do
92
- it "can be set by epoch" do
93
- setup_webmocks
94
- Pushover.notification message:'a message', token:'good_token', user:'good_user', timestamp:1000
95
- Pushover.notification message:'a message', token:'good_token', user:'good_user', timestamp:'1000'
96
- WebMock.should have_requested(:post, /api.pushover.net/).with { |req| req.body.include? 'timestamp=1000' }.twice
97
- end
98
-
99
- it "can be set by a text string" do
100
- setup_webmocks
101
- Pushover.notification message:'a message', token:'good_token', user:'good_user', timestamp:'1970-01-01 00:00:01 UTC'
102
- WebMock.should have_requested(:post, /api.pushover.net/).with { |req| req.body.include? 'timestamp=1' }
103
- end
104
- end
105
-
106
- describe "Sounds" do
107
- it "will cache the sounds locally for at least a day" do
108
- setup_webmocks
109
- cache_file = "#{Bini.cache_dir}/sounds.json"
110
- FileUtils.rm(cache_file) if File.exist?(cache_file)
111
- Pushover.sounds.keys.should include("pushover")
112
- stat = File.stat(cache_file)
113
- Pushover.sounds.keys.should include("none")
114
- stat.mtime.to_i.should eq File.stat(cache_file).mtime.to_i
115
- end
116
- end
117
-
118
- end
3
+ describe Pushover do
119
4
  end