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.
- data/MIT-LICENSE +20 -0
- data/README.md +56 -0
- data/lib/constant_contact.rb +13 -0
- data/lib/constant_contact/activity.rb +41 -0
- data/lib/constant_contact/base.rb +150 -0
- data/lib/constant_contact/campaign.rb +112 -0
- data/lib/constant_contact/contact.rb +82 -0
- data/lib/constant_contact/contact_event.rb +7 -0
- data/lib/constant_contact/email_address.rb +6 -0
- data/lib/constant_contact/formats.rb +3 -0
- data/lib/constant_contact/formats/atom_format.rb +78 -0
- data/lib/constant_contact/formats/html_encoded_format.rb +17 -0
- data/lib/constant_contact/list.rb +11 -0
- data/lib/constant_contact/member.rb +5 -0
- data/lib/constant_contact/version.rb +3 -0
- data/test/constant_contact/activity_test.rb +41 -0
- data/test/constant_contact/atom_format_test.rb +28 -0
- data/test/constant_contact/base_test.rb +85 -0
- data/test/constant_contact/contact_test.rb +135 -0
- data/test/constant_contact/list_test.rb +17 -0
- data/test/constant_contact/member_test.rb +25 -0
- data/test/constant_contact_test.rb +8 -0
- data/test/fixtures/all_contacts.xml +51 -0
- data/test/fixtures/contactlistscollection.xml +96 -0
- data/test/fixtures/contactlistsindividuallist.xml +30 -0
- data/test/fixtures/memberscollection.xml +763 -0
- data/test/fixtures/new_list.xml +16 -0
- data/test/fixtures/nocontent.xml +12 -0
- data/test/fixtures/service_document.xml +15 -0
- data/test/fixtures/single_contact_by_email.xml +34 -0
- data/test/fixtures/single_contact_by_id.xml +71 -0
- data/test/fixtures/single_contact_by_id_with_no_contactlists.xml +65 -0
- data/test/test_helper.rb +46 -0
- metadata +186 -0
@@ -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,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,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
|