lexervariables 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 866f1bc83bd911c1870c91da77d7acd725f2961f
4
+ data.tar.gz: 55286b7635617c451c6c535488330e57a1cacdc6
5
+ SHA512:
6
+ metadata.gz: d66dc4d6676cc0f4c66596970599ab3c6d63954078e1c5c44862288fbf07a0ef7a2c6ad1763a7b43cc4a73ff1d37194a798210279bd0d2316d0b9ef5e6665f51
7
+ data.tar.gz: c5c21c4c76e322a513b5ff3fa6b145cb939841e9bba7166ede0b114f6619ba109275713fe4ee6a9ee7eac8c29c4adc3df72441e96c7cb20b0568163f17d77d23
data/.gitignore ADDED
@@ -0,0 +1,38 @@
1
+ *.gem
2
+ *.rbc
3
+ *.swp
4
+ /.config
5
+ /coverage/
6
+ /InstalledFiles
7
+ /pkg/
8
+ /test/reports/
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+
13
+ ## Specific to RubyMotion:
14
+ .dat*
15
+ .repl_history
16
+ build/
17
+
18
+ ## Documentation cache and generated files:
19
+ /.yardoc/
20
+ /_yardoc/
21
+ /doc/
22
+ /rdoc/
23
+
24
+ ## Environment normalisation:
25
+ /.bundle/
26
+ /lib/bundler/man/
27
+
28
+ # for a library or gem, you might want to ignore these files since the code is
29
+ # intended to run in multiple environments; otherwise, check them in:
30
+ Gemfile.lock
31
+ .ruby-version
32
+ .ruby-gemset
33
+
34
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
35
+ .rvmrc
36
+
37
+ .swp
38
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in lexervariables.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # lexer-variables.gem
2
+
3
+ Gem for loading variables (terms, geographies, authors, pages, oauths) to monitor
4
+
5
+ Communicates with the [lexer-dashboard-app](http://github.com/lexerdev/lexer-dashboard-app) to lease:
6
+ * Monitored Terms
7
+ * Monitored Geo Regions
8
+ * Monitored Authors
9
+ * Monitored Pages
10
+ * OAuths (with associations to above)
11
+
12
+ This gem and the functionality held in the dashboard-app aims to retire the current implementation whereby variables and oauths are loaded from the Lexer-API thorugh the Lexer-API.gem.
13
+
14
+ # Tests
15
+
16
+ Run tests:
17
+ bundle exec rake test
18
+
19
+ # IRB
20
+
21
+ Need to have a tinker?
22
+
23
+ irb -rubygems -I lib -r $PWD/lib/lexervariables.rb
24
+
25
+
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # encoding: UTF-8
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |task|
5
+ task.libs << %w(test lib)
6
+ task.pattern = 'test/*.rb'
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "lexervariables/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "lexervariables"
7
+ s.version = LexerVariables::VERSION
8
+ s.authors = ["Aaron Wallis"]
9
+ s.email = ["aaron.wallis@lexer.com.au"]
10
+ s.homepage = "http://lexer.com.au"
11
+ s.summary = "Gem for loading variables (terms, geographies, authors, pages, oauths) to monitor"
12
+ s.description = "Gem for loading variables (terms, geographies, authors, pages, oauths) to monitor"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'faraday'
20
+ s.add_dependency 'multi_json'
21
+ s.add_dependency 'oj'
22
+
23
+ s.add_development_dependency 'minitest'
24
+ s.add_development_dependency 'minitest-reporters'
25
+ s.add_development_dependency 'factory_girl'
26
+ s.add_development_dependency 'faker'
27
+ s.add_development_dependency 'rake'
28
+ s.add_development_dependency 'webmock'
29
+ end
30
+
@@ -0,0 +1,85 @@
1
+ require 'oj'
2
+ require 'multi_json'
3
+ require 'lexervariables/error'
4
+ require 'lexervariables/version'
5
+
6
+ module LexerVariables
7
+ module_function
8
+
9
+ DEFAULT_ENDPOINT = 'https://lexer-dashboard/api/system/'
10
+ USER_AGENT = 'Lexer Worker'
11
+ SECRET_TOKEN = 'MLXTblicbwEVqyWXXrtz2DccoEuoqx9h5VFKZfBsP48QCOQ2hEcWvPDYoWwY4sQj'
12
+
13
+ def validate_provider(provider)
14
+ fail LexerVariables::UnknownProvider, "Unknown provider: #{provider}" unless [:facebook, :twitter, :instagram, :spinn3r, :yammer].include?(provider)
15
+ true
16
+ end
17
+
18
+ class Configuration
19
+ class << self
20
+ attr_accessor :endpoint
21
+ attr_accessor :api_key
22
+ end
23
+
24
+ @endpoint = DEFAULT_ENDPOINT
25
+ @api_key = SECRET_TOKEN
26
+
27
+ def self.default_options
28
+ {'api_token' => self.api_key}
29
+ end
30
+ end
31
+
32
+ class LexerModel
33
+ attr_accessor :attrs
34
+ alias :to_hash :attrs
35
+
36
+ # Define methods that retrieve the value from an initialized instance variable Hash, using the attribute as a key
37
+ #
38
+ # @overload self.lazy_attr_reader(attr)
39
+ # @param attr [Symbol]
40
+ # @overload self.lazy_attr_reader(attrs)
41
+ # @param attrs [Array<Symbol>]
42
+ def self.lazy_attr_reader(*attrs)
43
+ attrs.each do |attribute|
44
+ class_eval do
45
+ define_method attribute do
46
+ @attrs[attribute.to_s]
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # Initializes a new Base object
53
+ #
54
+ # @param attrs [Hash]
55
+ # @return [LexerModel]
56
+ def initialize(attrs={})
57
+ @attrs = attrs.dup
58
+ end
59
+
60
+ # Initializes a new Base object
61
+ #
62
+ # @param method [String, Symbol] Message to send to the object
63
+ def [](method)
64
+ self.__send__(method.to_sym)
65
+ rescue NoMethodError
66
+ nil
67
+ end
68
+
69
+ end
70
+ end
71
+
72
+ require 'lexervariables/api'
73
+ require 'lexervariables/dashboard_object'
74
+ require 'lexervariables/attribute_generator'
75
+ require 'lexervariables/attribute_geo_region'
76
+ require 'lexervariables/attribute_page'
77
+ require 'lexervariables/attribute_user'
78
+ require 'lexervariables/monitored_account'
79
+ require 'lexervariables/monitored_object'
80
+ require 'lexervariables/monitored_geo_region'
81
+ require 'lexervariables/monitored_page'
82
+ require 'lexervariables/monitored_term'
83
+ require 'lexervariables/monitored_user'
84
+ require 'lexervariables/monitored_url'
85
+ require 'lexervariables/oauth'
@@ -0,0 +1,90 @@
1
+ require 'faraday'
2
+ require 'oj'
3
+ require 'multi_json'
4
+
5
+ module LexerVariables
6
+
7
+ class ParseJson < ::Faraday::Response::Middleware
8
+ def parse(body)
9
+ case body
10
+ when '', 'null'
11
+ nil
12
+ when 'true'
13
+ true
14
+ when 'false'
15
+ false
16
+ else
17
+ MultiJson.decode(body)
18
+ end
19
+ end
20
+
21
+ def on_complete(env)
22
+ if env[:status] >= 300
23
+ fail ::LexerVariables::RequestError, "API Request error #{env[:status]} : #{env[:url]} : #{MultiJson.encode(env[:request_headers])} #{env[:body]}"
24
+ elsif env[:status] == 204
25
+ env[:body] = nil
26
+ else
27
+ env[:body] = parse(env[:body])
28
+ end
29
+ end
30
+ end
31
+
32
+ def self.api_connection(options={})
33
+ default_options = {
34
+ :headers => {
35
+ :accept => 'application/json'
36
+ },
37
+ :ssl => {
38
+ :verify => false
39
+ }
40
+ }
41
+ @__api_connection ||= Faraday.new(default_options.merge(options)) do |builder|
42
+ builder.use(Faraday::Request::UrlEncoded) # convert request params as "www-form-urlencoded"
43
+ builder.use(LexerVariables::ParseJson) # Decode the response as JSON
44
+ builder.use(Faraday::Adapter::NetHttp) # make http requests with Net::HTTP
45
+
46
+ # Enable if you want super noisy (but informative) logs
47
+ # builder.use Faraday::Response::Logger # log the request to STDOUT
48
+ end
49
+ end
50
+
51
+ def self.reset_connection
52
+ @__api_connection = nil
53
+ end
54
+
55
+ module Request
56
+ module_function
57
+
58
+ # Perform an HTTP GET request
59
+ def get(path, params={}, options={})
60
+ request(:get, path, params, options)
61
+ end
62
+
63
+ # Perform an HTTP POST request
64
+ def self.post(path, params={}, options={})
65
+ request(:post, path, params, options)
66
+ end
67
+
68
+ private
69
+ # Perform an HTTP request
70
+ def self.request(method, path, params, options)
71
+ params.merge!(LexerVariables::Configuration.default_options)
72
+ path = "#{LexerVariables::Configuration.endpoint}#{path}"
73
+ response = LexerVariables::api_connection(options).run_request(method, nil, nil, nil) do |request|
74
+ case method.to_sym
75
+ when :delete, :get
76
+ request.url(path, params)
77
+ when :post, :put
78
+ request.path = path
79
+ request.body = params unless params.empty?
80
+ request.options.timeout = 20
81
+ request.options.open_timeout = 30
82
+ else
83
+ fail LexerVariables::RequestError, "Request method '#{method}' is unsupported"
84
+ end
85
+ end
86
+ response.body
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,15 @@
1
+ class LexerVariables::AttributeGenerator < LexerVariables::DashboardObject
2
+ ENDPOINT = "attribute_generators"
3
+
4
+ lazy_attr_reader :object, :attributes
5
+
6
+ def self.format_object(objects)
7
+ objects.collect do |object|
8
+ {
9
+ 'object' => object.fetch('monitored_object', {})['object'],
10
+ 'attributes' => object['attributes']
11
+ }
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,7 @@
1
+ class LexerVariables::AttributeGeoRegion < LexerVariables::AttributeGenerator
2
+ private
3
+ def self.object_type
4
+ 'regions'
5
+ end
6
+ end
7
+
@@ -0,0 +1,7 @@
1
+ class LexerVariables::AttributePage < LexerVariables::AttributeGenerator
2
+ private
3
+ def self.object_type
4
+ 'pages'
5
+ end
6
+ end
7
+
@@ -0,0 +1,7 @@
1
+ class LexerVariables::AttributeUser < LexerVariables::AttributeGenerator
2
+ private
3
+ def self.object_type
4
+ 'users'
5
+ end
6
+ end
7
+
@@ -0,0 +1,34 @@
1
+ class LexerVariables::DashboardObject < LexerVariables::LexerModel
2
+ def self.all(provider:, shards: 0)
3
+ LexerVariables.validate_provider(provider)
4
+
5
+ objects = LexerVariables::Request.get("#{self::ENDPOINT}/#{provider}/#{self.object_type}")
6
+ formatted_objects = format_object(objects)
7
+ shard_objects(objects:formatted_objects, shards:shards)
8
+ end
9
+
10
+ def self.format_object(objects)
11
+ objects
12
+ end
13
+
14
+ def self.shard_objects(objects:, shards:)
15
+ return objects if shards == 0
16
+
17
+ # If we don't have enough objects to shard, every shard gets all the objects
18
+ return shards.times.collect{objects} if objects.size.to_f <= (shards * 2)
19
+
20
+ slice_size = (objects.size.to_f / shards).ceil
21
+ object_distribution = objects.each_slice(slice_size).collect{|i| i}
22
+ number_of_objects_to_shift = slice_size - object_distribution.last.size - 1
23
+ number_of_objects_to_shift.times do |i|
24
+ object_distribution.last << object_distribution[i].pop
25
+ end
26
+
27
+ object_distribution
28
+ end
29
+
30
+ def to_s
31
+ self.object
32
+ end
33
+ end
34
+
@@ -0,0 +1,7 @@
1
+ module LexerVariables
2
+ Error = Class.new(StandardError)
3
+
4
+ UnknownProvider = Class.new(Error)
5
+ RequestError = Class.new(Error)
6
+ InvalidObject = Class.new(Error)
7
+ end
@@ -0,0 +1,85 @@
1
+ require 'multi_json'
2
+
3
+ class LexerVariables::MonitoredAccount < LexerVariables::LexerModel
4
+ attr_reader :key
5
+ attr_reader :secret
6
+ attr_reader :username
7
+ attr_reader :email
8
+ attr_reader :client_id
9
+ attr_reader :id
10
+ attr_reader :monitored_object
11
+
12
+ def initialize(data)
13
+
14
+ unless data.key?('access_token_key') && data.key?('access_token_secret')
15
+ fail LexerVariables::InvalidObject, "JSON OAuth returned (#{data}) was not usable due to missing fields."
16
+ end
17
+
18
+ @key = data['access_token_key']
19
+ @secret = data['access_token_secret']
20
+ @username = data['username']
21
+ @email = data['email']
22
+ @client_id = data['client_id']
23
+ @monitored_object = data['monitored_object']
24
+ @id = data['id']
25
+ end
26
+
27
+ def self.lease(provider)
28
+ self.lease_object(provider, nil)
29
+ end
30
+
31
+ def self.lease_object(provider, monitored_object)
32
+ LexerVariables.validate_provider(provider)
33
+
34
+ options = {}
35
+ if monitored_object
36
+ options['monitored_object'] = monitored_object
37
+ end
38
+
39
+ response = LexerVariables::Request.get("monitored_accounts/#{provider}/lease", options)
40
+ return nil if response == {}
41
+ LexerVariables::MonitoredAccount.new(response)
42
+ end
43
+
44
+ def self.all(provider)
45
+ LexerVariables.validate_provider(provider)
46
+
47
+ monitored_accounts = LexerVariables::Request.get("monitored_accounts/#{provider}")
48
+ return nil if monitored_accounts == []
49
+
50
+ response = []
51
+ monitored_accounts.each do |monitored_account|
52
+ response << LexerVariables::MonitoredAccount.new(monitored_account)
53
+ end
54
+ #Sort as lowest MonitoredAccount.id going to worker 0
55
+ response = response.sort_by{|account| account.id }
56
+
57
+ return response
58
+ end
59
+
60
+ def self.send_error(provider, error_message, id)
61
+ LexerVariables.validate_provider(provider)
62
+
63
+ options = {
64
+ "provider" => provider,
65
+ "id" => id,
66
+ "error_message" => error_message
67
+ }
68
+
69
+ response = LexerVariables::Request.post('monitored_accounts/error', options)
70
+ if response.nil?
71
+ response = "Successfully posted email"
72
+ end
73
+ return response
74
+ end
75
+
76
+ def <=>(account)
77
+ if self.id < account.id
78
+ -1
79
+ elsif self.id > account.id
80
+ 1
81
+ else
82
+ 0
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,7 @@
1
+ class LexerVariables::MonitoredGeoRegion < LexerVariables::MonitoredObject
2
+ private
3
+ def self.object_type
4
+ 'regions'
5
+ end
6
+ end
7
+
@@ -0,0 +1,21 @@
1
+ require 'multi_json'
2
+
3
+ class LexerVariables::MonitoredObject < LexerVariables::DashboardObject
4
+ ENDPOINT = "monitored_objects"
5
+
6
+ lazy_attr_reader :object
7
+
8
+ def self.pop(provider:)
9
+ LexerVariables.validate_provider(provider)
10
+
11
+ response = LexerVariables::Request.get("#{ENDPOINT}/#{provider}/#{self.object_type}/pop")
12
+ self.new(response)
13
+ end
14
+
15
+ def self.format_object(objects)
16
+ objects.collect do |object|
17
+ object['object']
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,7 @@
1
+ class LexerVariables::MonitoredPage < LexerVariables::MonitoredObject
2
+ private
3
+ def self.object_type
4
+ 'pages'
5
+ end
6
+ end
7
+
@@ -0,0 +1,7 @@
1
+ class LexerVariables::MonitoredTerm < LexerVariables::MonitoredObject
2
+ private
3
+ def self.object_type
4
+ 'terms'
5
+ end
6
+ end
7
+
@@ -0,0 +1,7 @@
1
+ class LexerVariables::MonitoredURL < LexerVariables::MonitoredObject
2
+ private
3
+ def self.object_type
4
+ 'urls'
5
+ end
6
+ end
7
+
@@ -0,0 +1,7 @@
1
+ class LexerVariables::MonitoredUser < LexerVariables::MonitoredObject
2
+ private
3
+ def self.object_type
4
+ 'users'
5
+ end
6
+ end
7
+
@@ -0,0 +1,29 @@
1
+ require 'multi_json'
2
+
3
+ class LexerVariables::OAuth < LexerVariables::MonitoredObject
4
+ attr_reader :key
5
+ attr_reader :secret
6
+ attr_reader :username
7
+ attr_reader :email
8
+
9
+ def initialize(attrs)
10
+ super(attrs)
11
+ data = MultiJson::decode(object)
12
+
13
+ unless data.key?('access_token') && data.key?('access_token_secret')
14
+ fail LexerVariables::InvalidObject, "JSON OAuth returned (#{object}) was not usable due to missing fields."
15
+ end
16
+
17
+ @key = data['access_token']
18
+ @secret = data['access_token_secret']
19
+ @username = data['username']
20
+ @email = data['email']
21
+ end
22
+
23
+ private
24
+
25
+ def self.object_type
26
+ 'oauths'
27
+ end
28
+ end
29
+
@@ -0,0 +1,3 @@
1
+ module LexerVariables
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,45 @@
1
+ require 'test_helper'
2
+
3
+ describe LexerVariables::AttributeGenerator do
4
+
5
+ describe 'no objects to acquire' do
6
+ before do
7
+ stub_get("/api/system/attribute_generators/twitter/regions?api_token=#{LexerVariables::SECRET_TOKEN}").
8
+ to_return(body: MultiJson.dump('Not found'), status: 404) if $should_stub
9
+ end
10
+
11
+ it 'should fail for an unpopulated type' do
12
+ assert_raises LexerVariables::RequestError do
13
+ LexerVariables::AttributeGeoRegion.all(provider: :twitter)
14
+ end
15
+ end
16
+ end
17
+
18
+ describe '#all' do
19
+ let(:attribute_users) {
20
+ (1..10).collect { |x| test_attribute_user }
21
+ }
22
+
23
+ before do
24
+ stub_get("/api/system/attribute_generators/twitter/users?api_token=#{LexerVariables::SECRET_TOKEN}").
25
+ to_return(body: MultiJson.dump(attribute_users), status: 200) if $should_stub
26
+ end
27
+
28
+ it 'should get all attribute generator users for single provider' do
29
+ users = LexerVariables::AttributeUser.all(provider: :twitter)
30
+ users.must_be_instance_of(Array)
31
+ users.size.must_equal(10)
32
+ end
33
+
34
+ it 'should shard attribute generator users' do
35
+ users = LexerVariables::AttributeUser.all(provider: :twitter, shards: 4)
36
+ users.must_be_instance_of(Array)
37
+ users.size.must_equal(4)
38
+ users[0].must_be_instance_of(Array)
39
+ users[0].size.must_equal(2)
40
+ users[1].must_be_instance_of(Array)
41
+ users[1].size.must_equal(3)
42
+ users.flatten.size.must_equal(10)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,4 @@
1
+ #!/bin/bash
2
+
3
+ # Script (*external*) to launch a Docker container and run tests
4
+ docker run --rm -v $(pwd):/code -w /code phusion/passenger-ruby22 /code/test/docker-run-tests.sh
@@ -0,0 +1,9 @@
1
+ #!/bin/bash
2
+
3
+ # Script to execute lexer-variables.gem tests *inside* a Docker container
4
+ #
5
+ # Expectations:
6
+ # - lexer-variables.gem checkout is mounted at /code
7
+
8
+ bundle install --standalone &&\
9
+ bundle exec rake test
@@ -0,0 +1,21 @@
1
+ FactoryGirl.define do
2
+
3
+ factory :monitored_account, class:Hash do
4
+ id { Faker::Number.number(4).to_i }
5
+ provider { "twitter" }
6
+ client_id { Faker::Number.digit }
7
+ username { Faker::Internet.user_name }
8
+ email { Faker::Internet.email }
9
+ access_token_key { Faker::Internet.password(8) }
10
+ access_token_secret { Faker::Internet.password(16) }
11
+ monitored_object { Faker::Lorem::words(1)[0] }
12
+ last_used { DateTime.now.iso8601 }
13
+ expires { DateTime.now.iso8601 }
14
+ created_time { DateTime.now.iso8601 }
15
+ updated_time { DateTime.now.iso8601 }
16
+ is_priority { false }
17
+
18
+ initialize_with { attributes }
19
+ end
20
+
21
+ end
@@ -0,0 +1,9 @@
1
+ FactoryGirl.define do
2
+
3
+ factory :monitored_term, class:Hash do
4
+ object { Faker::Lorem::words(1)[0] }
5
+
6
+ initialize_with { attributes }
7
+ end
8
+
9
+ end
@@ -0,0 +1,9 @@
1
+ FactoryGirl.define do
2
+
3
+ factory :oauth, class:Hash do
4
+ object { MultiJson::encode({access_token: 'abcdef', access_token_secret:'ghi'}) }
5
+
6
+ initialize_with { attributes }
7
+ end
8
+
9
+ end
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ describe LexerVariables do
4
+ describe '#validate_provider' do
5
+ it 'should reject invalid network' do
6
+ assert_raises LexerVariables::UnknownProvider do
7
+ LexerVariables.validate_provider(:lexer)
8
+ end
9
+ end
10
+
11
+ it 'should accept valid networks' do
12
+ assert LexerVariables.validate_provider(:twitter)
13
+ assert LexerVariables.validate_provider(:spinn3r)
14
+ assert LexerVariables.validate_provider(:instagram)
15
+ assert LexerVariables.validate_provider(:facebook)
16
+ assert LexerVariables.validate_provider(:yammer)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,106 @@
1
+ require 'test_helper'
2
+
3
+ describe LexerVariables::MonitoredAccount do
4
+
5
+ describe 'no accounts to monitor' do
6
+ before do
7
+ stub_get("/api/system/monitored_accounts/twitter/lease?api_token=#{LexerVariables::SECRET_TOKEN}").
8
+ to_return(body: MultiJson.dump('Not found'), status: 404) if $should_stub
9
+ end
10
+
11
+ it 'fails' do
12
+ assert_raises LexerVariables::RequestError do
13
+ LexerVariables::MonitoredAccount.lease(:twitter)
14
+ end
15
+ end
16
+ end
17
+
18
+ describe '#all' do
19
+ let(:monitored_accounts) {[
20
+ FactoryGirl.build(:monitored_account),
21
+ FactoryGirl.build(:monitored_account),
22
+ FactoryGirl.build(:monitored_account),
23
+ FactoryGirl.build(:monitored_account),
24
+ FactoryGirl.build(:monitored_account)
25
+ ]}
26
+
27
+ before do
28
+ stub_get("/api/system/monitored_accounts/twitter?api_token=#{LexerVariables::SECRET_TOKEN}").
29
+ to_return(body: MultiJson.dump(monitored_accounts)) if $should_stub
30
+
31
+ stub_get("/api/system/monitored_accounts/facebook?api_token=#{LexerVariables::SECRET_TOKEN}").
32
+ to_return(body: MultiJson.dump([])) if $should_stub
33
+ end
34
+
35
+ it 'should get all monitored accounts for single provider' do
36
+ accounts = LexerVariables::MonitoredAccount.all(:twitter)
37
+ accounts.must_be_instance_of(Array)
38
+ accounts.size.must_equal(5)
39
+ end
40
+
41
+ it 'should return nil for provider with no accounts' do
42
+ accounts = LexerVariables::MonitoredAccount.all(:facebook)
43
+ accounts.must_be_instance_of(NilClass)
44
+ end
45
+
46
+ it 'should return monitored accounts in sorted order' do
47
+ accounts = LexerVariables::MonitoredAccount.all(:twitter)
48
+ accounts.must_be_instance_of(Array)
49
+ accounts.size.must_equal(5)
50
+ last_id = -1
51
+ sorted = true
52
+ accounts.each do |account|
53
+ sorted &= account.id > last_id
54
+ last_id = account.id if sorted
55
+ end
56
+ assert(sorted, 'monitored_accounts are not sorted by .id')
57
+ end
58
+ end
59
+
60
+ describe 'twitter' do
61
+ let(:monitored_account) {
62
+ FactoryGirl.build(:monitored_account)
63
+ }
64
+
65
+ describe 'get accounts to monitor' do
66
+ before do
67
+ stub_get("/api/system/monitored_accounts/twitter/lease?api_token=#{LexerVariables::SECRET_TOKEN}").
68
+ to_return(body: MultiJson.dump(monitored_account)) if $should_stub
69
+ end
70
+
71
+ it 'leases a single account' do
72
+ account = LexerVariables::MonitoredAccount.lease(:twitter)
73
+ account.must_be_instance_of(LexerVariables::MonitoredAccount)
74
+ account.monitored_object.must_equal(monitored_account[:monitored_object])
75
+ account.key.must_equal(monitored_account[:access_token_key])
76
+ account.secret.must_equal(monitored_account[:access_token_secret])
77
+ account.client_id.must_equal(monitored_account[:client_id])
78
+ end
79
+ end
80
+ end
81
+
82
+ describe 'facebook' do
83
+ let(:monitored_account) {
84
+ FactoryGirl.build(:monitored_account)
85
+ }
86
+
87
+ let(:facebook_page_id) {
88
+ Faker::Internet.password(8)
89
+ }
90
+
91
+ describe 'get accounts to monitor' do
92
+ before do
93
+ stub_get("/api/system/monitored_accounts/facebook/lease?api_token=#{LexerVariables::SECRET_TOKEN}&monitored_object=#{facebook_page_id}").
94
+ to_return(body: MultiJson.dump(monitored_account)) if $should_stub
95
+ end
96
+
97
+ it 'leases a single account' do
98
+ account = LexerVariables::MonitoredAccount.lease_object(:facebook, facebook_page_id)
99
+ account.must_be_instance_of(LexerVariables::MonitoredAccount)
100
+ account.monitored_object.must_equal(monitored_account[:monitored_object])
101
+ account.key.must_equal(monitored_account[:access_token_key])
102
+ account.secret.must_equal(monitored_account[:access_token_secret])
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,62 @@
1
+ require 'test_helper'
2
+
3
+ describe LexerVariables::MonitoredObject do
4
+
5
+ describe 'no objects to acquire' do
6
+ before do
7
+ stub_get("/api/system/monitored_objects/twitter/regions/pop?api_token=#{LexerVariables::SECRET_TOKEN}").
8
+ to_return(body: MultiJson.dump('Not found'), status: 404) if $should_stub
9
+ end
10
+
11
+ it 'should fail for an unpopulated type' do
12
+ assert_raises LexerVariables::RequestError do
13
+ LexerVariables::MonitoredGeoRegion.pop(provider: :twitter)
14
+ end
15
+ end
16
+ end
17
+
18
+ describe '#all' do
19
+ let(:monitored_terms) {
20
+ (1..10).collect { |x| FactoryGirl.build(:monitored_term, object: x.to_s) }
21
+ }
22
+
23
+ before do
24
+ stub_get("/api/system/monitored_objects/twitter/terms?api_token=#{LexerVariables::SECRET_TOKEN}").
25
+ to_return(body: MultiJson.dump(monitored_terms), status: 200) if $should_stub
26
+ end
27
+
28
+ it 'should get all monitored terms for single provider' do
29
+ terms = LexerVariables::MonitoredTerm.all(provider: :twitter)
30
+ terms.must_be_instance_of(Array)
31
+ terms.size.must_equal(10)
32
+ end
33
+
34
+ it 'should shard monitored terms' do
35
+ terms = LexerVariables::MonitoredTerm.all(provider: :twitter, shards: 4)
36
+ terms.must_be_instance_of(Array)
37
+ terms.size.must_equal(4)
38
+ terms[0].must_be_instance_of(Array)
39
+ terms[0].size.must_equal(2)
40
+ terms[1].must_be_instance_of(Array)
41
+ terms[1].size.must_equal(3)
42
+ terms.flatten.size.must_equal(10)
43
+ end
44
+
45
+ end
46
+
47
+ describe '#pop' do
48
+ let(:monitored_term) { |x| FactoryGirl.build(:monitored_term) }
49
+
50
+ before do
51
+ stub_get("/api/system/monitored_objects/twitter/terms/pop?api_token=#{LexerVariables::SECRET_TOKEN}").
52
+ to_return(body: MultiJson.dump(monitored_term), status: 200) if $should_stub
53
+ stub_get("/api/system/monitored_objects/twitter/regions/pop?api_token=#{LexerVariables::SECRET_TOKEN}").
54
+ to_return(body: '{"error":"404 Not Found"}', status: 404) if $should_stub
55
+ end
56
+
57
+ it 'should acquire a term' do
58
+ term1 = LexerVariables::MonitoredTerm.pop(provider: :twitter)
59
+ term1.to_s.must_equal(monitored_term[:object])
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,22 @@
1
+ require 'test_helper'
2
+
3
+ describe LexerVariables::OAuth do
4
+
5
+ describe '#pop' do
6
+ let(:oauth) { |x| FactoryGirl.build(:oauth) }
7
+
8
+ before do
9
+ stub_get("/api/system/monitored_objects/twitter/oauths/pop?api_token=#{LexerVariables::SECRET_TOKEN}").
10
+ to_return(body: MultiJson.dump(oauth), status: 200) if $should_stub
11
+ end
12
+
13
+ it 'should acquire an OAuth' do
14
+ oauth = LexerVariables::OAuth.pop(provider: :twitter)
15
+ oauth.key.must_equal('abcdef')
16
+ oauth.secret.must_equal('ghi')
17
+ end
18
+
19
+ end
20
+
21
+
22
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'minitest/autorun'
4
+ require 'minitest/reporters'
5
+ require 'minitest/spec'
6
+ require 'webmock/minitest'
7
+ require 'faker'
8
+ require 'factory_girl'
9
+
10
+ MiniTest::Reporters.use! [Minitest::Reporters::SpecReporter.new, MiniTest::Reporters::JUnitReporter.new]
11
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'lexervariables')
12
+ FactoryGirl.find_definitions
13
+
14
+ $should_stub = true
15
+ if $should_stub
16
+ WebMock.disable_net_connect!
17
+ else
18
+ WebMock.allow_net_connect!
19
+ end
20
+
21
+ def request_path(path)
22
+ "https://lexer-dashboard#{path}"
23
+ end
24
+
25
+ def stub_get(path)
26
+ WebMock::API.stub_http_request(:get, request_path(path))
27
+ end
28
+
29
+ # As the hash requires a key called 'attributes', this breaks factory call as when you call
30
+ # ```initialise_with { attributes }``` in FactoryGirl, it becomes infinitely recursive.
31
+ def test_attribute_user
32
+ {
33
+ monitored_object: {
34
+ object: Faker::Number.number(10)
35
+ },
36
+ attributes: ['io.company.' + Faker::Lorem::words(1)[0]] * 3
37
+ }
38
+ end
metadata ADDED
@@ -0,0 +1,204 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lexervariables
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Wallis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: oj
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
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: minitest-reporters
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'
83
+ - !ruby/object:Gem::Dependency
84
+ name: factory_girl
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: faker
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: webmock
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Gem for loading variables (terms, geographies, authors, pages, oauths)
140
+ to monitor
141
+ email:
142
+ - aaron.wallis@lexer.com.au
143
+ executables: []
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".gitignore"
148
+ - Gemfile
149
+ - README.md
150
+ - Rakefile
151
+ - lexervariables.gemspec
152
+ - lib/lexervariables.rb
153
+ - lib/lexervariables/api.rb
154
+ - lib/lexervariables/attribute_generator.rb
155
+ - lib/lexervariables/attribute_geo_region.rb
156
+ - lib/lexervariables/attribute_page.rb
157
+ - lib/lexervariables/attribute_user.rb
158
+ - lib/lexervariables/dashboard_object.rb
159
+ - lib/lexervariables/error.rb
160
+ - lib/lexervariables/monitored_account.rb
161
+ - lib/lexervariables/monitored_geo_region.rb
162
+ - lib/lexervariables/monitored_object.rb
163
+ - lib/lexervariables/monitored_page.rb
164
+ - lib/lexervariables/monitored_term.rb
165
+ - lib/lexervariables/monitored_url.rb
166
+ - lib/lexervariables/monitored_user.rb
167
+ - lib/lexervariables/oauth.rb
168
+ - lib/lexervariables/version.rb
169
+ - test/attribute_generator_test.rb
170
+ - test/docker-launch-tests.sh
171
+ - test/docker-run-tests.sh
172
+ - test/factories/monitored_accounts.rb
173
+ - test/factories/monitored_terms.rb
174
+ - test/factories/oauths.rb
175
+ - test/lexer_variables_test.rb
176
+ - test/monitored_account_test.rb
177
+ - test/monitored_object_test.rb
178
+ - test/oauth_test.rb
179
+ - test/test_helper.rb
180
+ homepage: http://lexer.com.au
181
+ licenses: []
182
+ metadata: {}
183
+ post_install_message:
184
+ rdoc_options: []
185
+ require_paths:
186
+ - lib
187
+ required_ruby_version: !ruby/object:Gem::Requirement
188
+ requirements:
189
+ - - ">="
190
+ - !ruby/object:Gem::Version
191
+ version: '0'
192
+ required_rubygems_version: !ruby/object:Gem::Requirement
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ version: '0'
197
+ requirements: []
198
+ rubyforge_project:
199
+ rubygems_version: 2.2.2
200
+ signing_key:
201
+ specification_version: 4
202
+ summary: Gem for loading variables (terms, geographies, authors, pages, oauths) to
203
+ monitor
204
+ test_files: []