cupid 0.2.4 → 0.3.2

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.
@@ -0,0 +1,45 @@
1
+ describe Cupid::Response::Format, '.apply' do
2
+ def apply(data)
3
+ described_class.apply data
4
+ end
5
+
6
+ it 'should return hash with original data' do
7
+ simple_data = { :a => 1 }
8
+ apply(simple_data).should include :a => 1
9
+ end
10
+
11
+ it 'should rename specified fields' do
12
+ described_class::RENAME[:old] = :new
13
+ data_with_renaming = { :old => 33 }
14
+ apply(data_with_renaming).should include :new => 33
15
+ end
16
+
17
+ it 'should delete ignore fields' do
18
+ described_class::IGNORE << :extra
19
+ data_with_deletion = { :extra => 103 }
20
+ apply(data_with_deletion).should_not include :extra
21
+ end
22
+
23
+ it 'should delete empty parents' do
24
+ data_with_empty_parent = { :parent_data => { :id => '0' }}
25
+ apply(data_with_empty_parent).should_not include :parent_data
26
+ end
27
+
28
+ context 'contains nested data' do
29
+ it 'should extract nested object to the top level' do
30
+ nested_data = { :a => 1, :object => { :b => 2 }}
31
+ apply(nested_data).should include :a => 1, :b => 2
32
+ end
33
+
34
+ it 'should use new_id from nested definition' do
35
+ new_nested_data = { :object => { :new_id => 24 }}
36
+ apply(new_nested_data).should include :id => 24
37
+ end
38
+
39
+ it 'should delete ignored fields' do
40
+ described_class::IGNORE << :nested_extra
41
+ nested_data_with_deletion = { :nexted_extra => 17 }
42
+ apply(nested_data_with_deletion).should_not include :nested_extra
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,23 @@
1
+ describe Cupid::Response::Object do
2
+ subject { described_class.new data }
3
+
4
+ describe 'accessor for attributes' do
5
+ let(:data) {{ :foo => :bar }}
6
+
7
+ it { subject[:foo].should == :bar }
8
+ end
9
+
10
+ context 'direct accessors' do
11
+ let(:data) {{ :id => 42, :type => 'Email' }}
12
+
13
+ its(:id) { should == 42 }
14
+ its(:type) { should == 'Email' }
15
+ end
16
+
17
+ context 'gyoku compatibility' do
18
+ let(:id) { 77 }
19
+ let(:data) {{ :id => id }}
20
+
21
+ it { Gyoku.xml(:object => subject).should == "<Object>#{id}</Object>" }
22
+ end
23
+ end
@@ -0,0 +1,12 @@
1
+ describe Cupid::Retrieve do
2
+ subject { Cupid::Test }
3
+
4
+ its(:folders) { should be }
5
+ its(:emails) { should be }
6
+ its(:lists) { should be }
7
+ its(:deliveries) { should be }
8
+ its(:ui_folders) { should be }
9
+ its(:ui_emails) { should be }
10
+
11
+ it { subject.emails('unexisting name').should == [] }
12
+ end
@@ -0,0 +1,22 @@
1
+ describe Cupid::Server do
2
+ subject { Cupid::Server.new 'account' }
3
+
4
+ its(:account) { 'account' }
5
+
6
+ context '#input' do
7
+ let(:input) { subject.input action }
8
+
9
+ context '#for :get_system_status action' do
10
+ let(:action) { :get_system_status }
11
+ let(:tag_name) { 'SystemStatusRequestMsg' }
12
+
13
+ it { input.should == [tag_name, :xmlns => Cupid::NAMESPACE] }
14
+ end
15
+
16
+ context '#for :unexisting action' do
17
+ let(:action) { :unexisting }
18
+
19
+ it { expect { input }.to raise_error }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ describe Cupid do
2
+ subject { Cupid.new 'bob', 'x123', 42 }
3
+
4
+ its(:client) { should be }
5
+ its('client.wsse.username') { should == 'bob' }
6
+ its('client.wsse.password') { should == 'x123' }
7
+ its('server.account') { should == 42 }
8
+ end
@@ -0,0 +1,11 @@
1
+ require 'cupid'
2
+
3
+ Savon.log = false
4
+ HTTPI.log = false
5
+
6
+ test_credentials = YAML.load_file('.test_account')
7
+ Cupid::Test = Cupid.new *test_credentials
8
+
9
+ RSpec.configure do |config|
10
+ config.mock_with :rspec
11
+ end
metadata CHANGED
@@ -1,127 +1,131 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: cupid
3
- version: !ruby/object:Gem::Version
4
- hash: 31
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.2
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 2
9
- - 4
10
- version: 0.2.4
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - gazay
9
+ - brainopia
14
10
  autorequire:
15
11
  bindir: bin
16
12
  cert_chain: []
17
-
18
- date: 2011-09-28 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
13
+ date: 2012-02-17 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
21
16
  name: builder
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &70340244020260 !ruby/object:Gem::Requirement
24
18
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 15
29
- segments:
30
- - 2
31
- - 1
32
- - 2
33
- version: 2.1.2
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
34
23
  type: :runtime
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: nokogiri
38
24
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: *70340244020260
26
+ - !ruby/object:Gem::Dependency
27
+ name: nokogiri
28
+ requirement: &70340244012760 !ruby/object:Gem::Requirement
40
29
  none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 5
45
- segments:
46
- - 1
47
- - 4
48
- - 1
49
- version: 1.4.1
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1'
50
34
  type: :runtime
51
- version_requirements: *id002
52
- - !ruby/object:Gem::Dependency
53
- name: savon
54
35
  prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
36
+ version_requirements: *70340244012760
37
+ - !ruby/object:Gem::Dependency
38
+ name: savon
39
+ requirement: &70340244012160 !ruby/object:Gem::Requirement
56
40
  none: false
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- hash: 59
61
- segments:
62
- - 0
63
- - 9
64
- - 0
65
- version: 0.9.0
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: '0.9'
66
45
  type: :runtime
67
- version_requirements: *id003
68
- description: Send love, not war. This version of cupid can only work with ET SOAP API with s4.
69
- email:
46
+ prerelease: false
47
+ version_requirements: *70340244012160
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ requirement: &70340244011580 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: '2'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *70340244011580
59
+ description: Send love, not war. This version of cupid works with ET SOAP API s4.
60
+ email:
70
61
  - gazay@evilmartians.com
71
62
  executables: []
72
-
73
63
  extensions: []
74
-
75
64
  extra_rdoc_files: []
76
-
77
- files:
65
+ files:
66
+ - .gitignore
67
+ - .rspec
78
68
  - Gemfile
79
- - Gemfile.lock
80
69
  - README.md
81
70
  - Rakefile
82
71
  - cupid.gemspec
83
72
  - lib/cupid.rb
84
- - lib/cupid/configuration.rb
85
- - lib/cupid/methods.rb
86
- - lib/cupid/methods/email.rb
87
- - lib/cupid/methods/list.rb
88
- - lib/cupid/methods/subscriber.rb
89
- - lib/cupid/session.rb
73
+ - lib/cupid/create.rb
74
+ - lib/cupid/delete.rb
75
+ - lib/cupid/gyoku.rb
76
+ - lib/cupid/response.rb
77
+ - lib/cupid/response/caster.rb
78
+ - lib/cupid/response/data.rb
79
+ - lib/cupid/response/data_folder.rb
80
+ - lib/cupid/response/format.rb
81
+ - lib/cupid/response/object.rb
82
+ - lib/cupid/retrieve.rb
83
+ - lib/cupid/schedule.rb
84
+ - lib/cupid/server.rb
85
+ - lib/cupid/update.rb
90
86
  - lib/cupid/version.rb
91
- - spec/cupid/cupid_spec.rb
92
- - tmp/dancing_with_ET.rb
93
- homepage: ""
87
+ - spec/cupid/create_spec.rb
88
+ - spec/cupid/delete_spec.rb
89
+ - spec/cupid/response/caster_spec.rb
90
+ - spec/cupid/response/data_spec.rb
91
+ - spec/cupid/response/format_spec.rb
92
+ - spec/cupid/response/object_spec.rb
93
+ - spec/cupid/retrieve_spec.rb
94
+ - spec/cupid/server_spec.rb
95
+ - spec/cupid_spec.rb
96
+ - spec/spec_helper.rb
97
+ homepage: http://github.com/evilmartians/cupid
94
98
  licenses: []
95
-
96
99
  post_install_message:
97
100
  rdoc_options: []
98
-
99
- require_paths:
101
+ require_paths:
100
102
  - lib
101
- required_ruby_version: !ruby/object:Gem::Requirement
103
+ required_ruby_version: !ruby/object:Gem::Requirement
102
104
  none: false
103
- requirements:
104
- - - ">="
105
- - !ruby/object:Gem::Version
106
- hash: 3
107
- segments:
108
- - 0
109
- version: "0"
110
- required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
110
  none: false
112
- requirements:
113
- - - ">="
114
- - !ruby/object:Gem::Version
115
- hash: 3
116
- segments:
117
- - 0
118
- version: "0"
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
119
115
  requirements: []
120
-
121
- rubyforge_project: cupid
122
- rubygems_version: 1.8.6
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.15
123
118
  signing_key:
124
119
  specification_version: 3
125
120
  summary: Create, organize and send emails through Exact Target SOAP API
126
- test_files:
127
- - spec/cupid/cupid_spec.rb
121
+ test_files:
122
+ - spec/cupid/create_spec.rb
123
+ - spec/cupid/delete_spec.rb
124
+ - spec/cupid/response/caster_spec.rb
125
+ - spec/cupid/response/data_spec.rb
126
+ - spec/cupid/response/format_spec.rb
127
+ - spec/cupid/response/object_spec.rb
128
+ - spec/cupid/retrieve_spec.rb
129
+ - spec/cupid/server_spec.rb
130
+ - spec/cupid_spec.rb
131
+ - spec/spec_helper.rb
@@ -1,37 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- cupid (0.0.8)
5
- builder (>= 2.1.2)
6
- nokogiri (>= 1.4.1)
7
- savon (>= 0.9.0)
8
-
9
- GEM
10
- remote: http://rubygems.org/
11
- specs:
12
- akami (1.0.0)
13
- gyoku (>= 0.4.0)
14
- builder (3.0.0)
15
- gyoku (0.4.4)
16
- builder (>= 2.1.2)
17
- httpi (0.9.5)
18
- rack
19
- nokogiri (1.5.0)
20
- nori (1.0.2)
21
- rack (1.3.3)
22
- savon (0.9.7)
23
- akami (~> 1.0)
24
- builder (>= 2.1.2)
25
- gyoku (>= 0.4.0)
26
- httpi (~> 0.9)
27
- nokogiri (>= 1.4.0)
28
- nori (~> 1.0)
29
- wasabi (~> 2.0)
30
- wasabi (2.0.0)
31
- nokogiri (>= 1.4.0)
32
-
33
- PLATFORMS
34
- ruby
35
-
36
- DEPENDENCIES
37
- cupid!
@@ -1,19 +0,0 @@
1
- require 'erb'
2
- require 'uri'
3
- require 'savon'
4
- require 'builder'
5
- require 'nokogiri'
6
- require 'cupid/session'
7
-
8
- include(ERB::Util)
9
-
10
- module Cupid
11
- module Configuration
12
- attr_accessor(
13
- :username,
14
- # :api_type, #now it's only soap s4. But i want MOAR
15
- :password,
16
- :account
17
- )
18
- end
19
- end
@@ -1,3 +0,0 @@
1
- require("cupid/methods/email")
2
- require("cupid/methods/subscriber")
3
- require("cupid/methods/list")
@@ -1,215 +0,0 @@
1
- module Cupid
2
- class Session
3
- def retrieve_email_folders(account=nil, properties=nil)
4
- account ||= @account
5
- properties ||= ['ID', 'Name', 'ParentFolder.ID', 'ParentFolder.Name']
6
- filters = '<Filter xsi:type="SimpleFilterPart">' +
7
- '<Property>ContentType</Property>' +
8
- '<SimpleOperator>like</SimpleOperator>' +
9
- '<Value>email</Value>' +
10
- '</Filter>'
11
-
12
- soap_body = build_retrieve(account.to_s, 'DataFolder', properties, filters)
13
- response = build_request('Retrieve', 'RetrieveRequestMsg', soap_body)
14
- response = Nokogiri::XML(response.http.body).remove_namespaces!
15
- all_folders = response.css('Results').map{|f| {f.css('Name').to_a.map(&:text).join('/') => f.css('ID')[0].text}}
16
- end
17
-
18
- def retrieve_email_copies(name, account=nil, properties=nil)
19
- account ||= @account
20
- properties ||= ['ID', 'Name']
21
- filters = '<Filter xsi:type="SimpleFilterPart">' +
22
- '<Property>Name</Property>' +
23
- '<SimpleOperator>like</SimpleOperator>' +
24
- '<Value>' + name + '</Value>' +
25
- '</Filter>'
26
-
27
- soap_body = build_retrieve(account.to_s, 'Email', properties, filters)
28
- response = build_request('Retrieve', 'RetrieveRequestMsg', soap_body)
29
- response = Nokogiri::XML(response.http.body).remove_namespaces!
30
- all_copies = response.css('Results').map{|f| {f.css('Name').to_a.map(&:text).join('/') => f.css('ID')[0].text}}
31
- end
32
-
33
- def retrieve_emails_from_folder(folder, account=nil, properties=nil)
34
- account ||= @account
35
- properties ||= ['ID', 'Name']
36
- filters = '<Filter xsi:type="SimpleFilterPart">' +
37
- '<Property>CategoryID</Property>' +
38
- '<SimpleOperator>equals</SimpleOperator>' +
39
- '<Value>' + folder + '</Value>' +
40
- '</Filter>'
41
-
42
- soap_body = build_retrieve(account.to_s, 'Email', properties, filters)
43
- response = build_request('Retrieve', 'RetrieveRequestMsg', soap_body)
44
- response = Nokogiri::XML(response.http.body).remove_namespaces!
45
- all_copies = response.css('Results').map{|f| {f.css('Name').to_a.map(&:text).join('/') => f.css('ID')[0].text}}
46
- end
47
-
48
- def create_email(subject, body, *args)
49
- soap_body = prepare_email(subject, body, args)
50
-
51
- response = build_request('Create', 'CreateRequest', soap_body)
52
- response = Nokogiri::XML(response.http.body).remove_namespaces!
53
- created_email_id = response.css('NewID').text
54
- end
55
-
56
- def create_folder(title, *args)
57
- soap_body = prepare_folder(title, args)
58
-
59
- response = build_request('Create', 'CreateRequest', soap_body)
60
- response = Nokogiri::XML(response.http.body).remove_namespaces!
61
- created_folder_id = response.css('NewID').text
62
- end
63
-
64
- def send_email_to_list(email_id, list_id, account=nil)
65
- soap_body = prepare_send(email_id, list_id, account)
66
-
67
- response = build_request('Create', 'CreateRequest', soap_body)
68
- response = Nokogiri::XML(response.http.body).remove_namespaces!
69
- created_send_id = response.css('NewID').text
70
- end
71
-
72
- def create_emails(subject_bodies, *args)
73
- soap_body = ''
74
- subject_bodies.each{ |subject, body| soap_body += prepare_email(subject, body, args) }
75
-
76
- response = build_request('Create', 'CreateRequest', soap_body)
77
- response = Nokogiri::XML(response.http.body).remove_namespaces!
78
- response.css('Results').map{ |f| f.css('NewID').text }
79
- end
80
-
81
- def create_folders(titles, *args)
82
- soap_body = titles.map{ |title| prepare_folder(title, args) }.join('')
83
-
84
- response = build_request('Create', 'CreateRequest', soap_body)
85
- response = Nokogiri::XML(response.http.body).remove_namespaces!
86
- response.css('Results').map{ |f| f.css('NewID').text }
87
- end
88
-
89
- def send_emails_to_lists(emails_lists, account=nil)
90
- soap_body = ''
91
- emails_lists.each{ |email_id, list_id| soap_body += prepare_send(email_id, list_id, account) }
92
-
93
- response = build_request('Create', 'CreateRequest', soap_body)
94
- response = Nokogiri::XML(response.http.body).remove_namespaces!
95
- response.css('Results').map{ |f| f.css('NewID').text }
96
- end
97
-
98
- def delete_email(email_id, account=nil)
99
- soap_body = prepare_delete_email(email_id, account)
100
-
101
- response = build_request('Delete', 'DeleteRequest', soap_body)
102
- response = Nokogiri::XML(response.http.body).remove_namespaces!
103
- response.css('Results').css('StatusCode').text == 'OK'
104
- end
105
-
106
- def delete_emails(emails, account=nil)
107
- soap_body = emails.map{ |email_id| prepare_delete_email(email_id, account) }.join('')
108
-
109
- response = build_request('Delete', 'DeleteRequest', soap_body)
110
- response = Nokogiri::XML(response.http.body).remove_namespaces!
111
- response.css('Results').map{ |f| f.css('StatusCode').text == 'OK' }
112
- end
113
-
114
- private
115
-
116
- def prepare_email(subject, body, args)
117
- options = args.extract_options!
118
- options[:subject] = CGI.escapeHTML subject.to_s
119
- options[:body] = CGI.escapeHTML body.to_s
120
- options[:client_id] ||= @account
121
-
122
- options[:email_type] ||= 'HTML'
123
- options[:is_html_paste] ||= 'true' # ??
124
- options[:character_set] ||= 'utf-8'
125
-
126
- create_email_object(options)
127
- end
128
-
129
- def create_email_object(options)
130
- email_object = '<Objects xsi:type="Email"><ObjectID xsi:nil="true"/>'
131
- email_object += '<Client><ID>' + options[:client_id].to_s + '</ID></Client>' if options[:client_id]
132
- email_object += '<CategoryID>' + options[:category_id].to_s + '</CategoryID>' if options[:category_id]
133
- email_object += '<Name>' + options[:name].to_s + '</Name>' if options[:name]
134
- email_object += '<Description>' + options[:description].to_s + '</Description>' if options[:description]
135
- email_object += '<Subject>' + options[:subject] + '</Subject>' +
136
- '<HTMLBody>' + options[:body] + '</HTMLBody>' +
137
- '<EmailType>' + options[:email_type] + '</EmailType>' +
138
- '<IsHTMLPaste>' + options[:is_html_paste] + '</IsHTMLPaste>' +
139
- '<CharacterSet>' + options[:character_set] + '</CharacterSet></Objects>'
140
- end
141
-
142
- def prepare_folder(title, args)
143
- options = args.extract_options!
144
- options[:title] = CGI.escapeHTML title.to_s
145
- options[:description] ||= 'description'
146
- options[:client_id] ||= @account
147
-
148
- options[:content_type] ||= 'email'
149
- options[:is_active] ||= 'true'
150
- options[:is_editable] ||= 'true'
151
- options[:allow_children] ||= 'true'
152
-
153
- create_folder_object(options)
154
- end
155
-
156
- def create_folder_object(options)
157
- folder_object = '<Objects xsi:type="DataFolder"><ObjectID xsi:nil="true"/>'
158
- folder_object += '<Client><ID>' + options[:client_id].to_s + '</ID></Client>' if options[:client_id]
159
- folder_object += '<CustomerKey>' + options[:title].to_s + '</CustomerKey>' if options[:title]
160
- folder_object += '<Name>' + options[:title].to_s + '</Name>' +
161
- '<Description>' + options[:description].to_s + '</Description>' +
162
- '<ContentType>' + options[:content_type].to_s + '</ContentType>' +
163
- '<IsActive>' + options[:is_active].to_s + '</IsActive>' +
164
- '<IsEditable>' + options[:is_editable].to_s + '</IsEditable>' +
165
- '<AllowChildren>' + options[:allow_children].to_s + '</AllowChildren>'
166
-
167
- if options[:parent]
168
- folder_object += '<ParentFolder>
169
- <PartnerKey xsi:nil="true"/>
170
- <ModifiedDate xsi:nil="true"/>
171
- <ID>' + options[:parent].to_s + '</ID>
172
- <ObjectID xsi:nil="true"/>
173
- </ParentFolder>'
174
- end
175
- folder_object += '</Objects>'
176
- end
177
-
178
- def prepare_send(email_id, list_id, account=nil)
179
- account ||= @account
180
- create_send_object(email_id, list_id, account)
181
- end
182
-
183
- def create_send_object(email_id, list_id, account)
184
- '<Objects xsi:type="Send"><PartnerKey xsi:nil="true"/>' +
185
- '<ObjectID xsi:nil="true"/>' +
186
- '<Client><ID>' + account.to_s + '</ID></Client>' +
187
- '<Email>' +
188
- '<PartnerKey xsi:nil="true"/>' +
189
- '<ID>' + email_id.to_s + '</ID>' +
190
- '<ObjectID xsi:nil="true"/>' +
191
- '</Email>' +
192
- '<List>' +
193
- '<PartnerKey xsi:nil="true"/>' +
194
- '<ObjectID xsi:nil="true"/>' +
195
- '<ID>' + list_id.to_s + '</ID>' +
196
- '</List>' +
197
- '</Objects>'
198
- end
199
-
200
- def prepare_delete_email(email_id, account=nil)
201
- account ||= @account
202
- create_delete_email_object(email_id, account)
203
- end
204
-
205
- def create_delete_email_object(email_id, account)
206
- '<Objects xsi:type="Email">' +
207
- '<Client>' +
208
- '<ID>' + account.to_s + '</ID>' +
209
- '</Client>' +
210
- '<ID>' + email_id.to_s + '</ID>' +
211
- '<ObjectID xsi:nil="true"/>' +
212
- '</Objects>'
213
- end
214
- end
215
- end