patient_zero 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +2 -0
- data/lib/patient_zero/analytics/base.rb +35 -0
- data/lib/patient_zero/analytics/facebook.rb +25 -0
- data/lib/patient_zero/analytics/instagram.rb +13 -0
- data/lib/patient_zero/analytics/twitter.rb +13 -0
- data/lib/patient_zero/analytics.rb +16 -0
- data/lib/patient_zero/authorization.rb +8 -0
- data/lib/patient_zero/client.rb +35 -0
- data/lib/patient_zero/configurable.rb +21 -0
- data/lib/patient_zero/errors.rb +4 -0
- data/lib/patient_zero/message/base.rb +11 -0
- data/lib/patient_zero/message/facebook.rb +29 -0
- data/lib/patient_zero/message/instagram.rb +29 -0
- data/lib/patient_zero/message/twitter.rb +21 -0
- data/lib/patient_zero/message.rb +16 -0
- data/lib/patient_zero/organization.rb +27 -0
- data/lib/patient_zero/source.rb +36 -0
- data/lib/patient_zero/version.rb +1 -1
- data/lib/patient_zero.rb +19 -2
- data/patient_zero.gemspec +13 -8
- data/spec/patient_zero/analytics/base_spec.rb +54 -0
- data/spec/patient_zero/analytics/facebook_spec.rb +40 -0
- data/spec/patient_zero/analytics/instagram_spec.rb +35 -0
- data/spec/patient_zero/analytics/twitter_spec.rb +34 -0
- data/spec/patient_zero/analytics_spec.rb +29 -0
- data/spec/patient_zero/authorization_spec.rb +26 -0
- data/spec/patient_zero/client_spec.rb +31 -0
- data/spec/patient_zero/message/facebook_spec.rb +52 -0
- data/spec/patient_zero/message/instagram_spec.rb +53 -0
- data/spec/patient_zero/message/twitter_spec.rb +40 -0
- data/spec/patient_zero/message_spec.rb +29 -0
- data/spec/patient_zero/organization_spec.rb +67 -0
- data/spec/patient_zero/source_spec.rb +83 -0
- data/spec/spec_helper.rb +14 -0
- metadata +106 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44dbcc4b6d6cf236eb77f548a0b764e7816b7962
|
4
|
+
data.tar.gz: 33e6b2e9170ebe01eb61ddb7bb3ddd61661e4e16
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7129206bd4afe74fdb1708a02d6fcfc8040845cd04fec49b67916f8aa928193b27976905a24f0db7dd784d9195c2bc9099c8ce278ffd2cc3897c332bd88d76fe
|
7
|
+
data.tar.gz: 10c63b464b5426341cd6393be167ff564ff5dc99a5356fe1493fcd6cc435e52b3fbbe8587ff12761b91437a8b0c7a881c33cd37cb477c51e4809c9d44336f3f2
|
data/.rspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module PatientZero
|
2
|
+
module Analytics
|
3
|
+
class Base < Client
|
4
|
+
attr_accessor :token, :source_id, :start_date, :end_date
|
5
|
+
|
6
|
+
def initialize token:, source_id:, start_date: nil, end_date: nil
|
7
|
+
@token = token
|
8
|
+
@source_id = source_id
|
9
|
+
@end_date = end_date || Date.today.to_s
|
10
|
+
@start_date = start_date || Date.today.prev_day(7).to_s
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
analytical_data['name']
|
15
|
+
end
|
16
|
+
|
17
|
+
def platform
|
18
|
+
analytical_data['platform']
|
19
|
+
end
|
20
|
+
|
21
|
+
def messages
|
22
|
+
analytical_data['messages'].map { |message| Message.for_platform message['platform'], message }
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def analytical_data
|
28
|
+
@analytical_data ||= get('/mobile/api/v1/analytics', client_token: token,
|
29
|
+
social_object_uid: source_id,
|
30
|
+
start_date: start_date,
|
31
|
+
end_date: end_date)['stats'].first
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module PatientZero
|
2
|
+
module Analytics
|
3
|
+
class Facebook < Base
|
4
|
+
def engagements
|
5
|
+
@engagements ||= messages.reduce(0) { |sum, message| sum + message.engagements }
|
6
|
+
end
|
7
|
+
|
8
|
+
def impressions
|
9
|
+
page_impressions + message_impressions
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def message_impressions
|
15
|
+
messages.reduce(0) { |sum, message| sum + message.impressions }
|
16
|
+
end
|
17
|
+
|
18
|
+
def page_impressions
|
19
|
+
analytical_data['page_impressions'].find do |impressions_hash|
|
20
|
+
impressions_hash['key'] == 'Total'
|
21
|
+
end['values'].each_value.reduce(:+)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module PatientZero
|
2
|
+
module Analytics
|
3
|
+
class Instagram < Base
|
4
|
+
def engagements
|
5
|
+
@engagements ||= messages.reduce(0) { |sum, message| sum + message.engagements }
|
6
|
+
end
|
7
|
+
|
8
|
+
def impressions
|
9
|
+
@impressions ||= messages.reduce(0) { |sum, message| sum + message.impressions }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'patient_zero/analytics/base'
|
2
|
+
require 'patient_zero/analytics/twitter'
|
3
|
+
require 'patient_zero/analytics/facebook'
|
4
|
+
require 'patient_zero/analytics/instagram'
|
5
|
+
|
6
|
+
module PatientZero
|
7
|
+
module Analytics
|
8
|
+
SOURCE_TYPES = {'twitter' => Twitter,
|
9
|
+
'facebook' => Facebook,
|
10
|
+
'instagram' => Instagram}
|
11
|
+
|
12
|
+
def self.for_platform platform, params={}
|
13
|
+
SOURCE_TYPES[platform].new params
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PatientZero
|
2
|
+
class Client
|
3
|
+
def self.connection
|
4
|
+
@@connection ||= Faraday.new(PatientZero.url) do |faraday|
|
5
|
+
faraday.request :url_encoded
|
6
|
+
faraday.response :logger
|
7
|
+
faraday.adapter Faraday.default_adapter
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.parse request
|
12
|
+
response = JSON.parse request.body
|
13
|
+
raise Error, response['error'] unless response['error'].nil?
|
14
|
+
response
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.get *args
|
18
|
+
parse connection.get *args
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.post *args
|
22
|
+
parse connection.post *args
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def get *args
|
28
|
+
self.class.get *args
|
29
|
+
end
|
30
|
+
|
31
|
+
def post *args
|
32
|
+
self.class.post *args
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module PatientZero
|
2
|
+
module Configurable
|
3
|
+
attr_accessor :url, :api_key, :email, :password
|
4
|
+
|
5
|
+
def self.extended(base)
|
6
|
+
base.reset
|
7
|
+
end
|
8
|
+
|
9
|
+
def configure
|
10
|
+
yield self
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def reset
|
15
|
+
self.url = 'https://app.viralheat.com'
|
16
|
+
self.api_key = ENV['VIRAL_HEAT_API_KEY']
|
17
|
+
self.email = ENV['VIRAL_HEAT_EMAIL']
|
18
|
+
self.password = ENV['VIRAL_HEAT_PASSWORD']
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PatientZero
|
2
|
+
module Message
|
3
|
+
class Facebook < Base
|
4
|
+
def engagements
|
5
|
+
@engagements ||= likes + comments + shares + clicks
|
6
|
+
end
|
7
|
+
|
8
|
+
def impressions
|
9
|
+
data.fetch 'impressions'
|
10
|
+
end
|
11
|
+
|
12
|
+
def likes
|
13
|
+
data.fetch 'likes'
|
14
|
+
end
|
15
|
+
|
16
|
+
def comments
|
17
|
+
data.fetch 'comments'
|
18
|
+
end
|
19
|
+
|
20
|
+
def shares
|
21
|
+
data.fetch 'shares'
|
22
|
+
end
|
23
|
+
|
24
|
+
def clicks
|
25
|
+
data.fetch 'clicks'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PatientZero
|
2
|
+
module Message
|
3
|
+
class Instagram < Base
|
4
|
+
def engagements
|
5
|
+
@engagements ||= likes + comments + clicks + shares
|
6
|
+
end
|
7
|
+
|
8
|
+
def impressions
|
9
|
+
data.fetch 'impressions'
|
10
|
+
end
|
11
|
+
|
12
|
+
def likes
|
13
|
+
data.fetch 'likes'
|
14
|
+
end
|
15
|
+
|
16
|
+
def comments
|
17
|
+
data.fetch 'comments'
|
18
|
+
end
|
19
|
+
|
20
|
+
def clicks
|
21
|
+
data.fetch 'clicks'
|
22
|
+
end
|
23
|
+
|
24
|
+
def shares
|
25
|
+
data.fetch('shares').to_i
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module PatientZero
|
2
|
+
module Message
|
3
|
+
class Twitter < Base
|
4
|
+
def engagements
|
5
|
+
@engagements ||= retweets + favorites + clicks
|
6
|
+
end
|
7
|
+
|
8
|
+
def retweets
|
9
|
+
data.fetch 'retweets'
|
10
|
+
end
|
11
|
+
|
12
|
+
def favorites
|
13
|
+
data.fetch 'favorites'
|
14
|
+
end
|
15
|
+
|
16
|
+
def clicks
|
17
|
+
data.fetch 'clicks'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'patient_zero/message/base'
|
2
|
+
require 'patient_zero/message/facebook'
|
3
|
+
require 'patient_zero/message/twitter'
|
4
|
+
require 'patient_zero/message/instagram'
|
5
|
+
|
6
|
+
module PatientZero
|
7
|
+
module Message
|
8
|
+
SOURCE_TYPES = {'TW' => Twitter,
|
9
|
+
'FB' => Facebook,
|
10
|
+
'IG' => Instagram}
|
11
|
+
|
12
|
+
def self.for_platform platform, params={}
|
13
|
+
SOURCE_TYPES[platform].new params
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module PatientZero
|
2
|
+
class Organization < Client
|
3
|
+
attr_accessor :id, :name, :avatar
|
4
|
+
|
5
|
+
def initialize attributes
|
6
|
+
@id = attributes.fetch 'id'
|
7
|
+
@name = attributes.fetch 'name'
|
8
|
+
@avatar = attributes.fetch 'avatar'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.all
|
12
|
+
response = get '/mobile/api/v1/organizations', client_token: Authorization.token
|
13
|
+
response['organizations'].map do |organization_attributes|
|
14
|
+
new organization_attributes
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def sources
|
19
|
+
Source.all token
|
20
|
+
end
|
21
|
+
|
22
|
+
def token
|
23
|
+
response = get "/mobile/api/v1/organizations/#{id}/switch", client_token: Authorization.token
|
24
|
+
response['user_token']
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PatientZero
|
2
|
+
class Source < Client
|
3
|
+
attr_accessor :id, :name, :platform, :token
|
4
|
+
|
5
|
+
def initialize attributes, token
|
6
|
+
@id = attributes.fetch 'id'
|
7
|
+
@name = attributes.fetch 'name'
|
8
|
+
@invalid = attributes.fetch 'is_invalid'
|
9
|
+
@tracked = attributes.fetch 'is_tracked'
|
10
|
+
@platform = attributes.fetch 'platform'
|
11
|
+
@token = token
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.all token=Authorization.token
|
15
|
+
response = get '/mobile/api/v1/sources/', client_token: token
|
16
|
+
response['sources'].map do |source_attributes|
|
17
|
+
new source_attributes, token
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.find source_id, token=Authorization.token
|
22
|
+
response = get '/mobile/api/v1/sources/show/', id: source_id, client_token: token
|
23
|
+
new response['source'], token
|
24
|
+
rescue Error => e
|
25
|
+
raise NotFoundError, e
|
26
|
+
end
|
27
|
+
|
28
|
+
def profile_id
|
29
|
+
id.split('#').last
|
30
|
+
end
|
31
|
+
|
32
|
+
def analytics start_date: nil, end_date: nil
|
33
|
+
@analytics ||= Analytics.for_platform platform, token: token, source_id: id, start_date: start_date, end_date: end_date
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/patient_zero/version.rb
CHANGED
data/lib/patient_zero.rb
CHANGED
@@ -1,5 +1,22 @@
|
|
1
|
-
require
|
1
|
+
require 'json'
|
2
|
+
require 'faraday'
|
3
|
+
require 'patient_zero/version'
|
4
|
+
require 'patient_zero/errors'
|
5
|
+
require 'patient_zero/client'
|
6
|
+
require 'patient_zero/configurable'
|
7
|
+
require 'patient_zero/authorization'
|
8
|
+
require 'patient_zero/organization'
|
9
|
+
require 'patient_zero/analytics'
|
10
|
+
require 'patient_zero/source'
|
11
|
+
require 'patient_zero/message'
|
2
12
|
|
3
13
|
module PatientZero
|
4
|
-
|
14
|
+
extend PatientZero::Configurable
|
5
15
|
end
|
16
|
+
|
17
|
+
# Configuration Example
|
18
|
+
# PatientZero.configure do |config|
|
19
|
+
# config.api_key = 'somethingsomethingdangerzone'
|
20
|
+
# config.email = 'duchess@cia.gov'
|
21
|
+
# config.password = 'password'
|
22
|
+
# end
|
data/patient_zero.gemspec
CHANGED
@@ -4,20 +4,25 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'patient_zero/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'patient_zero'
|
8
8
|
spec.version = PatientZero::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['Adam Zaninovich','Devin Clark']
|
10
|
+
spec.email = ['adam.zaninovich@gmail.com', 'notdevinclark@gmail.com']
|
11
11
|
spec.summary = %q{A gem to use the Viral Heat API}
|
12
12
|
spec.description = %q{A gem to use the Viral Heat API}
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_development_dependency
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
22
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
23
|
+
spec.add_development_dependency 'rspec'
|
24
|
+
spec.add_development_dependency 'pry'
|
25
|
+
|
26
|
+
spec.add_dependency 'faraday'
|
27
|
+
spec.add_dependency 'json'
|
23
28
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
module Analytics
|
5
|
+
describe Base do
|
6
|
+
let(:source_id) { "12345##{platform}#1234567890" }
|
7
|
+
let(:name) { 'account_name' }
|
8
|
+
let(:platform) { 'account_type' }
|
9
|
+
let(:messages) { [ { 'platform' => 'FB' } ] }
|
10
|
+
let(:token) { 'token-shmoken' }
|
11
|
+
let(:analytical_data) { { 'stats' => [ { 'id' => source_id, 'platform' => platform, 'name' => name, 'messages' => messages } ] } }
|
12
|
+
subject(:analytics_base) { Base.new token: token, source_id: source_id }
|
13
|
+
before { allow(Client).to receive(:get).with('/mobile/api/v1/analytics', anything).and_return analytical_data }
|
14
|
+
|
15
|
+
describe '#name' do
|
16
|
+
it 'calls the analytics API endpoint' do
|
17
|
+
expect(Client).to receive(:get).with('/mobile/api/v1/analytics', anything)
|
18
|
+
analytics_base.name
|
19
|
+
end
|
20
|
+
it 'pulls the name from the analytical_data hash' do
|
21
|
+
expect(analytics_base.name).to be name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#platform' do
|
26
|
+
it 'calls the analytics API endpoint' do
|
27
|
+
expect(Client).to receive(:get).with('/mobile/api/v1/analytics', anything)
|
28
|
+
analytics_base.name
|
29
|
+
end
|
30
|
+
it 'pulls the platform from the analytical_data hash' do
|
31
|
+
expect(analytics_base.platform).to be platform
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#messages' do
|
36
|
+
it 'calls the analytics API endpoint' do
|
37
|
+
expect(Client).to receive(:get).with('/mobile/api/v1/analytics', anything)
|
38
|
+
analytics_base.name
|
39
|
+
end
|
40
|
+
context 'when there are messages' do
|
41
|
+
it 'returns an array of messages' do
|
42
|
+
expect(analytics_base.messages.first).to be_a Message::Facebook
|
43
|
+
end
|
44
|
+
end
|
45
|
+
context 'when there are no messages' do
|
46
|
+
let(:messages) { [] }
|
47
|
+
it 'returns an empty array' do
|
48
|
+
expect(analytics_base.messages).to be_empty
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
module Analytics
|
5
|
+
describe Facebook do
|
6
|
+
let(:source_id) { "12345##{platform}#1234567890" }
|
7
|
+
let(:platform) { 'facebook' }
|
8
|
+
let(:message) do
|
9
|
+
{ 'platform' => 'FB',
|
10
|
+
'likes' => 93,
|
11
|
+
'comments' => 7,
|
12
|
+
'impressions' => 345,
|
13
|
+
'shares' => 22,
|
14
|
+
'clicks' => 38 }
|
15
|
+
end
|
16
|
+
let(:messages) { [ message ] }
|
17
|
+
let(:page_impressions) do
|
18
|
+
[ { 'key'=>'Total',
|
19
|
+
'values'=>
|
20
|
+
{ '2010-10-10'=> 99 } } ]
|
21
|
+
end
|
22
|
+
let(:token) { 'token-shmoken' }
|
23
|
+
let(:analytical_data) { { 'messages' => messages, 'page_impressions' => page_impressions } }
|
24
|
+
let(:facebook_analytics) { Facebook.new token: token, source_id: source_id }
|
25
|
+
before{ allow(facebook_analytics).to receive(:analytical_data).and_return analytical_data }
|
26
|
+
|
27
|
+
describe '#impressions' do
|
28
|
+
it 'returns the total for message and page impressions' do
|
29
|
+
expect(facebook_analytics.impressions).to eq 444
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#engagements' do
|
34
|
+
it 'returns the sum of likes, comments, shares, and clicks' do
|
35
|
+
expect(facebook_analytics.engagements).to eq 160
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
module Analytics
|
5
|
+
describe Instagram do
|
6
|
+
let(:source_id) { "12345##{platform}#1234567890" }
|
7
|
+
let(:platform) { 'instagram' }
|
8
|
+
let(:message) do
|
9
|
+
{ 'platform' => 'IG',
|
10
|
+
'impressions' => 10101,
|
11
|
+
'shares'=>'3',
|
12
|
+
'likes'=>52,
|
13
|
+
'comments'=>3,
|
14
|
+
'clicks'=>14 }
|
15
|
+
end
|
16
|
+
let(:messages) { [ message ] }
|
17
|
+
let(:token) { 'token-shmoken' }
|
18
|
+
let(:analytical_data) { { 'messages' => messages } }
|
19
|
+
let(:instagram_analytics) { Instagram.new token: token, source_id: source_id }
|
20
|
+
before{ allow(instagram_analytics).to receive(:analytical_data).and_return analytical_data }
|
21
|
+
|
22
|
+
describe '#impressions' do
|
23
|
+
it 'returns the sum of impressions for all messages' do
|
24
|
+
expect(instagram_analytics.impressions).to eq 10101
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#engagements' do
|
29
|
+
it 'returns the sum of retweets, favorites, and clicks for all messages' do
|
30
|
+
expect(instagram_analytics.engagements).to eq 72
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
module Analytics
|
5
|
+
describe Twitter do
|
6
|
+
let(:source_id) { "12345##{platform}#1234567890" }
|
7
|
+
let(:platform) { 'twitter' }
|
8
|
+
let(:message) do
|
9
|
+
{ 'platform' => 'TW',
|
10
|
+
'retweets' => 6,
|
11
|
+
'impressions' => 13,
|
12
|
+
'favorites' => 2,
|
13
|
+
'clicks' => 12 }
|
14
|
+
end
|
15
|
+
let(:messages) { [ message ] }
|
16
|
+
let(:token) { 'token-shmoken' }
|
17
|
+
let(:analytical_data) { { 'messages' => messages, 'total_impressions' => 13 } }
|
18
|
+
let(:twitter_analytics) { Twitter.new token: token, source_id: source_id }
|
19
|
+
before{ allow(twitter_analytics).to receive(:analytical_data).and_return analytical_data }
|
20
|
+
|
21
|
+
describe '#impressions' do
|
22
|
+
it 'returns the total_impressions value from the analytical_data hash' do
|
23
|
+
expect(twitter_analytics.impressions).to eq 13
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#engagements' do
|
28
|
+
it 'returns the sum of retweets, favorites, and clicks for all messages' do
|
29
|
+
expect(twitter_analytics.engagements).to eq 20
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
describe Analytics do
|
5
|
+
describe '.for_platform' do
|
6
|
+
let(:data_hash) { { token: "", source_id: "" } }
|
7
|
+
context 'when platform is Facebook' do
|
8
|
+
let(:platform) { 'facebook' }
|
9
|
+
it 'news up a Analytics::Facebook object' do
|
10
|
+
expect(Analytics.for_platform(platform, data_hash)).to be_a Analytics::Facebook
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when platform is Twitter' do
|
15
|
+
let(:platform) { 'twitter' }
|
16
|
+
it 'news up a Analytics::Twitter object' do
|
17
|
+
expect(Analytics.for_platform(platform, data_hash)).to be_a Analytics::Twitter
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when platform is Instagram' do
|
22
|
+
let(:platform) { 'instagram' }
|
23
|
+
it 'news up a Analytics::Instagram object' do
|
24
|
+
expect(Analytics.for_platform(platform, data_hash)).to be_a Analytics::Instagram
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
describe Authorization do
|
5
|
+
describe '.token' do
|
6
|
+
let(:token) { 'token-shmoken' }
|
7
|
+
let(:authorization_response) { response_with_body user_token: token }
|
8
|
+
before{ allow(Client.connection).to receive(:post).with('/mobile/api/v1/user/login', anything).and_return authorization_response }
|
9
|
+
it 'calls the login api endpoint' do
|
10
|
+
expect(Client.connection).to receive(:post).with('/mobile/api/v1/user/login', anything)
|
11
|
+
Authorization.token
|
12
|
+
end
|
13
|
+
context 'when email and password are correct' do
|
14
|
+
it 'returns a user_token' do
|
15
|
+
expect(Authorization.token).to eq token
|
16
|
+
end
|
17
|
+
end
|
18
|
+
context 'when email and password are incorrect' do
|
19
|
+
let(:authorization_response) { response_with_body error: 'Invalid login/password' }
|
20
|
+
it 'raises a PatientZero::Error error' do
|
21
|
+
expect{ Authorization.token }.to raise_error PatientZero::Error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
describe Client do
|
5
|
+
let(:token) { 'token-shmoken' }
|
6
|
+
let(:body) { "{}" }
|
7
|
+
let(:response) { double body: body }
|
8
|
+
|
9
|
+
describe '.connection' do
|
10
|
+
it 'news up a connection to the Viral Heat API' do
|
11
|
+
expect(Client.connection).to be_a Faraday::Connection
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.parse' do
|
16
|
+
subject(:parse) { Client.parse response }
|
17
|
+
context 'when the response contains an error key with nil' do
|
18
|
+
let(:body) { "{\"status\":200,\"error\":null,\"user_token\":\"#{token}\"}" }
|
19
|
+
it 'returns a hash of data' do
|
20
|
+
expect(parse).to be_a Hash
|
21
|
+
end
|
22
|
+
end
|
23
|
+
context 'when the response contains an error key that is not nil' do
|
24
|
+
let(:body) { "{\"status\":403,\"error\":\"Invalid login/password\",\"user_token\":null}" }
|
25
|
+
it 'raises an error' do
|
26
|
+
expect { parse }.to raise_error Error
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
module Message
|
5
|
+
describe Facebook do
|
6
|
+
let(:data) do
|
7
|
+
{ 'platform' => 'FB',
|
8
|
+
'likes' => 93,
|
9
|
+
'comments' => 7,
|
10
|
+
'impressions' => 345,
|
11
|
+
'shares' => 22,
|
12
|
+
'clicks' => 38 }
|
13
|
+
end
|
14
|
+
subject(:facebook_message) { Facebook.new data }
|
15
|
+
describe '#engagements' do
|
16
|
+
it 'returns the sum of likes, comments, shares, and clicks' do
|
17
|
+
expect(facebook_message.engagements).to eq 160
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#impressions' do
|
22
|
+
it 'returns the impression variable from the data hash' do
|
23
|
+
expect(facebook_message.impressions).to eq 345
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#likes' do
|
28
|
+
it 'returns the likes variable from the data hash' do
|
29
|
+
expect(facebook_message.likes).to eq 93
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#comments' do
|
34
|
+
it 'returns the comments variable from the data hash' do
|
35
|
+
expect(facebook_message.comments).to eq 7
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#shares' do
|
40
|
+
it 'returns the shares variable from the data hash' do
|
41
|
+
expect(facebook_message.shares).to eq 22
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#clicks' do
|
46
|
+
it 'returns the clicks variable from the data hash' do
|
47
|
+
expect(facebook_message.clicks).to eq 38
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
module Message
|
5
|
+
describe Instagram do
|
6
|
+
let(:data) do
|
7
|
+
{ 'platform' => 'IG',
|
8
|
+
'likes' => 93,
|
9
|
+
'comments' => 7,
|
10
|
+
'impressions' => 345,
|
11
|
+
'shares' => '22',
|
12
|
+
'clicks' => 38 }
|
13
|
+
end
|
14
|
+
subject(:instagram_message) { Instagram.new data }
|
15
|
+
|
16
|
+
describe '#engagements' do
|
17
|
+
it 'returns the sum of likes, comments, shares, and clicks' do
|
18
|
+
expect(instagram_message.engagements).to eq 160
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#impressions' do
|
23
|
+
it 'returns the impression variable from the data hash' do
|
24
|
+
expect(instagram_message.impressions).to eq 345
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#likes' do
|
29
|
+
it 'returns the likes variable from the data hash' do
|
30
|
+
expect(instagram_message.likes).to eq 93
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#comments' do
|
35
|
+
it 'returns the comments variable from the data hash' do
|
36
|
+
expect(instagram_message.comments).to eq 7
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#shares' do
|
41
|
+
it 'returns the shares variable from the data hash' do
|
42
|
+
expect(instagram_message.shares).to eq 22
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#clicks' do
|
47
|
+
it 'returns the clicks variable from the data hash' do
|
48
|
+
expect(instagram_message.clicks).to eq 38
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
module Message
|
5
|
+
describe Twitter do
|
6
|
+
let(:data) do
|
7
|
+
{ 'platform' => 'TW',
|
8
|
+
'favorites' => 7,
|
9
|
+
'impressions' => 345,
|
10
|
+
'retweets' => 22,
|
11
|
+
'clicks' => 38 }
|
12
|
+
end
|
13
|
+
subject(:twitter_message) { Twitter.new data }
|
14
|
+
|
15
|
+
describe '#engagements' do
|
16
|
+
it 'returns the sum of retweets, favorites, and clicks' do
|
17
|
+
expect(twitter_message.engagements).to eq 67
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#retweets' do
|
22
|
+
it 'returns the retweets variable from the data hash' do
|
23
|
+
expect(twitter_message.retweets).to eq 22
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#favorites' do
|
28
|
+
it 'returns the favorites variable from the data hash' do
|
29
|
+
expect(twitter_message.favorites).to eq 7
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#clicks' do
|
34
|
+
it 'returns the clicks variable from the data hash' do
|
35
|
+
expect(twitter_message.clicks).to eq 38
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
describe Message do
|
5
|
+
describe '.for_platform' do
|
6
|
+
let(:data_hash) { { } }
|
7
|
+
context 'when platform is Facebook' do
|
8
|
+
let(:platform) { 'FB' }
|
9
|
+
it 'news up a Message::Facebook object' do
|
10
|
+
expect(Message.for_platform(platform, data_hash)).to be_a Message::Facebook
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when platform is Twitter' do
|
15
|
+
let(:platform) { 'TW' }
|
16
|
+
it 'news up a Message::Twitter object' do
|
17
|
+
expect(Message.for_platform(platform, data_hash)).to be_a Message::Twitter
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when platform is Instagram' do
|
22
|
+
let(:platform) { 'IG' }
|
23
|
+
it 'news up a Message::Instagram object' do
|
24
|
+
expect(Message.for_platform(platform, data_hash)).to be_a Message::Instagram
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
describe Organization do
|
5
|
+
let(:id) { 12345 }
|
6
|
+
let(:token) { 'token-shmoken' }
|
7
|
+
let(:organization) { Organization.new organization_response_data }
|
8
|
+
let(:organizations_response_data) { [organization_response_data] }
|
9
|
+
let(:organization_response_data) do
|
10
|
+
{ "id"=>id,
|
11
|
+
"name"=>"Organization One",
|
12
|
+
"avatar"=>
|
13
|
+
{ "thumbnail"=>"https://s3.amazonaws.com/viralheat/avatars/organizations/12345/thumb/fake_img_1.png",
|
14
|
+
"medium"=>"https://s3.amazonaws.com/viralheat/avatars/organizations/12345/medium/fake_img_1.png",
|
15
|
+
"large"=>"https://s3.amazonaws.com/viralheat/avatars/organizations/12345/large/fake_img_1.png" } }
|
16
|
+
end
|
17
|
+
|
18
|
+
before { allow(Authorization).to receive(:token).and_return token }
|
19
|
+
|
20
|
+
describe '.all' do
|
21
|
+
let(:organizations) { [organization] }
|
22
|
+
let(:organizations_response) { response_with_body organizations: organizations_response_data }
|
23
|
+
before { allow(Client.connection).to receive(:get).with('/mobile/api/v1/organizations', anything) { organizations_response } }
|
24
|
+
|
25
|
+
it 'calls the organizations api endpoint' do
|
26
|
+
expect(Client.connection).to receive(:get).with('/mobile/api/v1/organizations', anything)
|
27
|
+
Organization.all
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'if the user has organizations' do
|
31
|
+
it 'returns an array of all organizations available' do
|
32
|
+
expect(Organization.all.map(&:id)).to eq organizations.map(&:id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'if the user has no organizations' do
|
37
|
+
let(:organizations_response_data) { [] }
|
38
|
+
it 'returns an empty array' do
|
39
|
+
expect(Organization.all).to be_empty
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#sources' do
|
45
|
+
it 'calls Source.all and passes its own organization user_token' do
|
46
|
+
allow(organization).to receive(:token).and_return token
|
47
|
+
expect(Source).to receive(:all).with(token)
|
48
|
+
organization.sources
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#token' do
|
53
|
+
let(:organization_specific_token) { 'organization-token' }
|
54
|
+
let(:switch_response) { response_with_body user_token: organization_specific_token }
|
55
|
+
before { allow(Client.connection).to receive(:get).with("/mobile/api/v1/organizations/#{id}/switch", anything).and_return switch_response }
|
56
|
+
|
57
|
+
it 'calls the organization switch api endpoint' do
|
58
|
+
expect(Client.connection).to receive(:get).with("/mobile/api/v1/organizations/#{id}/switch", anything)
|
59
|
+
organization.token
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns the organization specific user_token' do
|
63
|
+
expect(organization.token).to eq organization_specific_token
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module PatientZero
|
4
|
+
describe Source do
|
5
|
+
let(:id) { '12345#instagram_account#1234567890' }
|
6
|
+
let(:token) { 'token-shmoken' }
|
7
|
+
let(:sources_response_data) { [source_response_data] }
|
8
|
+
let(:source_response_data) do
|
9
|
+
{'id'=> id,
|
10
|
+
'name' => 'account_name',
|
11
|
+
'is_invalid' => false,
|
12
|
+
'is_tracked' => true,
|
13
|
+
'platform' => 'instagram',
|
14
|
+
'delete_id' => id }
|
15
|
+
end
|
16
|
+
let(:source) { Source.new source_response_data, token }
|
17
|
+
|
18
|
+
describe '.all' do
|
19
|
+
before do
|
20
|
+
allow(Authorization).to receive(:token).and_return token
|
21
|
+
allow(Client.connection).to receive(:get).with('/mobile/api/v1/sources/', anything).and_return response_with_body sources: sources_response_data
|
22
|
+
end
|
23
|
+
it 'calls the sources index api' do
|
24
|
+
expect(Client.connection).to receive(:get).with('/mobile/api/v1/sources/', anything)
|
25
|
+
Source.all
|
26
|
+
end
|
27
|
+
it 'calls Authorization.token if no token is passed in' do
|
28
|
+
expect(Authorization).to receive(:token)
|
29
|
+
Source.all
|
30
|
+
end
|
31
|
+
context 'when the associated organization token has sources' do
|
32
|
+
it 'returns an array of sources' do
|
33
|
+
expect(Source.all.first.id).to eq source.id
|
34
|
+
end
|
35
|
+
end
|
36
|
+
context 'when the associated organization token has no sources' do
|
37
|
+
it 'returns an empty array' do
|
38
|
+
allow(Client.connection).to receive(:get).with('/mobile/api/v1/sources/', anything).and_return response_with_body sources: []
|
39
|
+
expect(Source.all).to be_empty
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.find' do
|
45
|
+
before do
|
46
|
+
allow(Authorization).to receive(:token).and_return token
|
47
|
+
allow(Client.connection).to receive(:get).with('/mobile/api/v1/sources/show/', anything).and_return response_with_body source: source_response_data
|
48
|
+
end
|
49
|
+
it 'calls the sources show api' do
|
50
|
+
expect(Client.connection).to receive(:get).with('/mobile/api/v1/sources/show/', anything)
|
51
|
+
Source.find id
|
52
|
+
end
|
53
|
+
it 'calls Authorization.token if no token is passed in' do
|
54
|
+
expect(Authorization).to receive(:token)
|
55
|
+
Source.find id
|
56
|
+
end
|
57
|
+
context 'when the source exists' do
|
58
|
+
it 'returns a source' do
|
59
|
+
expect(Source.find(id).id).to eq source.id
|
60
|
+
end
|
61
|
+
end
|
62
|
+
context 'when no source exists' do
|
63
|
+
it 'throws an PatientZero::Error' do
|
64
|
+
allow(Client).to receive(:get).and_raise Error, 'The source could not be found. Please check your inputs.'
|
65
|
+
expect{ Source.find id }.to raise_error PatientZero::NotFoundError
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#profile_id' do
|
71
|
+
it 'returns the number at the end of the id' do
|
72
|
+
expect(source.profile_id).to eq '1234567890'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe '#analytics' do
|
77
|
+
it 'calls Analytics.for_platorm to create an analytics object' do
|
78
|
+
expect(Analytics).to receive(:for_platform).with(source.platform, { token: source.token, source_id: source.id, start_date: nil, end_date: nil })
|
79
|
+
source.analytics
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: patient_zero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Zaninovich
|
8
|
+
- Devin Clark
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2015-
|
12
|
+
date: 2015-04-16 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
@@ -38,21 +39,109 @@ dependencies:
|
|
38
39
|
- - "~>"
|
39
40
|
- !ruby/object:Gem::Version
|
40
41
|
version: '10.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: pry
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: faraday
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: json
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :runtime
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
41
98
|
description: A gem to use the Viral Heat API
|
42
99
|
email:
|
43
100
|
- adam.zaninovich@gmail.com
|
101
|
+
- notdevinclark@gmail.com
|
44
102
|
executables: []
|
45
103
|
extensions: []
|
46
104
|
extra_rdoc_files: []
|
47
105
|
files:
|
48
106
|
- ".gitignore"
|
107
|
+
- ".rspec"
|
49
108
|
- Gemfile
|
50
109
|
- LICENSE.txt
|
51
110
|
- README.md
|
52
111
|
- Rakefile
|
53
112
|
- lib/patient_zero.rb
|
113
|
+
- lib/patient_zero/analytics.rb
|
114
|
+
- lib/patient_zero/analytics/base.rb
|
115
|
+
- lib/patient_zero/analytics/facebook.rb
|
116
|
+
- lib/patient_zero/analytics/instagram.rb
|
117
|
+
- lib/patient_zero/analytics/twitter.rb
|
118
|
+
- lib/patient_zero/authorization.rb
|
119
|
+
- lib/patient_zero/client.rb
|
120
|
+
- lib/patient_zero/configurable.rb
|
121
|
+
- lib/patient_zero/errors.rb
|
122
|
+
- lib/patient_zero/message.rb
|
123
|
+
- lib/patient_zero/message/base.rb
|
124
|
+
- lib/patient_zero/message/facebook.rb
|
125
|
+
- lib/patient_zero/message/instagram.rb
|
126
|
+
- lib/patient_zero/message/twitter.rb
|
127
|
+
- lib/patient_zero/organization.rb
|
128
|
+
- lib/patient_zero/source.rb
|
54
129
|
- lib/patient_zero/version.rb
|
55
130
|
- patient_zero.gemspec
|
131
|
+
- spec/patient_zero/analytics/base_spec.rb
|
132
|
+
- spec/patient_zero/analytics/facebook_spec.rb
|
133
|
+
- spec/patient_zero/analytics/instagram_spec.rb
|
134
|
+
- spec/patient_zero/analytics/twitter_spec.rb
|
135
|
+
- spec/patient_zero/analytics_spec.rb
|
136
|
+
- spec/patient_zero/authorization_spec.rb
|
137
|
+
- spec/patient_zero/client_spec.rb
|
138
|
+
- spec/patient_zero/message/facebook_spec.rb
|
139
|
+
- spec/patient_zero/message/instagram_spec.rb
|
140
|
+
- spec/patient_zero/message/twitter_spec.rb
|
141
|
+
- spec/patient_zero/message_spec.rb
|
142
|
+
- spec/patient_zero/organization_spec.rb
|
143
|
+
- spec/patient_zero/source_spec.rb
|
144
|
+
- spec/spec_helper.rb
|
56
145
|
homepage: ''
|
57
146
|
licenses:
|
58
147
|
- MIT
|
@@ -77,4 +166,18 @@ rubygems_version: 2.4.5
|
|
77
166
|
signing_key:
|
78
167
|
specification_version: 4
|
79
168
|
summary: A gem to use the Viral Heat API
|
80
|
-
test_files:
|
169
|
+
test_files:
|
170
|
+
- spec/patient_zero/analytics/base_spec.rb
|
171
|
+
- spec/patient_zero/analytics/facebook_spec.rb
|
172
|
+
- spec/patient_zero/analytics/instagram_spec.rb
|
173
|
+
- spec/patient_zero/analytics/twitter_spec.rb
|
174
|
+
- spec/patient_zero/analytics_spec.rb
|
175
|
+
- spec/patient_zero/authorization_spec.rb
|
176
|
+
- spec/patient_zero/client_spec.rb
|
177
|
+
- spec/patient_zero/message/facebook_spec.rb
|
178
|
+
- spec/patient_zero/message/instagram_spec.rb
|
179
|
+
- spec/patient_zero/message/twitter_spec.rb
|
180
|
+
- spec/patient_zero/message_spec.rb
|
181
|
+
- spec/patient_zero/organization_spec.rb
|
182
|
+
- spec/patient_zero/source_spec.rb
|
183
|
+
- spec/spec_helper.rb
|