just_giving 0.1.0 → 0.2.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.
Files changed (43) hide show
  1. data/Gemfile +8 -0
  2. data/README.md +40 -1
  3. data/just_giving.gemspec +58 -7
  4. data/lib/faraday/raise_http_4xx.rb +29 -0
  5. data/lib/faraday/raise_http_5xx.rb +28 -0
  6. data/lib/just_giving.rb +11 -2
  7. data/lib/just_giving/account.rb +43 -0
  8. data/lib/just_giving/api.rb +9 -0
  9. data/lib/just_giving/charity.rb +13 -0
  10. data/lib/just_giving/configuration.rb +59 -0
  11. data/lib/just_giving/connection.rb +28 -0
  12. data/lib/just_giving/donation.rb +17 -0
  13. data/lib/just_giving/error.rb +9 -0
  14. data/lib/just_giving/event.rb +17 -0
  15. data/lib/just_giving/fundraising.rb +51 -0
  16. data/lib/just_giving/request.rb +40 -0
  17. data/lib/just_giving/response.rb +9 -0
  18. data/lib/just_giving/search.rb +13 -0
  19. data/lib/just_giving/simple_donation_integration.rb +7 -3
  20. data/lib/just_giving/version.rb +1 -1
  21. data/test/fixtures/account_create_fail.json +1 -0
  22. data/test/fixtures/account_create_success.json +3 -0
  23. data/test/fixtures/account_list_all_pages.json +21 -0
  24. data/test/fixtures/charity_auth_success.json +5 -0
  25. data/test/fixtures/charity_get_success.json +1 -0
  26. data/test/fixtures/donation_status_success.json +7 -0
  27. data/test/fixtures/event_get_success.json +8 -0
  28. data/test/fixtures/event_pages_success.json +26 -0
  29. data/test/fixtures/fundraising_donations_success.json +1 -0
  30. data/test/fixtures/fundraising_get_page_success.json +1 -0
  31. data/test/fixtures/fundraising_pages_success.json +1 -0
  32. data/test/fixtures/fundraising_update_story_success.json +1 -0
  33. data/test/fixtures/search_success.json +1 -0
  34. data/test/helper.rb +29 -0
  35. data/test/test_account.rb +110 -0
  36. data/test/test_charity.rb +31 -0
  37. data/test/test_configuration.rb +37 -0
  38. data/test/test_donation.rb +26 -0
  39. data/test/test_event.rb +30 -0
  40. data/test/test_fundraising.rb +75 -0
  41. data/test/test_search.rb +32 -0
  42. metadata +139 -22
  43. data/lib/just_giving/config.rb +0 -7
@@ -0,0 +1,9 @@
1
+ module JustGiving
2
+ class Error < StandardError; end
3
+
4
+ class NotFound < Error; end
5
+
6
+ class InternalServerError < Error; end
7
+
8
+ class InvalidApplicationId < Error; end
9
+ end
@@ -0,0 +1,17 @@
1
+ module JustGiving
2
+ class Event < API
3
+ def initialize(id)
4
+ @id = id
5
+ end
6
+
7
+ # Get details for an event
8
+ def details
9
+ get("v1/event/#{@id}")
10
+ end
11
+
12
+ # Get all pages for an event
13
+ def pages
14
+ get("v1/event/#{@id}/pages")
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,51 @@
1
+ module JustGiving
2
+ class Fundraising < API
3
+ def initialize(short_name=nil)
4
+ @short_name = short_name
5
+ end
6
+
7
+ # Get all pages
8
+ def pages
9
+ get("v1/fundraising/pages", :basic_auth => true)
10
+ end
11
+
12
+ # Create a new fundraising page
13
+ def create(params)
14
+ put("v1/fundraising/pages", {:basic_auth => true}.merge(params))
15
+ end
16
+
17
+ # Check if a short name is registered
18
+ def short_name_registered?
19
+ begin
20
+ head("v1/fundraising/pages/#{@short_name}")
21
+ return true
22
+ rescue JustGiving::NotFound
23
+ return false
24
+ end
25
+ end
26
+
27
+ # Get a specific page
28
+ def page
29
+ get("v1/fundraising/pages/#{@short_name}")
30
+ end
31
+
32
+ # Get all donations per page
33
+ def donations(page=1, per_page=50)
34
+ get("v1/fundraising/pages/#{@short_name}/donations?pageNum=#{page}&page_size=#{per_page}",
35
+ :basic_auth => true)
36
+ end
37
+
38
+ # Update a pages story
39
+ def update_story(story)
40
+ post("v1/fundraising/pages/#{@short_name}", {:basic_auth => true}.merge({:storySupplement => story}))
41
+ end
42
+
43
+ def upload_image
44
+ # TODO
45
+ end
46
+
47
+ def suggest
48
+ # TODO
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,40 @@
1
+ module JustGiving
2
+ module Request
3
+ def get(path, options={})
4
+ request(:get, path, options)
5
+ end
6
+
7
+ def put(path, options={})
8
+ request(:put, path, options)
9
+ end
10
+
11
+ def head(path, options={})
12
+ request(:head, path, options)
13
+ end
14
+
15
+ def post(path, options={})
16
+ request(:post, path, options)
17
+ end
18
+
19
+ private
20
+
21
+ def request(method, path, options)
22
+ basic_auth = options.delete(:basic_auth)
23
+ response = connection(basic_auth).send(method) do |request|
24
+ case method.to_sym
25
+ when :get, :head
26
+ request.url(path, options)
27
+ when :put, :post
28
+ request.path = path
29
+ request.body = options unless options.empty?
30
+ end
31
+ end
32
+ case response.status
33
+ when 400 #Return errors if 400
34
+ JustGiving::Response.new(response.body)
35
+ else
36
+ response.body
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ module JustGiving
2
+ class Response
3
+ attr_accessor :errors
4
+ def initialize(errors)
5
+ @errors = []
6
+ errors.each{|e| @errors << Hashie::Mash.new(e)}
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module JustGiving
2
+ class Search < API
3
+ # Search charites
4
+ def search_charities(query, page=1, per_page=10)
5
+ get("v1/charity/search?q=#{query}&page=#{page}&pageSize=#{per_page}")
6
+ end
7
+
8
+ # Search events
9
+ def search_events(query, page=1, per_page=10)
10
+ get("v1/event/search?q=#{query}&page=#{page}&pageSize=#{per_page}")
11
+ end
12
+ end
13
+ end
@@ -2,13 +2,15 @@ require 'cgi'
2
2
 
3
3
  module JustGiving
4
4
  class SimpleDonationIntegration
5
+ # Returns url to link to a charity page
5
6
  def self.charity_page_url(short_name)
6
- "#{JustGiving::Config::BASE_URI}/#{short_name}/donate"
7
+ "#{JustGiving::Configuration::BASE_URI}/#{short_name}/donate"
7
8
  end
8
9
 
10
+ # Returns url for the donation page of a charity
9
11
  def self.charity_donation_url(charity_id, options={})
10
12
  options = self.parse_options(options)
11
- url = "#{JustGiving::Config::BASE_URI}/donation/direct/charity/#{charity_id}"
13
+ url = "#{JustGiving::Configuration::BASE_URI}/donation/direct/charity/#{charity_id}"
12
14
  url << self.options_to_query(options) if options.any?
13
15
  url
14
16
  end
@@ -17,15 +19,17 @@ module JustGiving
17
19
  alias :fundraising_page_url :charity_page_url
18
20
  end
19
21
 
22
+ # Returns url for the donation page of a fundraising
20
23
  def self.fundraising_donation_url(page_id, options={})
21
24
  options = self.parse_options(options)
22
- url = "#{JustGiving::Config::BASE_URI}/donation/sponsor/page/#{page_id}"
25
+ url = "#{JustGiving::Configuration::BASE_URI}/donation/sponsor/page/#{page_id}"
23
26
  url << self.options_to_query(options) if options.any?
24
27
  url
25
28
  end
26
29
 
27
30
  private
28
31
 
32
+ # Remove options we are not interested in
29
33
  def self.parse_options(options)
30
34
  available_options = [:amount, :frequency, :exit_url, :donation_id]
31
35
  options.delete_if{|key, value| !available_options.include?(key)}
@@ -1,7 +1,7 @@
1
1
  module JustGiving
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 1
4
+ MINOR = 2
5
5
  PATCH = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, PATCH].compact.join('.')
@@ -0,0 +1 @@
1
+ [{"id":"TitleNotSpecified","desc":"The Title field is required."},{"id":"FirstNameNotSpecified","desc":"The FirstName field is required."},{"id":"LastNameNotSpecified","desc":"The LastName field is required."},{"id":"EmailNotSpecified","desc":"The Email field is required."},{"id":"PasswordNotSpecified","desc":"The Password field is required."},{"id":"AcceptTermsAndConditionsNotSpecified","desc":"The AcceptTermsAndConditions field is required."},{"id":"InvalidTitleSpecified","desc":"Please provide your title"},{"id":"AddressNotSpecified","desc":"address is invalid or missing."}]
@@ -0,0 +1,3 @@
1
+ {
2
+ "email": "test@example.com"
3
+ }
@@ -0,0 +1,21 @@
1
+ [
2
+ {
3
+ "pageId": 1457423,
4
+ "pageTitle": "Alwyn’s page",
5
+ "pageStatus": "Active",
6
+ "pageShortName": "myJustGivingShortName",
7
+ "raisedAmount": 20.0,
8
+ "designId": 1,
9
+ "targetAmount": 1000.0,
10
+ "offlineDonations": 10.0,
11
+ "totalRaisedOnline": 50.00,
12
+ "giftAidPlusSupplement": 1.25,
13
+ "pageImages": [
14
+ "42010/65f56cc6-3535-436e-927d-eb9c24b82a6e.jpg"
15
+ ],
16
+ "eventName": "My Awesome Event",
17
+ "domain": "www.justgiving.com",
18
+ "smsCode": "PEJN76",
19
+ "charityId": 1
20
+ }
21
+ ]
@@ -0,0 +1,5 @@
1
+ {
2
+ "isValid": true,
3
+ "error": null,
4
+ "charityId": 1235
5
+ }
@@ -0,0 +1 @@
1
+ {"description":"This charity is for demo purposes only and enables you to build a sample sponsorship page. A 'real' charity would display its purpose and mission here, outlining its achievements and projects. Please do not donate to the Demo Charity! ","id":2050,"logoUrl":"demo.jpg","name":"The Demo Charity","pageShortName":"jgdemo","profilePageUrl":"http:\/\/www.justgiving.com\/jgdemo","registrationNumber":"123456","websiteUrl":"http:\/\/www.democharity.co.uk","smsShortName":"The Demo Charity","mobileAppeals":[{"name":"STEV22-test","smsCode":"TESS22"}]}
@@ -0,0 +1,7 @@
1
+ {
2
+ "ref": "my-sdi-ref",
3
+ "donationId": 1234,
4
+ "donationRef": "35626",
5
+ "status": "Accepted",
6
+ "amount": 2.00
7
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "name": "Playing Mario for 48 hours for charity",
3
+ "description": "Playing Mario for charity",
4
+ "id": 12356,
5
+ "completionDate": "\/Date(1345213305272+0100)\/",
6
+ "expiryDate": "\/Date(1345213305272+0100)\/",
7
+ "startDate": "\/Date(1313763705272+0100)\/"
8
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "eventId": 1234,
3
+ "totalFundraisingPages": 1,
4
+ "totalPages": 1,
5
+ "fundraisingPages": [
6
+ {
7
+ "pageId": 1457423,
8
+ "pageTitle": "My Fundraising Page!",
9
+ "pageStatus": "Active",
10
+ "pageShortName": "myJustGivingShortName",
11
+ "raisedAmount": 20.0,
12
+ "designId": 1,
13
+ "targetAmount": 1000.0,
14
+ "offlineDonations": 10.0,
15
+ "totalRaisedOnline": 50.00,
16
+ "giftAidPlusSupplement": 1.25,
17
+ "pageImages": [
18
+ "42010/65f56cc6-3535-436e-927d-eb9c24b82a6e.jpg"
19
+ ],
20
+ "eventName": "My Awesome Event",
21
+ "domain": "www.justgiving.com",
22
+ "smsCode": "PEJN76",
23
+ "charityId": 1
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1 @@
1
+ {"donations":[],"id":"test","pagination":{"pageNumber":1,"pageSizeRequested":25,"pageSizeReturned":0,"totalPages":1}}
@@ -0,0 +1 @@
1
+ {"activityId":"512239","activityType":1,"branding":{"buttonColour":"00A246","buttonTextColour":"FFFFFF","headerTextColour":"005C46","thermometerBackgroundColour":"005C46","thermometerFillColour":"00A246","thermometerTextColour":"FFFFFF"},"charity":{"description":"Macmillan Cancer Support improves the lives of people affected by cancer. We provide practical, medical, emotional and financial support and push for better cancer care. One in three of us will get cancer. Two million of us are living with it. We are all affected by cancer. We can all help. We are Macmillan.","logoUrl":"macmillan_logo_large.gif","name":"Macmillan Cancer Support","profilePageUrl":null,"registrationNumber":"261017"},"currencySymbol":"£","domain":"v3.staging.justgiving.com","eventDate":"\/Date(1315090800000+0100)\/","eventName":"Great Scottish Run 2011","expiryDate":"\/Date(1322956800000+0000)\/","fundraisingTarget":"0.00","grandTotalRaisedExcludingGiftAid":"0.0000","image":{"caption":"","url":"Stock\/oldtrainers.jpg"},"imageCount":"1","media":{"images":[{"caption":"","url":"Stock\/oldtrainers.jpg"}]},"owner":"test","pageId":"2938879","pageShortName":"test","showEventDate":"True","showExpiryDate":"False","smsCode":"TPNP50","status":"Active","story":"<p class=\"iphone-update\">Updated on Aug 17th 2011 at 1:46 PM from the JustGiving API<\/p><p>test<\/p><p>Thanks for taking the time to visit my JustGiving page.<\/p><p>Donating through JustGiving is simple, fast and totally secure. Your details are safe with JustGiving – they’ll never sell them on or send unwanted emails. Once you donate, they’ll send your money directly to the charity and make sure Gift Aid is reclaimed on every eligible donation by a UK taxpayer. So it’s the most efficient way to donate - I raise more, whilst saving time and cutting costs for the charity.<\/p><p>So please dig deep and donate now.<\/p>","title":"thomas's page","totalEstimatedGiftAid":"0","totalRaisedOffline":"0.0000","totalRaisedOnline":"0","totalRaisedPercentageOfFundraisingTarget":"0"}
@@ -0,0 +1 @@
1
+ [{"designId":1,"domain":"v3.staging.justgiving.com","eventName":"Event: Great Scottish Run 2011, Fundraiser: Macmillan Cancer Support, Revenue Stream: Macmillan - Donations & other ad hoc Events","giftAidPlusSupplement":0,"offlineDonations":0.0000,"pageId":2938879,"pageImages":["Stock\/oldtrainers.jpg"],"pageShortName":"test","pageStatus":"Active","pageTitle":"thomas's page","raisedAmount":0.0000,"targetAmount":0.0000,"totalRaisedOnline":0,"smsCode":"TPNP50","charityId":2116}]
@@ -0,0 +1 @@
1
+ {"charitySearchResults":[{"charityId":"311","description":"The Motor Neurone Disease (MND) Association is the only national\u000aorganisation in England, Wales and Northern Ireland dedicated to the\u000asupport of people with MND and those who care for them.\u000a\u000a\u000a\u000aOur mission is to fund and promote research to bring about an end to\u000aMND. Until then we will do all that we can to enable everyone with MND\u000ato receive the best care, achieve the highest quality of life possible,\u000aand die with dignity. We will also do all that we can to support the\u000afamilies and carers of people with MND.\u000a\u000a\u000a\u000aOur vision is of a world free of MND.","logoFileName":"\/Utils\/imaging.ashx?imageType=charitybrandinglogo&img=73debe79-18c9-4ab2-a98a-33835da5145f.jpg&width=120&height=120","name":"Motor Neurone Disease Association","registrationNumber":"294354"}],"next":{"rel":"http:\/\/api.staging.justgiving.com\/77253a18\/v1\/charity\/search?q=test&page=1&pagesize=1","uri":"http:\/\/api.staging.justgiving.com\/77253a18\/v1\/charity\/search?q=test&page=2&pagesize=1","type":"text\/xml"},"numberOfHits":100,"prev":null,"query":"test","sugguestedQuery":null,"totalPages":100}
data/test/helper.rb CHANGED
@@ -8,11 +8,40 @@ rescue Bundler::BundlerError => e
8
8
  exit e.status_code
9
9
  end
10
10
  require 'test/unit'
11
+ require 'webmock/test_unit'
11
12
  require 'shoulda'
12
13
 
13
14
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
15
  $LOAD_PATH.unshift(File.dirname(__FILE__))
15
16
  require 'just_giving'
16
17
 
18
+ def stub_get(path, basic_auth=nil)
19
+ stub_request(:get, make_url(path, basic_auth))
20
+ end
21
+
22
+ def stub_put(path, basic_auth=nil)
23
+ stub_request(:put, make_url(path, basic_auth))
24
+ end
25
+
26
+ def stub_post(path, basic_auth=nil)
27
+ stub_request(:post, make_url(path, basic_auth))
28
+ end
29
+
30
+ def stub_head(path)
31
+ stub_request(:head, JustGiving::Configuration.api_endpoint + path)
32
+ end
33
+
34
+ def make_url(path, basic_auth)
35
+ if basic_auth
36
+ JustGiving::Configuration.api_endpoint.gsub('https://', "https://#{basic_auth}@") + path
37
+ else
38
+ JustGiving::Configuration.api_endpoint + path
39
+ end
40
+ end
41
+
42
+ def fixture(file)
43
+ File.new(File.expand_path("../fixtures", __FILE__) + '/' + file)
44
+ end
45
+
17
46
  class Test::Unit::TestCase
18
47
  end
@@ -0,0 +1,110 @@
1
+ require 'helper'
2
+
3
+ class TestAccount < Test::Unit::TestCase
4
+ def setup
5
+ JustGiving::Configuration.application_id = '2345'
6
+ end
7
+
8
+ context 'Getting pages' do
9
+ should 'get pages for account' do
10
+ stub_get('/v1/account/test@example.com/pages').with(:headers => {'Accept'=>'application/json'}).to_return(
11
+ :body => fixture('account_list_all_pages.json'),
12
+ :headers => {:content_type => 'application/json; charset=utf-8'})
13
+ account = JustGiving::Account.new('test@example.com')
14
+ pages = account.pages
15
+ assert_equal 'Alwyn’s page', pages.first['pageTitle']
16
+ assert_equal 'Active', pages.first['pageStatus']
17
+ assert_equal 1, pages.first['designId']
18
+ end
19
+
20
+ should 'raise 404 on account not found' do
21
+ stub_get('/v1/account/test@example.com/pages').to_raise(JustGiving::NotFound)
22
+ account = JustGiving::Account.new('test@example.com')
23
+ assert_raise JustGiving::NotFound do
24
+ account.pages
25
+ end
26
+ end
27
+ end
28
+
29
+ context 'Creating account' do
30
+ should 'create account successfully' do
31
+ stub_put('/v1/account').with({'Accept'=>'application/json', 'Content-Length'=>'0'}).to_return(
32
+ :body => fixture('account_create_success.json'),
33
+ :headers => {:content_type => 'application/json; charset=utf-8'})
34
+ account = JustGiving::Account.new.create({:registration => {:email => 'test@example.com'}})
35
+ assert_equal 'test@example.com', account["email"]
36
+ end
37
+
38
+ should 'not create account with bad params' do
39
+ stub_put('/v1/account').to_return(:body => fixture('account_create_fail.json'),
40
+ :headers => {:content_type => 'text/xml; charset=utf-8'}, :status => 400)
41
+ account = JustGiving::Account.new.create({})
42
+ assert account.errors
43
+ end
44
+ end
45
+
46
+ context 'Validate account' do
47
+ should 'return invalid account' do
48
+ stub_post('/v1/account/validate').with({'Accept'=>'application/json'}).to_return(
49
+ :body => "{\"consumerId\":0,\"isValid\":false}", :headers => {:content_type => 'application/json; charset=utf-8'})
50
+ account = JustGiving::Account.new.validate(:email => 'test@example.com', :password => 'secret')
51
+ assert !account["isValid"]
52
+ end
53
+
54
+ should 'return valid account' do
55
+ stub_post('/v1/account/validate').with({'Accept'=>'application/json'}).to_return(
56
+ :body => "{\"consumerId\":1,\"isValid\":true}", :headers => {:content_type => 'application/json; charset=utf-8'})
57
+ account = JustGiving::Account.new.validate(:email => 'test@example.com', :password => 'secret')
58
+ assert account["isValid"]
59
+ assert_equal 1, account["consumerId"]
60
+ end
61
+ end
62
+
63
+ context 'Checking if an email is available' do
64
+ should 'return email is not available' do
65
+ stub_head('/v1/account/test@example.com').with({'Accept'=>'application/json'}).to_return(
66
+ :status => 200, :headers => {:content_type => 'application/json; charset=utf-8'})
67
+ assert !JustGiving::Account.new('test@example.com').available?
68
+ end
69
+
70
+ should 'return email is available' do
71
+ stub_head('/v1/account/test@example.com').with({'Accept'=>'application/json'}).to_return(
72
+ :status => 404, :headers => {:content_type => 'application/json; charset=utf-8'})
73
+ assert JustGiving::Account.new('test@example.com').available?
74
+ end
75
+ end
76
+
77
+ context 'Changing password' do
78
+ should 'change password' do
79
+ stub_post('/v1/account/changePassword').with({'Accept'=>'application/json'}).to_return(
80
+ :body => "{\"success\": true}", :headers => {:content_type => 'application/json; charset=utf-8'})
81
+ response = JustGiving::Account.new.change_password(:emailAddress => 'test@example.com', :newPassword => 'secret',
82
+ :currentPassword => 'password')
83
+ assert response["success"]
84
+ end
85
+
86
+ should 'not change password' do
87
+ stub_post('/v1/account/changePassword').with({'Accept'=>'application/json'}).to_return(
88
+ :body => "{\"success\": false}", :headers => {:content_type => 'application/json; charset=utf-8'})
89
+ response = JustGiving::Account.new.change_password(:emailAddress => 'test@example.com', :newPassword => 'secret',
90
+ :currentPassword => 'password')
91
+ assert !response["success"]
92
+ end
93
+ end
94
+
95
+ context 'Password reminder' do
96
+ should 'send password reminder' do
97
+ stub_get('/v1/account/test@example.com/requestpasswordreminder').with({'Accept'=>'application/json'}).to_return(
98
+ :status => 200, :headers => {:content_type => 'application/json; charset=utf-8'})
99
+ assert JustGiving::Account.new('test@example.com').password_reminder
100
+ end
101
+
102
+ should 'not sent password reminder' do
103
+ stub_get('/v1/account/test@example.com/requestpasswordreminder').with({'Accept'=>'application/json'}).to_return(
104
+ :status => 400, :body => "[{\"id\":\"AccountNotFound\",\"desc\":\"An account with that email address could not be found\"}",
105
+ :headers => {:content_type => 'application/json; charset=utf-8'})
106
+ response = JustGiving::Account.new('test@example.com').password_reminder
107
+ assert response.errors
108
+ end
109
+ end
110
+ end