salsa_labs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 789c61d06d857f8f1de240ce34828659bc89f63f
4
+ data.tar.gz: 51a6cf8d8845b2105ca3afaaa5dcab4bf37b8856
5
+ SHA512:
6
+ metadata.gz: 7f4b97d640ef36363b0a47054e2b0e05beab55f345300d59ac92983521531312f00154a117fcc4942cc1e38518319e57fa98826c3ddd8a756cf8734290dbcc30
7
+ data.tar.gz: ea1f1ea916fef505b78ee05d846109e7df28a76ce62e9a10685566dec3b2df4276402f295c2bf98191524027a4dc1ab4ec2d688abac9d0584200bf649cddcf77
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bateman.gemspec
4
+ gemspec
5
+
data/Gemfile.lock ADDED
@@ -0,0 +1,58 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ salsa_labs (0.0.1)
5
+ faraday
6
+ httparty
7
+ nokogiri
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ addressable (2.3.5)
13
+ crack (0.4.1)
14
+ safe_yaml (~> 0.9.0)
15
+ diff-lcs (1.2.5)
16
+ docile (1.1.1)
17
+ fakeweb (1.3.0)
18
+ faraday (0.8.8)
19
+ multipart-post (~> 1.2.0)
20
+ httparty (0.12.0)
21
+ json (~> 1.8)
22
+ multi_xml (>= 0.5.2)
23
+ json (1.8.1)
24
+ mini_portile (0.5.2)
25
+ multi_json (1.8.2)
26
+ multi_xml (0.5.5)
27
+ multipart-post (1.2.0)
28
+ nokogiri (1.6.1)
29
+ mini_portile (~> 0.5.0)
30
+ rspec (2.14.1)
31
+ rspec-core (~> 2.14.0)
32
+ rspec-expectations (~> 2.14.0)
33
+ rspec-mocks (~> 2.14.0)
34
+ rspec-core (2.14.7)
35
+ rspec-expectations (2.14.4)
36
+ diff-lcs (>= 1.1.3, < 2.0)
37
+ rspec-mocks (2.14.4)
38
+ safe_yaml (0.9.7)
39
+ simplecov (0.8.2)
40
+ docile (~> 1.1.0)
41
+ multi_json
42
+ simplecov-html (~> 0.8.0)
43
+ simplecov-html (0.8.0)
44
+ vcr (2.8.0)
45
+ webmock (1.16.1)
46
+ addressable (>= 2.2.7)
47
+ crack (>= 0.3.2)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ fakeweb
54
+ rspec
55
+ salsa_labs!
56
+ simplecov
57
+ vcr
58
+ webmock
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Velocity
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # SalsaLabs bindings for Ruby
2
+
3
+ [![Gem
4
+ Version](https://badge.fury.io/rb/salsa_labs.png)](http://badge.fury.io/rb/salsa_labs)
5
+ [![Build Status](https://travis-ci.org/fivetooldev/salsa_labs.png?branch=master)](https://travis-ci.org/fivetooldev/salsa_labs)
6
+ [![Dependency Status](https://gemnasium.com/fivetooldev/salsa_labs.png)](https://gemnasium.com/fivetooldev/salsa_labs)
7
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/fivetooldev/salsa_labs)
8
+
9
+ ``salsa_labs`` can fetch data from the [Salsa Labs](http://salsalabs.com) API.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'salsa_labs'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install salsa_labs
24
+
25
+ ## Usage
26
+
27
+ By default, you can store your API credentials as the environment variables ``SALSA_LABS_API_EMAIL`` and ``SALSA_LABS_API_PASSWORD`` to avoid the need to re-enter your password multiple times. Otherwise you will need to pass your credentials into the ``SalsaLabs::ApiClient`` or appropriate fetching method as you call it.
28
+
29
+ ``SalsaLabs::ApiClient`` is a general-purpose object for performing GET requests from the Salsa API.
30
+
31
+ ```ruby
32
+ # Create a client
33
+ client = SalsaLabs::ApiClient.new({email: 'barry@example.com', password: 'myPassword'})
34
+
35
+ # Perform arbitrary requests from Salsa API. If not already authenticated, client will do so automatically.
36
+ client.fetch('getObjects.sjs', {object: 'Supporter'})
37
+ # => Returns XML output of all supporters returned by API.
38
+
39
+ # Pass filter criteria to #fetch to retrieve a more focused result set.
40
+ # Filtering can be necessary if your result set exceeds allowed API limits.
41
+ # This query pulls all supporters with an address in Washington, D.C.
42
+ client.fetch('getObjects.sjs', {object: 'Supporter', State: 'DC'})
43
+ ```
44
+
45
+ You can get a list of API calls and information about Salsa database objects here:
46
+ [https://help.salsalabs.com/entries/23537918-Getting-data-from-Salsa](https://help.salsalabs.com/entries/23537918-Getting-data-from-Salsa)
47
+
48
+ Currently specific functionality exists to work with Action campaigns, but more objects will be added later.
49
+
50
+ ```ruby
51
+ # Fetch all actions from Salsa. First argument is filter criteria, second argument is credentials if you are not storing them as environment variables.
52
+ actions = SalsaLabs::Action.fetch({}, {})
53
+ # => Array of SalsaLabs::Action objects.
54
+
55
+ # Examine the Action.
56
+ actions.first.attributes
57
+ # => {'title' => 'My Action Title', 'organization_key' => '90210', action_key => '1234'}
58
+ ```
59
+
60
+ ``SalsaLabs::Action#attributes`` returns a hash corresponding to all the attributes returned by the API, so it should accommodate custom fields and/or new fields added later by SalsaLabs. All attribute names are downcased.
61
+
62
+ ## Dependencies
63
+
64
+ Ruby 1.9 is required.
65
+
66
+ ## Credits
67
+
68
+ The ``salsa_labs`` gem was created and is maintained by [Allison Sheren](http://github.com/asheren) and [Geoff Harcourt](http://github.com/geoffharcourt).
69
+
70
+ Development is generously sponsored by [Velocity](http://wearevelocity.com), in support of their work with progressive organizations.
71
+
72
+ ## Contributing
73
+
74
+ 1. Fork it
75
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
76
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
77
+ 4. Push to the branch (`git push origin my-new-feature`)
78
+ 5. Create new Pull Request
79
+
80
+ ## License
81
+
82
+ The ``salsa_labs`` gem is Copyright 2013-2014 Velocity. It is free software, and
83
+ may be redistributed under the terms of the MIT license, specified in the
84
+ LICENSE file.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,85 @@
1
+ module SalsaLabs
2
+ ##
3
+ # Used to request information from Salsa Labs. Handles cookie-based
4
+ # authentication, and raises an exception when the API returns an error.
5
+ ##
6
+ class ApiClient
7
+
8
+ attr_reader :authentication_cookie
9
+
10
+ def initialize(credentials = {})
11
+ @email = credentials[:email] || ENV['SALSA_LABS_API_EMAIL']
12
+ @password = credentials[:password] || ENV['SALSA_LABS_API_PASSWORD']
13
+
14
+ @authenticated = false
15
+ end
16
+
17
+ def authenticate
18
+ return true if authenticated?
19
+
20
+ response = authenticate!
21
+
22
+ @authentication_cookie = response.env[:response_headers]["set-cookie"]
23
+ @authenticated = Nokogiri::XML(response.body).css('error').empty?
24
+ end
25
+
26
+ def authenticated?
27
+ @authenticated
28
+ end
29
+
30
+ def fetch(endpoint, params)
31
+ authenticate unless authenticated?
32
+
33
+ perform_get_request(endpoint, params).body
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :authenticated,
39
+ :email,
40
+ :password
41
+
42
+ def authenticate!
43
+ perform_get_request(
44
+ '/api/authenticate.sjs',
45
+ authentication_parameters
46
+ )
47
+ end
48
+
49
+ def authentication_parameters
50
+ {email: email, password: password}
51
+ end
52
+
53
+ def connection
54
+ @connection ||= Faraday.
55
+ new(url: 'https://hq-salsa.wiredforchange.com') do |faraday|
56
+
57
+ faraday.use Faraday::Request::UrlEncoded
58
+ faraday.adapter Faraday.default_adapter
59
+ end
60
+ end
61
+
62
+ def perform_get_request(endpoint, params)
63
+ response = connection.get do |request|
64
+ request.headers['cookie'] = authentication_cookie.to_s
65
+ request.url(endpoint, params)
66
+ end
67
+
68
+ raise_if_error!(response)
69
+
70
+ response
71
+ end
72
+
73
+ def raise_if_error!(response)
74
+ # Raise SalsaLabs::Error if response.body contains error (need to do this
75
+ # because API always gives 200 but then gives an error in the XML).
76
+ errors = Nokogiri::XML(response.body).css('error')
77
+
78
+ if errors.any?
79
+ raise SalsaLabs::Error.new(response),
80
+ "There is an error: #{errors.first.text}"
81
+ end
82
+ end
83
+ end
84
+
85
+ end
@@ -0,0 +1,35 @@
1
+ module SalsaLabs
2
+ ##
3
+ # Action represents a single instance of an advocacy campaign ("Action") in
4
+ # the Salsa Labs / DemocracyInAction CRM.
5
+ ##
6
+ class Action < SalsaObject
7
+
8
+ attr_reader :attributes
9
+
10
+ def initialize(attributes)
11
+ @attributes = attributes
12
+ end
13
+
14
+ def action_key
15
+ (attributes['action_key'] || 0).to_i
16
+ end
17
+
18
+ def description
19
+ attributes['description']
20
+ end
21
+
22
+ def reference_name
23
+ attributes['reference_name']
24
+ end
25
+
26
+ def title
27
+ attributes['title']
28
+ end
29
+
30
+ def self.fetch(credentials = {})
31
+ ActionsFetcher.new(credentials).fetch
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,61 @@
1
+ module SalsaLabs
2
+ ##
3
+ # Service object to pull back a collection of actions from the Salsa Labs API.
4
+ ##
5
+ class ActionsFetcher
6
+
7
+ def initialize(filter_parameters = {}, credentials = {})
8
+ @filter_parameters = filter_parameters
9
+ @client = SalsaLabs::ApiClient.new(credentials)
10
+ end
11
+
12
+ def fetch
13
+ item_nodes.map do |node|
14
+ SalsaLabs::Action.new(SalsaLabsApiObjectNode.new(node).attributes)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :client, :filter_parameters
21
+
22
+ def api_call
23
+ client.fetch('/api/getObjects.sjs', api_parameters)
24
+ end
25
+
26
+ def api_parameters
27
+ filter_parameters.merge(object: 'Action')
28
+ end
29
+
30
+ def item_nodes
31
+ Nokogiri::XML(api_call).css('item')
32
+ end
33
+
34
+ ##
35
+ # Object used to translate API's XML node into a hash of attributes for
36
+ # SalsaLabs::Action creation.
37
+ ##
38
+ class SalsaLabsApiObjectNode
39
+
40
+ def initialize(xml_element)
41
+ @node = xml_element
42
+ end
43
+
44
+ def attributes
45
+ children.inject({}) do |memo, attribute|
46
+ memo[attribute.name.downcase] = attribute.text
47
+ attribute
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ attr_reader :node
54
+
55
+ def children
56
+ node.children
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,19 @@
1
+ module SalsaLabs
2
+ ##
3
+ # Base class used for subclasses that can be represented by Salsa Labs
4
+ # concepts that can be returned by getObject or getObjects.
5
+ ##
6
+ class SalsaObject
7
+
8
+ attr_reader :attributes
9
+
10
+ def initialize(params)
11
+ @attributes = params
12
+ end
13
+
14
+ def organization_key
15
+ (attributes['organization_key'] || 0).to_i
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module SalsaLabs
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'salsa_labs/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "salsa_labs"
8
+ gem.version = SalsaLabs::VERSION
9
+ gem.authors = ['Geoff Harcourt', 'Allison Sheren']
10
+ gem.email = ['asheren@gmail.com']
11
+ gem.description = %q{A Ruby binding for the Salsa Labs (http://salsalabs.com) API.}
12
+ gem.summary = %q{Salsa Labs' API contains information about supporters, donations, and actions. This gem faciliates pulling that information into a Ruby application.}
13
+ gem.homepage = "http://github.com/geoffharcourt/ruby-salsa_labs"
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.test_files = gem.files.grep(%r{^(spec)/})
16
+ gem.require_paths = ['lib']
17
+ gem.licenses = ['LICENSE']
18
+
19
+ gem.add_runtime_dependency 'dotenv'
20
+ gem.add_runtime_dependency 'faraday'
21
+ gem.add_runtime_dependency 'httparty'
22
+ gem.add_runtime_dependency 'nokogiri'
23
+
24
+ gem.add_development_dependency 'fakeweb'
25
+ gem.add_development_dependency 'rspec'
26
+ gem.add_development_dependency 'simplecov'
27
+ gem.add_development_dependency 'vcr'
28
+ gem.add_development_dependency 'webmock'
29
+
30
+ end
data/salsa_labs.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'faraday'
2
+ require 'nokogiri'
3
+
4
+ require 'salsa_labs/version'
5
+ require 'salsa_labs/api_client'
6
+ require 'salsa_labs/salsa_object'
7
+ require 'salsa_labs/action'
8
+ require 'salsa_labs/actions_fetcher'
9
+
10
+ module SalsaLabs
11
+
12
+ ##
13
+ # Exception class for API-related errors.
14
+ ##
15
+ class Error < StandardError
16
+ end
17
+
18
+ end
@@ -0,0 +1,50 @@
1
+ <?xml version="1.0"?>
2
+ <data organization_KEY="6120">
3
+ <Action>
4
+ <item>
5
+ <action_KEY>6656</action_KEY>
6
+ <organization_KEY>6120</organization_KEY>
7
+ <chapter_KEY/>
8
+ <Last_Modified>Tue Dec 17 2013 11:08:58 GMT-0500 (EST)</Last_Modified>
9
+ <Date_Created>Wed Sep 26 2012 14:30:02 GMT-0400 (EDT)</Date_Created>
10
+ <Reference_Name>My TItle</Reference_Name>
11
+ <Title>My Action Title</Title>
12
+ <Description>&lt;p&gt;&amp;#160;&lt;/p&gt;</Description>
13
+ <Allow_Comments_BOOLVALUE>false</Allow_Comments_BOOLVALUE>
14
+ <Allow_Comments>false</Allow_Comments>
15
+ <Comment_Question/>
16
+ <Max_Number_Of_Emails/>
17
+ <Max_Number_Of_Faxes/>
18
+ <Signatures/>
19
+ <Signature_Goal/>
20
+ <Deadline/>
21
+ <Signature_Minimum_for_Display/>
22
+ <Allow_Anonymous_BOOLVALUE>false</Allow_Anonymous_BOOLVALUE>
23
+ <Allow_Anonymous>false</Allow_Anonymous>
24
+ <Footer>&lt;p&gt;&amp;#160;&lt;/p&gt;</Footer>
25
+ <Request>First_Name,Last_Name,Street,Street_2,City,State,Zip,Email</Request>
26
+ <Required>First_Name,Last_Name,Street,City,State,Zip,Email</Required>
27
+ <Thank_You_Text/>
28
+ <redirect_path/>
29
+ <alternate_action_path/>
30
+ <email_trigger_KEYS/>
31
+ <add_to_groups_KEYS/>
32
+ <optionally_add_to_groups_KEYS/>
33
+ <Restriction_Type/>
34
+ <Restricted_Regions/>
35
+ <Restricted_Districts/>
36
+ <Restricted_Text/>
37
+ <No_Target_Text/>
38
+ <template_KEY/>
39
+ <Style>Targeted</Style>
40
+ <style_path/>
41
+ <Status/>
42
+ <linkRequest/>
43
+ <linkRequired/>
44
+ <key>6656</key>
45
+ <object>action</object>
46
+ </item>
47
+ <count>1</count>
48
+ </Action>
49
+ </data>
50
+
@@ -0,0 +1,67 @@
1
+ require "spec_helper"
2
+
3
+ describe SalsaLabs::Action do
4
+
5
+ let(:attributes) do
6
+ {
7
+ 'action_key' => '1234',
8
+ 'description' => 'Lengthy Description',
9
+ 'organization_key' => '90210',
10
+ 'reference_name' => 'A Good Reference',
11
+ 'title' => 'A Distinguished Title'
12
+ }
13
+ end
14
+
15
+ let(:action) { SalsaLabs::Action.new(attributes) }
16
+
17
+ describe "#action_key" do
18
+ it "returns the action_key attribute as an integer" do
19
+ expect(action.action_key).to eq(1234)
20
+ end
21
+ end
22
+
23
+ describe "#attributes" do
24
+ it "returns the attributes hash passed in to initialize" do
25
+ expect(action.attributes).to eq(attributes)
26
+ end
27
+ end
28
+
29
+ describe "#description" do
30
+ it "returns the description attribute" do
31
+ expect(action.description).to eq('Lengthy Description')
32
+ end
33
+ end
34
+
35
+ describe "#organization_key" do
36
+ it "returns the organization_key attribute as an integer" do
37
+ expect(action.organization_key).to eq(90210)
38
+ end
39
+ end
40
+
41
+ describe "#reference_name" do
42
+ it "returns the reference_name attribute" do
43
+ expect(action.reference_name).to eq('A Good Reference')
44
+ end
45
+ end
46
+
47
+ describe "#title" do
48
+ it "returns the title as an attribute" do
49
+ expect(action.title).to eq('A Distinguished Title')
50
+ end
51
+ end
52
+
53
+ describe ".fetch" do
54
+ let(:actions_fetcher) { double('ActionsFetcher', fetch: []) }
55
+
56
+ before(:each) do
57
+ SalsaLabs::ActionsFetcher.stub(new: actions_fetcher)
58
+ end
59
+
60
+ it "calls .fetch on an SalsaLabs::ActionsFetcher object" do
61
+ SalsaLabs::Action.fetch
62
+
63
+ expect(actions_fetcher).to have_received(:fetch)
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,32 @@
1
+ require "spec_helper"
2
+
3
+ describe SalsaLabs::ActionsFetcher do
4
+
5
+ let(:client) do
6
+ double(
7
+ 'API client',
8
+ fetch: File.read('spec/fixtures/getObjects.sjs_action.xml')
9
+ )
10
+ end
11
+
12
+ describe "#fetch" do
13
+ before(:each) do
14
+ allow(SalsaLabs::ApiClient).to receive(:new) { client }
15
+ end
16
+
17
+ it "calls the getObjects API endpoint" do
18
+ SalsaLabs::ActionsFetcher.new.fetch
19
+
20
+ expect(client).to have_received(:fetch).
21
+ with('/api/getObjects.sjs', {object: 'Action'})
22
+ end
23
+
24
+ it "returns an array of SalsaLabs::Action objects" do
25
+ results = SalsaLabs::ActionsFetcher.new.fetch
26
+
27
+ expect(results).to be_a(Array)
28
+ expect(results.first).to be_a(SalsaLabs::Action)
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+ require 'vcr'
3
+
4
+ describe SalsaLabs::ApiClient do
5
+
6
+ let(:api_client) do
7
+ SalsaLabs::ApiClient.new({
8
+ email: 'allison@example.com', password: 'password'
9
+ })
10
+ end
11
+
12
+ describe "#authenticate" do
13
+ it "stores the cookie from Salsa Labs" do
14
+ VCR.use_cassette 'successful_authentication',
15
+ match_requests_on: [:path] do
16
+
17
+ api_client.authenticate
18
+
19
+ expect(api_client.authentication_cookie).to eq(
20
+ 'JSESSIONID=67EBA60BFE7BCF73E2BA0B8E6F9592D0-n2; Path=/; Secure; '\
21
+ 'HttpOnly, hqtab_2=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT, '\
22
+ 'READONLY_Short_Name=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT, '\
23
+ 'SRV=vweb213; path=/'
24
+ )
25
+ end
26
+ end
27
+
28
+ context "with proper credentials" do
29
+ it "sets authenticated to be true" do
30
+ VCR.use_cassette 'successful_authentication',
31
+ match_requests_on: [:path] do
32
+
33
+ api_client.authenticate
34
+
35
+ expect(api_client.authenticated?).to be_true
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ context "with improper credentials" do
42
+ it "raises an exception" do
43
+ VCR.use_cassette 'unsuccessful_authentication',
44
+ match_requests_on: [:path] do
45
+
46
+ expect{
47
+ api_client.authenticate
48
+ }.to raise_error(SalsaLabs::Error)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "#authenticated?" do
55
+ it "returns the value of the instance variable @authenticated" do
56
+ api_client.instance_variable_set(:@authenticated, 123)
57
+
58
+ expect(api_client.authenticated?).to eq(123)
59
+ end
60
+ end
61
+
62
+ describe "#fetch" do
63
+ it "returns the body of the response from Salsa Labs for that API call" do
64
+ VCR.use_cassette 'get_objects/action',
65
+ match_requests_on: [:path] do
66
+
67
+ data = api_client.fetch('/api/getObjects.sjs', object: 'Action')
68
+
69
+ expect(data.gsub(/\n|\s{2,}/, "")).
70
+ to eq(salsa_get_objects_for_action_xml_response)
71
+ end
72
+ end
73
+ end
74
+
75
+ def salsa_get_objects_for_action_xml_response
76
+ File.read('spec/fixtures/getObjects.sjs_action.xml').gsub(/\n|\s{2,}/, '')
77
+ end
78
+
79
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe SalsaLabs::SalsaObject do
4
+
5
+ let(:attributes) do
6
+ {
7
+ "description" => "A depiction of a description",
8
+ "organization_key" => "456"
9
+ }
10
+ end
11
+
12
+ let(:salsa_object) { SalsaLabs::SalsaObject.new(attributes) }
13
+
14
+ describe "#attributes" do
15
+ it "returns the hash used to constuct the object" do
16
+ expect(salsa_object.attributes).to eq(attributes)
17
+ end
18
+ end
19
+
20
+ describe "#organization_key" do
21
+ it "returns the organization_key attribute as an integer" do
22
+ expect(salsa_object.organization_key).to eq(456)
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,20 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+
4
+ require 'salsa_labs'
5
+
6
+ require 'rspec/autorun'
7
+ require 'vcr'
8
+ require 'webmock'
9
+
10
+ WebMock.disable_net_connect!
11
+
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ end
15
+
16
+ VCR.configure do |c|
17
+ c.cassette_library_dir = 'spec/vcr_cassettes'
18
+ c.hook_into :faraday
19
+ c.hook_into :webmock
20
+ end
@@ -0,0 +1,45 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://hq-salsa.wiredforchange.com/api/authenticate.sjs?email=allison@example.com&password=password
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.8.8
12
+ cookie:
13
+ - ''
14
+ response:
15
+ status:
16
+ code: 200
17
+ message:
18
+ headers:
19
+ server:
20
+ - nginx/1.0.0
21
+ date:
22
+ - Sat, 28 Dec 2013 02:55:27 GMT
23
+ content-type:
24
+ - text/xml;charset=UTF-8
25
+ transfer-encoding:
26
+ - chunked
27
+ connection:
28
+ - keep-alive
29
+ keep-alive:
30
+ - timeout=20
31
+ set-cookie:
32
+ - JSESSIONID=67EBA60BFE7BCF73E2BA0B8E6F9592D0-n2; Path=/; Secure; HttpOnly,
33
+ hqtab_2=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT, READONLY_Short_Name="";
34
+ Expires=Thu, 01-Jan-1970 00:00:10 GMT, SRV=vweb213; path=/
35
+ requesturi:
36
+ - "/api/authenticate.sjs?email=allison@example.com&password=password"
37
+ cache-control:
38
+ - private
39
+ body:
40
+ encoding: UTF-8
41
+ string: "<?xml version=\"1.0\"?>\n\t\t\t<data organization_KEY=\"6120\">\n\t\t\t<message>Successful
42
+ Login</message>\n\t\t\t</data>"
43
+ http_version:
44
+ recorded_at: Sat, 28 Dec 2013 02:55:27 GMT
45
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,45 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://hq-salsa.wiredforchange.com/api/authenticate.sjs?email=allison%40example.com&password=password
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ User-Agent:
11
+ - Faraday v0.8.8
12
+ cookie:
13
+ - ''
14
+ response:
15
+ status:
16
+ code: 200
17
+ message:
18
+ headers:
19
+ server:
20
+ - nginx/1.0.0
21
+ date:
22
+ - Sat, 28 Dec 2013 02:56:00 GMT
23
+ content-type:
24
+ - text/xml;charset=UTF-8
25
+ transfer-encoding:
26
+ - chunked
27
+ connection:
28
+ - keep-alive
29
+ keep-alive:
30
+ - timeout=20
31
+ set-cookie:
32
+ - JSESSIONID=646F52AB13B1FCD5AA7B94A935B6E479-n3; Path=/; Secure; HttpOnly,
33
+ hqtab_2=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT, READONLY_Short_Name="";
34
+ Expires=Thu, 01-Jan-1970 00:00:10 GMT, SRV=vweb208; path=/
35
+ requesturi:
36
+ - "/api/authenticate.sjs?email=allison%40example.com&password=password"
37
+ cache-control:
38
+ - private
39
+ body:
40
+ encoding: UTF-8
41
+ string: "<?xml version=\"1.0\"?>\n\t\t\t<data>\n\t\t\t<error>Invalid login,
42
+ please try again.</error>\n\t\t\t</data>"
43
+ http_version:
44
+ recorded_at: Sat, 28 Dec 2013 02:56:00 GMT
45
+ recorded_with: VCR 2.8.0
metadata ADDED
@@ -0,0 +1,200 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: salsa_labs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Geoff Harcourt
8
+ - Allison Sheren
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-12-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: dotenv
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: faraday
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: httparty
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
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: nokogiri
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
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: fakeweb
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
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: rspec
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ - !ruby/object:Gem::Dependency
99
+ name: simplecov
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ - !ruby/object:Gem::Dependency
113
+ name: vcr
114
+ requirement: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :development
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: webmock
128
+ requirement: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :development
134
+ prerelease: false
135
+ version_requirements: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ description: A Ruby binding for the Salsa Labs (http://salsalabs.com) API.
141
+ email:
142
+ - asheren@gmail.com
143
+ executables: []
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - Gemfile
148
+ - Gemfile.lock
149
+ - LICENSE
150
+ - README.md
151
+ - Rakefile
152
+ - lib/salsa_labs/API_Client.rb
153
+ - lib/salsa_labs/action.rb
154
+ - lib/salsa_labs/actions_fetcher.rb
155
+ - lib/salsa_labs/salsa_object.rb
156
+ - lib/salsa_labs/version.rb
157
+ - salsa_labs.gemspec
158
+ - salsa_labs.rb
159
+ - spec/fixtures/getObjects.sjs_action.xml
160
+ - spec/salsa_labs/action_spec.rb
161
+ - spec/salsa_labs/actions_fetcher_spec.rb
162
+ - spec/salsa_labs/api_client_spec.rb
163
+ - spec/salsa_labs/salsa_object_spec.rb
164
+ - spec/spec_helper.rb
165
+ - spec/vcr_cassettes/successful_authentication.yml
166
+ - spec/vcr_cassettes/unsuccessful_authentication.yml
167
+ homepage: http://github.com/geoffharcourt/ruby-salsa_labs
168
+ licenses:
169
+ - LICENSE
170
+ metadata: {}
171
+ post_install_message:
172
+ rdoc_options: []
173
+ require_paths:
174
+ - lib
175
+ required_ruby_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ required_rubygems_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ requirements: []
186
+ rubyforge_project:
187
+ rubygems_version: 2.2.0
188
+ signing_key:
189
+ specification_version: 4
190
+ summary: Salsa Labs' API contains information about supporters, donations, and actions.
191
+ This gem faciliates pulling that information into a Ruby application.
192
+ test_files:
193
+ - spec/fixtures/getObjects.sjs_action.xml
194
+ - spec/salsa_labs/action_spec.rb
195
+ - spec/salsa_labs/actions_fetcher_spec.rb
196
+ - spec/salsa_labs/api_client_spec.rb
197
+ - spec/salsa_labs/salsa_object_spec.rb
198
+ - spec/spec_helper.rb
199
+ - spec/vcr_cassettes/successful_authentication.yml
200
+ - spec/vcr_cassettes/unsuccessful_authentication.yml