zuck 2.0.0 → 2.1.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 (38) hide show
  1. checksums.yaml +13 -5
  2. data/CHANGELOG.markdown +9 -0
  3. data/README.markdown +7 -1
  4. data/VERSION +1 -1
  5. data/lib/zuck/facebook/ad_creative.rb +0 -3
  6. data/lib/zuck/facebook/ad_group.rb +7 -7
  7. data/lib/zuck/facebook/targeting_spec.rb +0 -1
  8. data/lib/zuck.rb +6 -0
  9. data/spec/fixtures/a_single_account.yml +31 -111
  10. data/spec/fixtures/a_single_campaign.yml +11 -57
  11. data/spec/fixtures/a_single_group.yml +13 -62
  12. data/spec/fixtures/ad_interest_search_disney.yml +19 -19
  13. data/spec/fixtures/ad_interest_search_moviepilot.yml +15 -18
  14. data/spec/fixtures/ad_interest_search_nonexistant.yml +11 -11
  15. data/spec/fixtures/create_a_creative.yml +48 -0
  16. data/spec/fixtures/create_ad_campaign.yml +44 -226
  17. data/spec/fixtures/create_ad_group.yml +13 -155
  18. data/spec/fixtures/create_ad_set.yml +11 -57
  19. data/spec/fixtures/delete_ad_group.yml +10 -55
  20. data/spec/fixtures/delete_ad_set.yml +48 -0
  21. data/spec/fixtures/delete_campaign.yml +93 -0
  22. data/spec/fixtures/delete_creative.yml +48 -0
  23. data/spec/fixtures/find_a_single_group_and_update_it.yml +84 -110
  24. data/spec/fixtures/list_of_ad_accounts.yml +10 -57
  25. data/spec/fixtures/list_of_ad_campaigns.yml +10 -57
  26. data/spec/fixtures/list_of_ad_creatives.yml +9 -56
  27. data/spec/fixtures/list_of_ad_groups.yml +10 -57
  28. data/spec/fixtures/list_of_all_ad_creatives_of_account.yml +10 -57
  29. data/spec/fixtures/reach_for_invalid_interest.yml +28 -31
  30. data/spec/fixtures/reach_for_valid_keywords.yml +13 -13
  31. data/spec/fixtures/reach_for_valid_keywords_male_young.yml +13 -13
  32. data/spec/lib/zuck/facebook/ad_interest_spec.rb +1 -1
  33. data/spec/lib/zuck/facebook/targeting_spec_spec.rb +3 -3
  34. data/spec/lib/zuck_spec.rb +125 -86
  35. data/spec/spec_helper.rb +14 -0
  36. data/test_access_token +1 -1
  37. data/zuck.gemspec +7 -3
  38. metadata +49 -45
@@ -2,56 +2,121 @@ require 'spec_helper'
2
2
 
3
3
  describe Zuck::FbObject do
4
4
 
5
- before(:all) do
5
+ before(:all) {
6
+ puts "Koala version: #{Koala.config.api_version}"
6
7
  Zuck.graph = Koala::Facebook::API.new(test_access_token)
7
- end
8
+ }
8
9
 
9
- let(:graph) { Zuck.graph }
10
- let(:account) { Zuck::AdAccount.new(graph, {id: "act_10150585630710217"}) }
11
- let(:campaign){ Zuck::AdCampaign.new(graph, {id: "6021499361751"}, account) }
12
- let(:group) { Zuck::AdGroup.new(graph, {id: "6010889169151"}, campaign)}
13
- let(:creative){ Zuck::AdCreative.new(graph, {id: "6021396606151"}, group) }
14
- let(:set) { Zuck::AdSet.new(graph, {id: "6021525283751"}, account) }
15
10
 
11
+ let(:graph) { Zuck.graph }
12
+ let(:account_id) { "act_367106653" }
13
+ let(:account) { Zuck::AdAccount.new(graph, {id: account_id}) }
16
14
 
17
- describe "read only objects" do
18
- it "can't be created" do
19
- expect{
20
- Zuck::AdCreative.create(:x, {}, :y)
21
- }.to raise_error(Zuck::Error::ReadOnly)
22
- end
15
+ describe "talking to facebook" do
16
+ act_campaign = nil
17
+ campaign = nil
18
+ creative = nil
19
+ group = nil
20
+ set = nil
23
21
 
24
- it "can't be saved" do
25
- expect{
26
- creative.save
27
- }.to raise_error(Zuck::Error::ReadOnly)
28
- end
22
+ context "creating" do
29
23
 
30
- it "can't be destroyed" do
31
- expect{
32
- creative.destroy
33
- }.to raise_error(Zuck::Error::ReadOnly)
24
+ it "an ad campaign via an existing ad account" do
25
+ VCR.use_cassette('create_ad_campaign') do
26
+ o = {
27
+ daily_budget: 1000,
28
+ name: "bloody campaign (via account)"
29
+ }
30
+ explain_error {
31
+ act_campaign = account.create_ad_campaign(o)
32
+ act_campaign.name.should == "bloody campaign (via account)"
33
+ }
34
+ end
35
+ end
36
+
37
+
38
+ it "an ad campaign" do
39
+ VCR.use_cassette('create_ad_campaign') do
40
+ o = {
41
+ objective: 'NONE',
42
+ name: "bloody campaign",
43
+ campaign_group_status: 'PAUSED'
44
+ }
45
+ explain_error {
46
+ campaign = Zuck::AdCampaign.create(graph, o, account)
47
+ campaign.name.should == "bloody campaign"
48
+ }
49
+ end
50
+ end
51
+
52
+ it "an ad set" do
53
+ VCR.use_cassette('create_ad_set') do
54
+ o = {
55
+ bid_type: 'CPC',
56
+ bid_info: "{'CLICKS': 1}",
57
+ name: 'bloody ad set',
58
+ campaign_status: 'PAUSED',
59
+ daily_budget: 100,
60
+ targeting: "{'geo_locations':{'countries':['US','GB']}}",
61
+ campaign_group_id: campaign.id
62
+ }
63
+ explain_error {
64
+ set = Zuck::AdSet.create(graph, o, account)
65
+ set.name.should == 'bloody ad set'
66
+ }
67
+ end
68
+ end
69
+
70
+ it "a creative by uploading an image" do
71
+ VCR.use_cassette('create a creative') do
72
+ o = {
73
+ title: 'bloody title',
74
+ body: 'bloody body',
75
+ object_url: 'http://moviepilot.com/',
76
+ image_url: 'http://images-cdn.moviepilot.com/image/upload/c_fill,h_246,w_470/v1427727623/moviepilot.jpg'
77
+ }
78
+ explain_error {
79
+ creative = Zuck::AdCreative.create(graph, o, account)
80
+ creative.id.should_not == nil
81
+ }
82
+ end
83
+ end
84
+
85
+
86
+ it "an ad group via an existing ad campaign" do
87
+ VCR.use_cassette('create_ad_group') do
88
+ o = {
89
+ name: "Rap like me",
90
+ # targeting: '{"geo_locations": {"countries":["US"]}}',
91
+ objective: 'WEBSITE_CLICKS',
92
+ creative: '{"creative_id": '+creative.id+'}'
93
+ }
94
+ explain_error {
95
+ group = set.create_ad_group(o)
96
+ group.name.should == "Rap like me"
97
+ group['bid_type'].should == 'CPC'
98
+ }
99
+ end
100
+ end
34
101
  end
35
- end
36
102
 
37
- describe "talking to facebook" do
38
103
  context "reading" do
39
104
 
40
105
  it "a list of ad accounts" do
41
106
  VCR.use_cassette('list_of_ad_accounts') do
42
- Zuck::AdAccount.all.should have(2).items
107
+ Zuck::AdAccount.all.should have_at_least(1).items
43
108
  end
44
109
  end
45
110
 
46
111
  it "a list of ad campaigns" do
47
112
  VCR.use_cassette('list_of_ad_campaigns') do
48
- account.ad_campaigns.should have(24).items
113
+ account.ad_campaigns.should have_at_least(2).items
49
114
  end
50
115
  end
51
116
 
52
117
  it "a list of ad groups" do
53
118
  VCR.use_cassette('list_of_ad_groups') do
54
- campaign.ad_groups.should have(4).item
119
+ campaign.ad_groups.should have_at_least(1).item
55
120
  end
56
121
  end
57
122
 
@@ -65,7 +130,7 @@ describe Zuck::FbObject do
65
130
  g = graph
66
131
  Zuck::AdAccount.should_receive(:all).and_return([account])
67
132
  VCR.use_cassette('list_of_all_ad_creatives_of_account') do
68
- Zuck::AdCreative.all(g).should have(13).items
133
+ Zuck::AdCreative.all(g).should have_at_least(1).items
69
134
  end
70
135
  end
71
136
 
@@ -73,97 +138,71 @@ describe Zuck::FbObject do
73
138
 
74
139
  it "campaign with the correct type" do
75
140
  VCR.use_cassette('a_single_campaign') do
76
- c = Zuck::AdCampaign.find(6021496142951, graph)
141
+ c = Zuck::AdCampaign.find(campaign.id, graph)
142
+ c.buying_type.should == "AUCTION"
77
143
  end
78
144
  end
79
145
 
80
146
  it "account with the correct type" do
81
147
  VCR.use_cassette('a_single_account') do
82
- c = Zuck::AdAccount.find('act_10150585630710217', graph)
148
+ c = Zuck::AdAccount.find(account_id, graph)
149
+ c.account_id.should == account_id[4..-1]
150
+ c.account_status.should == 1
83
151
  end
84
152
  end
85
153
 
86
154
  it "when expecting an ad group but the id belongs to a campaign" do
87
155
  VCR.use_cassette('a_single_group') do
88
156
  expect{
89
- c = Zuck::AdGroup.find(6010889111951, graph)
157
+ Zuck::AdGroup.find(campaign.id, graph)
90
158
  }.to raise_error(Koala::Facebook::ClientError)
91
159
  end
92
160
  end
93
161
 
94
162
  it "and saving it" do
95
163
  VCR.use_cassette('find_a_single_group_and_update_it') do
96
- group = Zuck::AdGroup.find(6021525861551, graph)
97
- group.name = "My old name"
98
- group.save
99
- group.name.should == "My old name"
100
- group.name = "My new name"
101
- group.save
102
- group.name.should == "My new name"
103
- group.reload
104
- group.name.should == "My new name"
164
+ explain_error {
165
+ found_group = Zuck::AdGroup.find(group.id, graph)
166
+ found_group.name = "My old name"
167
+ found_group.save
168
+ found_group.name.should == "My old name"
169
+ found_group.name = "My new name"
170
+ found_group.save
171
+ found_group.name.should == "My new name"
172
+ found_group.reload
173
+ found_group.name.should == "My new name"
174
+ }
105
175
  end
106
176
  end
107
177
 
108
178
  end
109
179
  end
110
180
 
111
-
112
- context "creating" do
113
- it "an ad set" do
114
- VCR.use_cassette('create_ad_set') do
115
- o = {
116
- name: 'test ad set',
117
- campaign_status: 'PAUSED',
118
- daily_budget: 100,
119
- targeting: "{'geo_locations':{'countries':['US','GB']}}",
120
- campaign_group_id: campaign.id
121
- }
122
- ad_set = Zuck::AdSet.create(graph, o, account)
123
- ad_set.name.should == 'test ad set'
124
- end
125
- end
126
-
127
- it "an ad campaign" do
128
- VCR.use_cassette('create_ad_campaign') do
129
- o = {objective: 'NONE', name: "bloody", campaign_group_status: 'PAUSED' }
130
- campaign = Zuck::AdCampaign.create(graph, o, account)
131
- campaign.name.should == "bloody"
181
+ context "deleting" do
182
+ it "an ad group" do
183
+ VCR.use_cassette('delete_ad_group') do
184
+ group.destroy.should be_true
132
185
  end
133
186
  end
134
187
 
135
- it "an ad campaign via an existing ad account" do
136
- VCR.use_cassette('create_ad_campaign') do
137
- o = {daily_budget: 1000, name: "bloody" }
138
- campaign = account.create_ad_campaign(o)
139
- campaign.name.should == "bloody"
188
+ it "an ad set" do
189
+ VCR.use_cassette('delete_ad_set') do
190
+ set.destroy.should be_true
140
191
  end
141
192
  end
142
193
 
143
- it "an ad group via an existing ad campaign" do
144
- VCR.use_cassette('create_ad_group') do
145
- o = {
146
- bid_type: 'CPC',
147
- bid_info: '{"CLICKS": 1}',
148
- name: "Rap like me",
149
- targeting: '{"geo_locations": {"countries":["US"]}}',
150
- objective: 'WEBSITE_CLICKS',
151
- creative: '{"creative_id": "6021396606151"}'
152
- }
153
- group = set.create_ad_group(o)
154
- group.name.should == "Rap like me"
155
- group.bid_type.should == 'CPC'
194
+ it "a creative" do
195
+ VCR.use_cassette('delete_creative') do
196
+ creative.destroy.should be_true
156
197
  end
157
198
  end
158
- end
159
199
 
160
- context "deleting" do
161
- it "an ad group" do
162
- VCR.use_cassette('delete_ad_group') do
163
- group.destroy.should be_true
200
+ it "a campaign" do
201
+ VCR.use_cassette('delete_campaign') do
202
+ campaign.destroy.should be_true
203
+ act_campaign.destroy.should be_true
164
204
  end
165
205
  end
166
206
  end
167
-
168
207
  end
169
208
  end
data/spec/spec_helper.rb CHANGED
@@ -44,4 +44,18 @@ def test_access_token
44
44
  @test_access_token ||= File.read("test_access_token")
45
45
  end
46
46
 
47
+ def explain_error(&block)
48
+ raise "missing code block" unless block_given?
49
+
50
+ begin
51
+ block.call
52
+ rescue Koala::Facebook::APIError => e
53
+ puts "=== Facebook API Error ===================================="
54
+ body = JSON.parse e.response_body
55
+ body['error'].each { |k, v| printf("%-20s %s\n", k+":", v) }
56
+ puts "==========================================================="
57
+ raise e
58
+ end
59
+ end
60
+
47
61
  require File.expand_path("../../lib/zuck", __FILE__)
data/test_access_token CHANGED
@@ -1 +1 @@
1
- CAAEvJ5vzhl8BAICOwypV5nYnYWXhBq1eskHA7rKyrz9fXcAvKRXDWVZAaG7FpQ21qTXeCtGZCR7iu1dtZCqZCZBZCQbefKrMOnZAibDZAiQKiX0s22PgtKuCoQK4LDVimREnqkGdoLMyB4zgT3A6ZAU7pn6wc2mTzZBWVbkr71bZBJKjhyeb4V58TkMsUbN9SQer3ZCRRtWTxqNFTUwHuv51RoVsI7LNw0mCr5gZD
1
+ FAKEACCESSTOKEN
data/zuck.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: zuck 2.0.0 ruby lib
5
+ # stub: zuck 2.1.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "zuck"
9
- s.version = "2.0.0"
9
+ s.version = "2.1.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Jannis Hermanns"]
14
- s.date = "2015-01-09"
14
+ s.date = "2015-04-15"
15
15
  s.description = "This gem allows to easily access facebook's ads api in ruby. See https://developers.facebook.com/docs/reference/ads-api/"
16
16
  s.email = "jannis@gmail.com"
17
17
  s.extra_rdoc_files = [
@@ -55,10 +55,14 @@ Gem::Specification.new do |s|
55
55
  "spec/fixtures/ad_interest_search_disney.yml",
56
56
  "spec/fixtures/ad_interest_search_moviepilot.yml",
57
57
  "spec/fixtures/ad_interest_search_nonexistant.yml",
58
+ "spec/fixtures/create_a_creative.yml",
58
59
  "spec/fixtures/create_ad_campaign.yml",
59
60
  "spec/fixtures/create_ad_group.yml",
60
61
  "spec/fixtures/create_ad_set.yml",
61
62
  "spec/fixtures/delete_ad_group.yml",
63
+ "spec/fixtures/delete_ad_set.yml",
64
+ "spec/fixtures/delete_campaign.yml",
65
+ "spec/fixtures/delete_creative.yml",
62
66
  "spec/fixtures/find_a_single_group_and_update_it.yml",
63
67
  "spec/fixtures/list_of_ad_accounts.yml",
64
68
  "spec/fixtures/list_of_ad_campaigns.yml",