constant_contact 1.0.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 (34) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +56 -0
  3. data/lib/constant_contact.rb +13 -0
  4. data/lib/constant_contact/activity.rb +41 -0
  5. data/lib/constant_contact/base.rb +150 -0
  6. data/lib/constant_contact/campaign.rb +112 -0
  7. data/lib/constant_contact/contact.rb +82 -0
  8. data/lib/constant_contact/contact_event.rb +7 -0
  9. data/lib/constant_contact/email_address.rb +6 -0
  10. data/lib/constant_contact/formats.rb +3 -0
  11. data/lib/constant_contact/formats/atom_format.rb +78 -0
  12. data/lib/constant_contact/formats/html_encoded_format.rb +17 -0
  13. data/lib/constant_contact/list.rb +11 -0
  14. data/lib/constant_contact/member.rb +5 -0
  15. data/lib/constant_contact/version.rb +3 -0
  16. data/test/constant_contact/activity_test.rb +41 -0
  17. data/test/constant_contact/atom_format_test.rb +28 -0
  18. data/test/constant_contact/base_test.rb +85 -0
  19. data/test/constant_contact/contact_test.rb +135 -0
  20. data/test/constant_contact/list_test.rb +17 -0
  21. data/test/constant_contact/member_test.rb +25 -0
  22. data/test/constant_contact_test.rb +8 -0
  23. data/test/fixtures/all_contacts.xml +51 -0
  24. data/test/fixtures/contactlistscollection.xml +96 -0
  25. data/test/fixtures/contactlistsindividuallist.xml +30 -0
  26. data/test/fixtures/memberscollection.xml +763 -0
  27. data/test/fixtures/new_list.xml +16 -0
  28. data/test/fixtures/nocontent.xml +12 -0
  29. data/test/fixtures/service_document.xml +15 -0
  30. data/test/fixtures/single_contact_by_email.xml +34 -0
  31. data/test/fixtures/single_contact_by_id.xml +71 -0
  32. data/test/fixtures/single_contact_by_id_with_no_contactlists.xml +65 -0
  33. data/test/test_helper.rb +46 -0
  34. metadata +186 -0
@@ -0,0 +1,7 @@
1
+ module ConstantContact
2
+ class ContactEvent < Base
3
+ self.site += "/contacts/:contact_id"
4
+ end
5
+ end
6
+
7
+
@@ -0,0 +1,6 @@
1
+ # http://developer.constantcontact.com/doc/settingsemails
2
+ module ConstantContact
3
+ class EmailAddress < Base
4
+ self.element_name = 'settings/emailaddresses'
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ directory = File.expand_path(File.dirname(__FILE__))
2
+ require File.join(directory, 'formats','atom_format')
3
+ require File.join(directory, 'formats','html_encoded_format')
@@ -0,0 +1,78 @@
1
+ require 'rexml/document'
2
+ module ActiveResource
3
+ module Formats
4
+ module AtomFormat
5
+ extend self
6
+
7
+ def extension
8
+ "atom"
9
+ end
10
+
11
+ def mime_type
12
+ "application/atom+xml"
13
+ end
14
+
15
+ def encode(hash, options={})
16
+ hash.to_xml(options)
17
+ end
18
+
19
+ def decode(xml)
20
+ return [] if no_content?(xml)
21
+ result = Hash.from_xml(from_atom_data(xml))
22
+ is_collection?(xml) ? result['records'] : result.values.first
23
+ end
24
+
25
+
26
+ private
27
+
28
+ def from_atom_data(xml)
29
+ if is_collection?(xml)
30
+ return content_from_collection(xml)
31
+ else
32
+ return content_from_single_record(xml)
33
+ end
34
+ end
35
+
36
+ def no_content?(xml)
37
+ doc = REXML::Document.new(xml)
38
+ REXML::XPath.match(doc,'//content').size == 0
39
+ end
40
+
41
+ def is_collection?(xml)
42
+ doc = REXML::Document.new(xml)
43
+ REXML::XPath.match(doc,'//content').size > 1
44
+ end
45
+
46
+ def content_from_single_record(xml)
47
+ doc = REXML::Document.new(xml)
48
+ str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
49
+ REXML::XPath.each(doc, '//content') do |e|
50
+ content = e.children[1]
51
+ str << content.to_s
52
+ end
53
+ str
54
+ end
55
+
56
+ def content_from_collection(xml)
57
+ doc = REXML::Document.new(xml)
58
+ str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><records type=\"array\">"
59
+ REXML::XPath.each(doc, '//content') do |e|
60
+ content = e.children[1]
61
+ str << content.to_s
62
+ end
63
+ str << "</records>"
64
+ str
65
+ end
66
+
67
+ def content_from_member(xml)
68
+ doc = REXML::Document.new(xml)
69
+ str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
70
+ REXML::XPath.each(doc, '//content') do |e|
71
+ content = e.children[1].children
72
+ str << content.to_s
73
+ end
74
+ str
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,17 @@
1
+ module ActiveResource
2
+ module Formats
3
+ module HtmlEncodedFormat
4
+ extend self
5
+ def mime_type
6
+ "application/x-www-form-urlencoded"
7
+ end
8
+
9
+
10
+ def decode(xml)
11
+ {}
12
+ end
13
+
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module ConstantContact
2
+ class List < Base
3
+
4
+ # @@column_names = [:contact_count, :display_on_signup, :members, :name, :opt_in_default, :short_name, :sort_order]
5
+
6
+ def self.find_by_name(name)
7
+ lists = self.find :all
8
+ lists.find{|list| list.Name == name}
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module ConstantContact
2
+ class Member < Base
3
+ self.site += "/lists/:list_id"
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module ConstantContact
2
+ Version = '1.0.0'.freeze
3
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class Activity < Test::Unit::TestCase
4
+
5
+ context 'encode' do
6
+ setup do
7
+ @contacts = []
8
+ 3.times do |n|
9
+ @contacts << ConstantContact::Contact.new(:first_name => "Fred#{n}",
10
+ :last_name => "Test#{n}",
11
+ :email_address => "email#{n}@gmail.com")
12
+ end
13
+ @activity = ConstantContact::Activity.new(:activity_type => "SV_ADD")
14
+ @activity.contacts = @contacts
15
+ @list = ConstantContact::List.new
16
+ @list.stubs(:id).returns('http://api.constantcontact.com/ws/customers/joesflowers/lists/2')
17
+ @activity.lists = [@list]
18
+ end
19
+
20
+ should 'include activity type' do
21
+ assert_match(/activityType=SV_ADD/, @activity.encode)
22
+ end
23
+
24
+ should 'include contacts data' do
25
+ assert_match(/\&data\=Email\+Address\%2CFirst\+Name\%2CLast\+Name\%0A/, @activity.encode)
26
+ assert_match(/email0\%40gmail\.com\%2C\+Fred0\%2C\+Test0\%0A/, @activity.encode)
27
+ end
28
+
29
+ should 'include lists' do
30
+ assert_match(/Test2\&lists\=http\%3A\%2F\%2Fapi\.constantcontact\.com\%2Fws\%2Fcustomers\%2Fjoesflowers\%2Flists\%2F2/, @activity.encode)
31
+ end
32
+
33
+ end
34
+
35
+ context 'format' do
36
+ should 'be html encoded' do
37
+ assert_equal ActiveResource::Formats[:html_encoded], ConstantContact::Activity.connection.format
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class AtomFormatter
4
+ include ActiveResource::Formats::AtomFormat
5
+ end
6
+ class AtomFormatTest < Test::Unit::TestCase
7
+
8
+ context 'decode' do
9
+ should 'convert an xml collection into an array' do
10
+ c = AtomFormatter.new
11
+ assert_kind_of Array, c.decode(fixture_file('contactlistscollection.xml'))
12
+ end
13
+
14
+ should 'convert xml for a single record into a something' do
15
+ c = AtomFormatter.new
16
+ assert_kind_of Hash, c.decode(fixture_file('contactlistsindividuallist.xml'))
17
+ end
18
+
19
+ should 'return empty error if no content' do
20
+ c = AtomFormatter.new
21
+ assert_kind_of Array, c.decode(fixture_file('nocontent.xml'))
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+
28
+
@@ -0,0 +1,85 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ # require 'activeresource'
3
+ class BaseTest < Test::Unit::TestCase
4
+
5
+ # def test_should_use_site_prefix_and_credentials
6
+ # assert_equal 'https://baz%25foo:bar@api.constantcontact.com', ConstantContact::List.site.to_s
7
+ # end
8
+
9
+ def test_should_accept_setting_user
10
+ ConstantContact::List.api_key = 'api_key'
11
+ ConstantContact::List.user = 'david'
12
+ assert_equal('david', ConstantContact::List.user)
13
+ assert_equal('api_key%david', ConstantContact::List.connection.user)
14
+ end
15
+
16
+ def test_should_accept_setting_api_key
17
+ ConstantContact::List.api_key = 'david'
18
+ assert_equal('david', ConstantContact::List.api_key)
19
+ end
20
+
21
+
22
+ def test_should_accept_setting_password
23
+ ConstantContact::List.password = 'test123'
24
+ assert_equal('test123', ConstantContact::List.password)
25
+ assert_equal('test123', ConstantContact::List.connection.password)
26
+ end
27
+
28
+ def test_credentials_from_site_are_decoded
29
+ actor = Class.new(ConstantContact::Base)
30
+ actor.site = 'http://my%40email.com:%31%32%33@cinema'
31
+ assert_equal("my@email.com", actor.user)
32
+ assert_equal("123", actor.password)
33
+ end
34
+
35
+ def test_collection_name
36
+ assert_equal "lists", ConstantContact::List.collection_name
37
+ end
38
+
39
+ def test_collection_path
40
+ ConstantContact::Base.user = 'joesflowers'
41
+ assert_equal '/ws/customers/joesflowers/lists', ConstantContact::List.collection_path
42
+ end
43
+
44
+ def test_element_path
45
+ ConstantContact::Base.user = 'joesflowers'
46
+ assert_equal '/ws/customers/joesflowers/bases/1', ConstantContact::Base.element_path(1)
47
+ end
48
+
49
+ def test_should_use_site_prefix_and_credentials
50
+ ConstantContact::Base.user = "joesflowers"
51
+ ConstantContact::Base.password = "password"
52
+ ConstantContact::Base.api_key = "api_key"
53
+ assert_equal 'https://api.constantcontact.com/', ConstantContact::List.site.to_s
54
+ assert_equal 'https://api.constantcontact.com/lists/:list_id/', ConstantContact::Member.site.to_s
55
+ end
56
+
57
+
58
+ context 'find' do
59
+ setup do
60
+ ConstantContact::Base.user = "joesflowers"
61
+ ConstantContact::Base.password = "password"
62
+ ConstantContact::Base.api_key = "api_key"
63
+ stub_get('https://api_key%25joesflowers:password@api.constantcontact.com/ws/customers/joesflowers/lists', 'contactlistscollection.xml')
64
+ stub_get('https://api_key%25joesflowers:password@api.constantcontact.com/ws/customers/joesflowers/lists/1', 'contactlistsindividuallist.xml')
65
+ stub_get('https://api_key%25joesflowers:password@api.constantcontact.com/ws/customers/joesflowers/lists/1/members', 'memberscollection.xml')
66
+ end
67
+
68
+ should 'find one' do
69
+ list = ConstantContact::List.find(1)
70
+ assert_equal "General Interest", list.name
71
+ end
72
+
73
+ should 'find all' do
74
+ lists = ConstantContact::List.find(:all)
75
+ assert_equal 5, lists.size
76
+ assert_equal 'Clients', lists.last.name
77
+ end
78
+
79
+ should 'allow nested finds' do
80
+ members = ConstantContact::Member.find :all, :params => {:list_id => 1}
81
+ assert_equal 50, members.size
82
+ end
83
+ end
84
+
85
+ end
@@ -0,0 +1,135 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ContactTest < Test::Unit::TestCase
4
+
5
+ context 'class' do
6
+ setup do
7
+ ConstantContact::Base.user = "jonsflowers"
8
+ @contact = ConstantContact::Contact.new(:email_address => "jon@example.com",
9
+ :first_name => "jon",
10
+ :last_name => "smith")
11
+ end
12
+
13
+ should 'respond to encode' do
14
+ assert_respond_to ConstantContact::Contact.new, :encode
15
+ end
16
+
17
+ should 'call to_xml' do
18
+ @contact.expects(:to_xml)
19
+ @contact.encode
20
+ end
21
+ end
22
+
23
+ context 'setting accessible attributes' do
24
+ setup do
25
+ ConstantContact::Base.user = "jonsflowers"
26
+ @contact = ConstantContact::Contact.new(:email_address => "jon@example.com",
27
+ :first_name => "jon",
28
+ :last_name => "smith")
29
+ end
30
+
31
+ should 'returns nil when contact list has not been set' do
32
+ assert_equal nil, @contact.contact_lists
33
+ end
34
+ should 'permit assigning ids to the contact list' do
35
+ @contact.contact_lists = [1,2]
36
+ assert_equal [1,2], @contact.contact_lists
37
+ end
38
+ end
39
+
40
+ context 'to_xml' do
41
+ setup do
42
+ ConstantContact::Base.user = "jonsflowers"
43
+ @contact = ConstantContact::Contact.new(:email_address => "jon@example.com",
44
+ :first_name => "jon",
45
+ :last_name => "smith")
46
+ end
47
+
48
+ should 'have contact tag' do
49
+ assert_match /<Contact xmlns=\"http:\/\/ws.constantcontact.com\/ns\/1.0\/\"/, @contact.to_xml
50
+ assert_match /\<\/Contact\>/, @contact.to_xml
51
+ end
52
+
53
+ should 'have first_name' do
54
+ assert_match /<FirstName>/, @contact.to_xml
55
+ end
56
+
57
+ should 'list selected by default' do
58
+ assert_match /http:\/\/api.constantcontact.com\/ws\/customers\/jonsflowers\/lists\/1/, @contact.to_xml
59
+ end
60
+
61
+ should 'provide opt in select by default' do
62
+ assert_match /ACTION_BY_CUSTOMER/, @contact.to_xml
63
+ end
64
+
65
+ should 'include the default contact list when no lists are specified' do
66
+ assert_match /<ContactList id="/, @contact.to_xml
67
+ end
68
+
69
+ should 'include all contact lists configured' do
70
+ @contact.contact_lists = [1,2]
71
+ assert_equal [1,2], @contact.contact_lists
72
+ xml = @contact.to_xml
73
+ assert_equal 2, xml.scan(/<ContactList /).length, xml
74
+ assert_match /<ContactList id="#{Regexp.escape(@contact.list_url(1))}"/, xml
75
+ assert_match /<ContactList id="#{Regexp.escape(@contact.list_url(2))}"/, xml
76
+ end
77
+ end
78
+
79
+ context "find with query parameters" do
80
+ setup do
81
+ ConstantContact::Base.user = "joesflowers"
82
+ ConstantContact::Base.password = "password"
83
+ ConstantContact::Base.api_key = "api_key"
84
+ stub_get('https://api_key%25joesflowers:password@api.constantcontact.com/ws/customers/joesflowers/contacts/2', 'single_contact_by_id.xml')
85
+ stub_get('https://api_key%25joesflowers:password@api.constantcontact.com/ws/customers/joesflowers/contacts/3', 'single_contact_by_id_with_no_contactlists.xml')
86
+ end
87
+
88
+ should 'find contact with given id' do
89
+ assert_equal 'jon smith', ConstantContact::Contact.find(2).Name
90
+ end
91
+
92
+ should 'return an array of lists they are a member of' do
93
+ c = ConstantContact::Contact.find(2)
94
+ assert_equal [1], c.contact_lists
95
+ end
96
+ should 'return an empty array when no contact lists are present' do
97
+ c = ConstantContact::Contact.find(3)
98
+ assert_equal [], c.contact_lists
99
+ end
100
+
101
+ end
102
+
103
+ context "find with email in query parameters" do
104
+ setup do
105
+ ConstantContact::Base.user = "joesflowers"
106
+ ConstantContact::Base.password = "password"
107
+ ConstantContact::Base.api_key = "api_key"
108
+ stub_get('https://api_key%25joesflowers:password@api.constantcontact.com/ws/customers/joesflowers/contacts', 'all_contacts.xml')
109
+ stub_get('https://api_key%25joesflowers:password@api.constantcontact.com/ws/customers/joesflowers/contacts?email=jon%40example.com', 'single_contact_by_email.xml')
110
+ end
111
+
112
+ should 'find contact with email address' do
113
+ assert_equal 'smith, jon', ConstantContact::Contact.find(:first, :params => {:email => 'jon@example.com'}).Name
114
+ end
115
+
116
+ should 'return nil when asking for contact_lists' do
117
+ assert_equal nil, ConstantContact::Contact.find(:first, :params => {:email => 'jon@example.com'}).contact_lists
118
+ end
119
+
120
+ end
121
+
122
+ context 'list url' do
123
+ setup do
124
+ ConstantContact::Base.user = "joesflowers"
125
+ end
126
+ should 'apply the default id (1) to a new contact' do
127
+ c = ConstantContact::Contact.new(:email_address => "jon@example.com",
128
+ :first_name => "jon",
129
+ :last_name => "smith")
130
+ assert_equal 'http://api.constantcontact.com/ws/customers/joesflowers/lists/1', c.list_url
131
+ assert_equal 'http://api.constantcontact.com/ws/customers/joesflowers/lists/2', c.list_url(2)
132
+ end
133
+ end
134
+
135
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class ListTest < Test::Unit::TestCase
4
+
5
+ context "find by name" do
6
+ setup do
7
+ ConstantContact::List.user = "joesflowers"
8
+ ConstantContact::List.password = "password"
9
+ ConstantContact::List.api_key = "api_key"
10
+ stub_get('https://api_key%25joesflowers:password@api.constantcontact.com/ws/customers/joesflowers/lists', 'contactlistscollection.xml')
11
+ end
12
+
13
+ should 'find list for given name' do
14
+ assert_equal 'Clients', ConstantContact::List.find_by_name("Clients").name
15
+ end
16
+ end
17
+ end