sem4r 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +13 -2
- data/Gemfile.lock +13 -7
- data/README.rdoc +44 -7
- data/Rakefile +2 -122
- data/VERSION.yml +1 -1
- data/bin/sem +1 -0
- data/examples_sem4r/01_get_account.rb +1 -0
- data/examples_sem4r/02_get_info.rb +1 -0
- data/examples_sem4r/03_list_ad.rb +1 -0
- data/examples_sem4r/04_list_keywords.rb +1 -0
- data/examples_sem4r/05_request_report.rb +25 -14
- data/examples_sem4r/{05_request_report_2010.rb → 06_request_report_definition.rb} +2 -4
- data/examples_sem4r/{06_create_campaigns.rb → 07_create_campaigns.rb} +1 -0
- data/examples_sem4r/{07_create_campaigns_block.rb → 08_create_campaigns_block.rb} +1 -0
- data/examples_sem4r/{07_create_campaigns_simple.rb → 09_create_campaigns_simple.rb} +1 -0
- data/examples_sem4r/{08_ad_params.rb → 10_ad_params.rb} +1 -0
- data/examples_sem4r/{09_targeting_idea.rb → 11_targeting_idea.rb} +1 -0
- data/examples_sem4r/{10_get_location.rb → 12_get_location.rb} +1 -0
- data/examples_sem4r/{11_submit_bulk_job.rb → 13_submit_bulk_job.rb} +1 -1
- data/examples_sem4r/{12_list_bulk_job.rb → 14_list_bulk_job.rb} +3 -0
- data/examples_sem4r/30_prune_empty_adgroup.rb +1 -0
- data/examples_sem4r/31_empty_accounts.rb +1 -0
- data/examples_sem4r/example_helper.rb +2 -1
- data/lib/sem4r/ad_group/ad_group.rb +22 -7
- data/lib/sem4r/ad_group/ad_group_bids.rb +1 -1
- data/lib/sem4r/ad_group/ad_group_service.rb +12 -5
- data/lib/sem4r/ad_group_ad/ad_group_ad.rb +1 -0
- data/lib/sem4r/ad_group_ad/ad_group_ad_operations.rb +1 -0
- data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +14 -9
- data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +16 -25
- data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +18 -14
- data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +27 -19
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +2 -1
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +1 -0
- data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +9 -4
- data/lib/sem4r/ad_group_criterion/criterion.rb +1 -0
- data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +1 -0
- data/lib/sem4r/ad_group_criterion/criterion_placement.rb +1 -0
- data/lib/sem4r/ad_param/ad_param.rb +24 -8
- data/lib/sem4r/ad_param/ad_param_service.rb +8 -5
- data/lib/sem4r/adwords.rb +232 -76
- data/lib/sem4r/base.rb +1 -1
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +41 -35
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_account_extension.rb +49 -15
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_selector.rb +29 -20
- data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +13 -14
- data/lib/sem4r/bulk_mutate_job/job_operations.rb +1 -1
- data/lib/sem4r/campaign/campaign.rb +1 -0
- data/lib/sem4r/campaign/campaign_account_extension.rb +2 -1
- data/lib/sem4r/campaign/campaign_service.rb +9 -5
- data/lib/sem4r/credentials.rb +11 -5
- data/lib/sem4r/geo_location/address.rb +56 -0
- data/lib/sem4r/geo_location/geo_location_account_extension.rb +27 -6
- data/lib/sem4r/geo_location/geo_location_selector.rb +57 -0
- data/lib/sem4r/geo_location/geo_location_service.rb +9 -16
- data/lib/sem4r/info/info_account_extension.rb +3 -2
- data/lib/sem4r/info/info_selector.rb +2 -1
- data/lib/sem4r/info/info_service.rb +10 -3
- data/lib/sem4r/operation.rb +39 -20
- data/lib/sem4r/report_definition/report_definition.rb +37 -19
- data/lib/sem4r/report_definition/report_definition_account_extension.rb +66 -16
- data/lib/sem4r/report_definition/report_definition_operation.rb +2 -2
- data/lib/sem4r/report_definition/report_definition_selector.rb +1 -1
- data/lib/sem4r/report_definition/report_definition_service.rb +11 -7
- data/lib/sem4r/report_definition/report_field.rb +3 -2
- data/lib/sem4r/sem4r_templates.rb +77 -0
- data/lib/sem4r/{services/service.rb → service.rb} +23 -23
- data/lib/sem4r/targeting_idea/targeting_idea.rb +4 -4
- data/lib/sem4r/targeting_idea/targeting_idea_account_extension.rb +1 -1
- data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +6 -6
- data/lib/sem4r/targeting_idea/targeting_idea_service.rb +7 -5
- data/lib/sem4r/v13_account/account_account_extension.rb +7 -10
- data/lib/sem4r/v13_account/account_service.rb +10 -4
- data/lib/sem4r/v13_account/billing_address.rb +2 -2
- data/lib/sem4r/v13_report/report_service.rb +11 -9
- data/lib/sem4r.rb +46 -31
- data/lib/{sem4r/cli → sem4r_cli}/cli_helpers.rb +3 -2
- data/lib/{sem4r/cli/cli_command.rb → sem4r_cli/cli_mini_framework.rb} +77 -32
- data/lib/{sem4r/cli/cli_common_args.rb → sem4r_cli/cli_sem.rb} +177 -157
- data/lib/{sem4r/cli/commands/cli_list_ads.rb → sem4r_cli/commands/cli_ads.rb} +7 -9
- data/lib/sem4r_cli/commands/cli_campaign.rb +69 -0
- data/lib/{sem4r/cli/commands/cli_list_client.rb → sem4r_cli/commands/cli_clients.rb} +2 -2
- data/lib/{sem4r/cli → sem4r_cli}/commands/cli_ideas.rb +35 -27
- data/lib/{sem4r/cli → sem4r_cli}/commands/cli_info.rb +3 -4
- data/lib/{sem4r/cli/commands/cli_repdef.rb → sem4r_cli/commands/cli_job.rb} +57 -55
- data/lib/{sem4r/cli/commands/cli_list_keywords.rb → sem4r_cli/commands/cli_keywords.rb} +14 -13
- data/lib/sem4r_cli/commands/cli_profile.rb +138 -0
- data/lib/{sem4r/cli/commands/cli_report.rb → sem4r_cli/commands/cli_repdef.rb} +67 -20
- data/lib/{sem4r/cli/commands/cli_request_report.rb → sem4r_cli/commands/cli_report.rb} +82 -19
- data/lib/sem4r_cli.rb +5 -7
- data/lib/sem4r_soap/http_connector.rb +206 -0
- data/lib/{soap_helpers → sem4r_soap}/soap_attributes.rb +8 -3
- data/lib/{sem4r/services → sem4r_soap}/soap_dumper.rb +36 -20
- data/lib/{sem4r/services → sem4r_soap}/soap_error.rb +5 -2
- data/lib/sem4r_soap/soap_response.rb +75 -0
- data/lib/sem4r_soap/soap_service.rb +137 -0
- data/lib/{sem4r/cli/cli_sem.rb → sem4r_soap/soap_service_v13.rb} +27 -28
- data/lib/sem4r_soap/soap_service_v2010.rb +80 -0
- data/lib/sem4r_soap.rb +17 -0
- data/sem4r.gemspec +93 -58
- data/spec/build_fixtures.rb +49 -42
- data/spec/fixtures/password.example.yml +3 -0
- data/spec/fixtures/sem4r.example.yml +6 -0
- data/spec/fixtures/{services/error.xml → soap_error.xml} +0 -0
- data/spec/fixtures/soap_error2.xml +29 -0
- data/spec/helpers/dump_interceptor.rb +90 -0
- data/spec/helpers/fixtures_bulk_mutate_job.rb +48 -0
- data/spec/helpers/fixtures_geo_location.rb +45 -0
- data/{lib/sem4r/campaign_criterion/campaign_criterion_service.rb → spec/helpers/fixtures_info.rb} +10 -6
- data/spec/helpers/fixtures_report_definition.rb +65 -0
- data/spec/{rspec_hash.rb → helpers/rspec_hash.rb} +1 -0
- data/spec/{rspec_matchers.rb → helpers/rspec_matchers.rb} +46 -19
- data/spec/{rspec_sem4r_helper.rb → helpers/rspec_sem4r_helper.rb} +19 -16
- data/spec/{sem4r_stubs.rb → helpers/sem4r_stubs.rb} +5 -4
- data/spec/rspec_helper.rb +4 -4
- data/spec/sem4r/account_spec.rb +2 -3
- data/spec/sem4r/ad_group/ad_group_service_spec.rb +1 -1
- data/spec/sem4r/ad_group/ad_group_spec.rb +1 -1
- data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +3 -3
- data/spec/sem4r/adwords_spec.rb +62 -39
- data/{lib/sem4r/cli/commands/cli_list_campaign.rb → spec/sem4r/bulk_mutate_job/bulk_mutate_job_selector_spec.rb} +14 -11
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +2 -3
- data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +23 -17
- data/spec/sem4r/bulk_mutate_job/fixtures/get-list_job-req.xml +35 -0
- data/spec/sem4r/bulk_mutate_job/fixtures/get-list_job-res.xml +417 -0
- data/spec/sem4r/bulk_mutate_job/fixtures/mutate-add_job-req.xml +106 -0
- data/spec/sem4r/bulk_mutate_job/fixtures/mutate-add_job-res.xml +48 -0
- data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +5 -7
- data/spec/sem4r/campaign/campaign_service_spec.rb +2 -2
- data/spec/sem4r/credentials_spec.rb +10 -8
- data/spec/sem4r/geo_location/address_spec.rb +62 -0
- data/spec/sem4r/geo_location/fixtures/get-req.xml +42 -0
- data/spec/sem4r/geo_location/fixtures/get-res.xml +60 -0
- data/spec/sem4r/info/fixtures/get-req.xml +34 -0
- data/spec/sem4r/info/fixtures/get-res.xml +27 -0
- data/spec/sem4r/nokogiri_parsing_spec.rb +1 -0
- data/spec/sem4r/operation_spec.rb +72 -0
- data/spec/sem4r/report_definition/fixtures/get-list-repdef-req.xml +22 -0
- data/spec/sem4r/report_definition/fixtures/get-list-repdef-res.xml +73 -0
- data/spec/sem4r/report_definition/fixtures/getReportFields-req.xml +24 -0
- data/spec/sem4r/report_definition/fixtures/getReportFields-res.xml +1199 -0
- data/spec/sem4r/report_definition/fixtures/mutate-add-report-req.xml +63 -0
- data/spec/sem4r/report_definition/fixtures/mutate-add-report-res.xml +68 -0
- data/spec/sem4r/report_definition/report_definition_service_spec.rb +5 -5
- data/spec/sem4r/report_definition/report_definition_spec.rb +28 -43
- data/{lib/sem4r/cli/commands/cli_list_report.rb → spec/sem4r/report_definition/report_field_spec.rb} +12 -10
- data/spec/sem4r/rexml_parsing_spec.rb +1 -0
- data/spec/sem4r/{services/service_spec.rb → service_spec.rb} +1 -1
- data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +1 -1
- data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +1 -1
- data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +1 -1
- data/spec/sem4r/v13_account/account_service_spec.rb +2 -2
- data/spec/sem4r/v13_report/report_service_spec.rb +2 -2
- data/spec/{sem4r/cli → sem4r_cli}/cli_spec.rb +22 -27
- data/spec/{soap_helpers → sem4r_soap}/soap_attributes_spec.rb +3 -3
- data/spec/{sem4r/services/soap_message_v13_spec.rb → sem4r_soap/soap_response_spec.rb} +10 -15
- data/spec/{sem4r/services/soap_call_spec.rb → sem4r_soap/soap_service_spec.rb} +35 -54
- data/tasks/jeweler.rake +66 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/sem4r.rake +25 -0
- data/tasks/yard.rake +31 -0
- metadata +173 -76
- data/lib/sem4r/ad_extension_override/ad_extension_override_service.rb +0 -30
- data/lib/sem4r/api_counters.rb +0 -8
- data/lib/sem4r/campaign_target/campaign_target_service.rb +0 -30
- data/lib/sem4r/cli/commands/cli_download_report.rb +0 -82
- data/lib/sem4r/services/http_connector.rb +0 -93
- data/lib/sem4r/services/soap_call.rb +0 -122
- data/lib/sem4r/services/soap_connector.rb +0 -139
- data/lib/sem4r/services/soap_message_v13.rb +0 -135
- data/lib/sem4r/services/soap_message_v2010.rb +0 -184
- data/lib/sem4r/v13_traffic_estimator/traffic_estimator_service.rb +0 -30
- data/spec/aggregates_rspec_helper.rb +0 -59
- data/spec/sem4r/report_definition/fixtures/mutate_add-req.xml +0 -24
- data/spec/sem4r/report_definition/fixtures/mutate_add-req_orig.xml +0 -45
@@ -0,0 +1,106 @@
|
|
1
|
+
<!-- Post to 'https://adwords-sandbox.google.com/api/adwords/job/v201008/BulkMutateJobService' -->
|
2
|
+
|
3
|
+
<env:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:env='http://schemas.xmlsoap.org/soap/envelope/' xmlns='https://adwords.google.com/api/adwords/cm/v201008' xmlns:s='https://adwords.google.com/api/adwords/cm/v201008'>
|
4
|
+
<env:Header>
|
5
|
+
<s:RequestHeader env:mustUnderstand='0'>
|
6
|
+
<authToken>
|
7
|
+
***censured***
|
8
|
+
</authToken>
|
9
|
+
<userAgent>
|
10
|
+
Sem4r Adwords Ruby Client Library (http://github.com/sem4r/sem4r)
|
11
|
+
</userAgent>
|
12
|
+
<developerToken>
|
13
|
+
***censured***
|
14
|
+
</developerToken>
|
15
|
+
</s:RequestHeader>
|
16
|
+
</env:Header>
|
17
|
+
<env:Body>
|
18
|
+
<mutate xmlns='https://adwords.google.com/api/adwords/cm/v201008'>
|
19
|
+
<operation xsi:type='JobOperation'>
|
20
|
+
<operator>
|
21
|
+
ADD
|
22
|
+
</operator>
|
23
|
+
<operand xsi:type='BulkMutateJob'>
|
24
|
+
<request>
|
25
|
+
<partIndex>
|
26
|
+
0
|
27
|
+
</partIndex>
|
28
|
+
<operationStreams>
|
29
|
+
<scopingEntityId>
|
30
|
+
<type>
|
31
|
+
CAMPAIGN_ID
|
32
|
+
</type>
|
33
|
+
<value>
|
34
|
+
49247
|
35
|
+
</value>
|
36
|
+
</scopingEntityId>
|
37
|
+
<operations xsi:type='AdGroupAdOperation'>
|
38
|
+
<operator>
|
39
|
+
ADD
|
40
|
+
</operator>
|
41
|
+
<operand xsi:type='AdGroupAd'>
|
42
|
+
<adGroupId>
|
43
|
+
3000128685
|
44
|
+
</adGroupId>
|
45
|
+
<ad xsi:type='TextAd'>
|
46
|
+
<url>
|
47
|
+
http://www.example.com
|
48
|
+
</url>
|
49
|
+
<displayUrl>
|
50
|
+
www.example.com
|
51
|
+
</displayUrl>
|
52
|
+
<headline>
|
53
|
+
Cruise to Mars Sector 1
|
54
|
+
</headline>
|
55
|
+
<description1>
|
56
|
+
Visit the Red Planet in style.
|
57
|
+
</description1>
|
58
|
+
<description2>
|
59
|
+
Low-gravity fun for everyone!
|
60
|
+
</description2>
|
61
|
+
</ad>
|
62
|
+
<status>
|
63
|
+
ENABLED
|
64
|
+
</status>
|
65
|
+
</operand>
|
66
|
+
</operations>
|
67
|
+
<operations xsi:type='AdGroupAdOperation'>
|
68
|
+
<operator>
|
69
|
+
ADD
|
70
|
+
</operator>
|
71
|
+
<operand xsi:type='AdGroupAd'>
|
72
|
+
<adGroupId>
|
73
|
+
3000128685
|
74
|
+
</adGroupId>
|
75
|
+
<ad xsi:type='TextAd'>
|
76
|
+
<url>
|
77
|
+
http://www.example.com
|
78
|
+
</url>
|
79
|
+
<displayUrl>
|
80
|
+
www.example.com
|
81
|
+
</displayUrl>
|
82
|
+
<headline>
|
83
|
+
Cruise to Mars Sector 2
|
84
|
+
</headline>
|
85
|
+
<description1>
|
86
|
+
Visit the Red Planet in style.
|
87
|
+
</description1>
|
88
|
+
<description2>
|
89
|
+
Low-gravity fun for everyone!
|
90
|
+
</description2>
|
91
|
+
</ad>
|
92
|
+
<status>
|
93
|
+
ENABLED
|
94
|
+
</status>
|
95
|
+
</operand>
|
96
|
+
</operations>
|
97
|
+
</operationStreams>
|
98
|
+
</request>
|
99
|
+
<numRequestParts>
|
100
|
+
2
|
101
|
+
</numRequestParts>
|
102
|
+
</operand>
|
103
|
+
</operation>
|
104
|
+
</mutate>
|
105
|
+
</env:Body>
|
106
|
+
</env:Envelope>
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
|
2
|
+
<soap:Header>
|
3
|
+
<ResponseHeader xmlns='https://adwords.google.com/api/adwords/cm/v201008'>
|
4
|
+
<requestId>
|
5
|
+
ecb7c017cc5a5b383577e2f05779ba29
|
6
|
+
</requestId>
|
7
|
+
<operations>
|
8
|
+
1
|
9
|
+
</operations>
|
10
|
+
<responseTime>
|
11
|
+
1109
|
12
|
+
</responseTime>
|
13
|
+
<units>
|
14
|
+
1
|
15
|
+
</units>
|
16
|
+
</ResponseHeader>
|
17
|
+
</soap:Header>
|
18
|
+
<soap:Body>
|
19
|
+
<mutateResponse xmlns='https://adwords.google.com/api/adwords/cm/v201008'>
|
20
|
+
<rval>
|
21
|
+
<context>
|
22
|
+
<authenticatedUserEmail>
|
23
|
+
sem4ruby@gmail.com
|
24
|
+
</authenticatedUserEmail>
|
25
|
+
<effectiveCustomerId>
|
26
|
+
0
|
27
|
+
</effectiveCustomerId>
|
28
|
+
</context>
|
29
|
+
<Job.Type>
|
30
|
+
BulkMutateJob
|
31
|
+
</Job.Type>
|
32
|
+
<id>
|
33
|
+
39169
|
34
|
+
</id>
|
35
|
+
<policy/>
|
36
|
+
<status>
|
37
|
+
PENDING
|
38
|
+
</status>
|
39
|
+
<numRequestParts>
|
40
|
+
2
|
41
|
+
</numRequestParts>
|
42
|
+
<numRequestPartsReceived>
|
43
|
+
1
|
44
|
+
</numRequestPartsReceived>
|
45
|
+
</rval>
|
46
|
+
</mutateResponse>
|
47
|
+
</soap:Body>
|
48
|
+
</soap:Envelope>
|
@@ -26,21 +26,19 @@
|
|
26
26
|
require File.expand_path(File.dirname(__FILE__) + '/../../rspec_helper')
|
27
27
|
|
28
28
|
describe JobOperation do
|
29
|
-
include Sem4rSpecHelper
|
30
|
-
|
29
|
+
include Sem4rSpecHelper
|
31
30
|
|
32
31
|
it "should produce xml" do
|
33
32
|
@campaign = mock("campaign").as_null_object
|
34
33
|
@campaign.stub(:id).and_return(100)
|
35
34
|
|
36
|
-
@
|
37
|
-
@
|
35
|
+
@ad_group = mock("adgroup").as_null_object
|
36
|
+
@ad_group.stub(:id).and_return(3060284754)
|
38
37
|
|
39
|
-
bulk_mutate_job =
|
38
|
+
bulk_mutate_job = template_bulk_mutate_job(@campaign, @ad_group)
|
40
39
|
bulk_mutate_job.should_not be_empty
|
41
40
|
|
42
|
-
job_operation = JobOperation.
|
43
|
-
job_operation.add(bulk_mutate_job)
|
41
|
+
job_operation = JobOperation.add(bulk_mutate_job)
|
44
42
|
|
45
43
|
expected_xml = read_model("//operation", "bulk_mutate_job", "mutate-req.xml")
|
46
44
|
job_operation.to_xml('operation').should xml_equivalent(expected_xml)
|
@@ -37,7 +37,7 @@ describe CampaignService do
|
|
37
37
|
connector = mock("connector")
|
38
38
|
connector.should_receive(:send).and_return(response_xml)
|
39
39
|
service = CampaignService.new(connector)
|
40
|
-
soap_message = service.all(
|
40
|
+
soap_message = service.all(@credentials)
|
41
41
|
els = soap_message.response.xpath("//getResponse")
|
42
42
|
els.should_not be_empty
|
43
43
|
end
|
@@ -59,7 +59,7 @@ describe CampaignService do
|
|
59
59
|
connector = mock("connector")
|
60
60
|
connector.should_receive(:send).and_return(response_xml)
|
61
61
|
service = CampaignService.new(connector)
|
62
|
-
soap_message = service.delete(
|
62
|
+
soap_message = service.delete(@credentials, "xml" )
|
63
63
|
els = soap_message.response.xpath("//mutateResponse")
|
64
64
|
els.should_not be_empty
|
65
65
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
# -------------------------------------------------------------------------
|
2
3
|
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
3
4
|
#
|
@@ -27,7 +28,7 @@ require File.dirname(__FILE__) + '/../rspec_helper'
|
|
27
28
|
describe Credentials do
|
28
29
|
|
29
30
|
before do
|
30
|
-
@
|
31
|
+
@credentials_options = {
|
31
32
|
:environment => "sandbox",
|
32
33
|
:email => "email",
|
33
34
|
:password => "password",
|
@@ -35,7 +36,7 @@ describe Credentials do
|
|
35
36
|
end
|
36
37
|
|
37
38
|
it "should have getter" do
|
38
|
-
credentials = Credentials.new(@
|
39
|
+
credentials = Credentials.new(@credentials_options)
|
39
40
|
|
40
41
|
credentials.email.should == "email"
|
41
42
|
credentials.password.should == "password"
|
@@ -44,20 +45,21 @@ describe Credentials do
|
|
44
45
|
end
|
45
46
|
|
46
47
|
it "should be mutable" do
|
47
|
-
@
|
48
|
-
credentials = Credentials.new(@
|
48
|
+
@credentials_options[:mutable] = true
|
49
|
+
credentials = Credentials.new(@credentials_options)
|
49
50
|
credentials.should be_mutable
|
50
51
|
end
|
51
52
|
|
52
53
|
it "requests authentication token should raise an exception without connector" do
|
53
|
-
credentials = Credentials.new(@
|
54
|
+
credentials = Credentials.new(@credentials_options)
|
54
55
|
lambda { credentials.authentication_token }.should raise_error
|
55
56
|
end
|
56
57
|
|
57
58
|
it "should call connector when request for an authentication token" do
|
58
|
-
|
59
|
-
connector =
|
60
|
-
|
59
|
+
connector = Sem4rSoap::HttpConnector.get
|
60
|
+
connector.should_receive(:post).and_return(double( :code => "200", :status => 200, :body => "Auth=auth_token") )
|
61
|
+
|
62
|
+
credentials = Credentials.new(@credentials_options)
|
61
63
|
credentials.connector= connector
|
62
64
|
credentials.authentication_token.should == "auth_token"
|
63
65
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# -------------------------------------------------------------------------
|
3
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
#
|
24
|
+
# -------------------------------------------------------------------------
|
25
|
+
|
26
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../rspec_helper')
|
27
|
+
|
28
|
+
describe Address do
|
29
|
+
include Sem4rSpecHelper
|
30
|
+
|
31
|
+
it "should accept multiple address" do
|
32
|
+
selector = GeoLocationSelector.new
|
33
|
+
selector.address do
|
34
|
+
city "Pisa"
|
35
|
+
country "IT"
|
36
|
+
end
|
37
|
+
selector.address do
|
38
|
+
address "Via Nazionale, 10"
|
39
|
+
city "Rome"
|
40
|
+
country "IT"
|
41
|
+
end
|
42
|
+
selector.should have(2).addresses
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should build xml (input for google)" do
|
46
|
+
address = Address.new do
|
47
|
+
address "Via Nazionale, 10"
|
48
|
+
city "Rome"
|
49
|
+
country "IT"
|
50
|
+
end
|
51
|
+
xml_expected = read_model("//addresses", "geo_location", "get-req.xml")
|
52
|
+
address.should xml_equivalent(xml_expected)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should parse xml (produced by google)" do
|
56
|
+
model = read_model("//address", "geo_location", "get-res.xml")
|
57
|
+
address = Address.from_element(model)
|
58
|
+
address.city.should == "Roma"
|
59
|
+
address.postal_code == "00184"
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<!-- Post to 'https://adwords-sandbox.google.com/api/adwords/cm/v201008/GeoLocationService' -->
|
2
|
+
|
3
|
+
<env:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:env='http://schemas.xmlsoap.org/soap/envelope/' xmlns='https://adwords.google.com/api/adwords/cm/v201008' xmlns:s='https://adwords.google.com/api/adwords/cm/v201008'>
|
4
|
+
<env:Header>
|
5
|
+
<s:RequestHeader env:mustUnderstand='0'>
|
6
|
+
<authToken>
|
7
|
+
***censured***
|
8
|
+
</authToken>
|
9
|
+
<userAgent>
|
10
|
+
Sem4r Adwords Ruby Client Library (http://github.com/sem4r/sem4r)
|
11
|
+
</userAgent>
|
12
|
+
<developerToken>
|
13
|
+
***censured***
|
14
|
+
</developerToken>
|
15
|
+
</s:RequestHeader>
|
16
|
+
</env:Header>
|
17
|
+
<env:Body>
|
18
|
+
<s:get>
|
19
|
+
<s:selector>
|
20
|
+
<addresses>
|
21
|
+
<streetAddress>
|
22
|
+
Via Nazionale, 10
|
23
|
+
</streetAddress>
|
24
|
+
<cityName>
|
25
|
+
Rome
|
26
|
+
</cityName>
|
27
|
+
<countryCode>
|
28
|
+
IT
|
29
|
+
</countryCode>
|
30
|
+
</addresses>
|
31
|
+
<addresses>
|
32
|
+
<cityName>
|
33
|
+
Pisa
|
34
|
+
</cityName>
|
35
|
+
<countryCode>
|
36
|
+
IT
|
37
|
+
</countryCode>
|
38
|
+
</addresses>
|
39
|
+
</s:selector>
|
40
|
+
</s:get>
|
41
|
+
</env:Body>
|
42
|
+
</env:Envelope>
|
@@ -0,0 +1,60 @@
|
|
1
|
+
<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
|
2
|
+
<soap:Header>
|
3
|
+
<ResponseHeader xmlns='https://adwords.google.com/api/adwords/cm/v201008'>
|
4
|
+
<requestId>
|
5
|
+
2f46eb41f5046946b248683b45a159fb
|
6
|
+
</requestId>
|
7
|
+
<operations>
|
8
|
+
2
|
9
|
+
</operations>
|
10
|
+
<responseTime>
|
11
|
+
162
|
12
|
+
</responseTime>
|
13
|
+
<units>
|
14
|
+
2
|
15
|
+
</units>
|
16
|
+
</ResponseHeader>
|
17
|
+
</soap:Header>
|
18
|
+
<soap:Body>
|
19
|
+
<getResponse xmlns='https://adwords.google.com/api/adwords/cm/v201008'>
|
20
|
+
<rval>
|
21
|
+
<geoPoint>
|
22
|
+
<latitudeInMicroDegrees>
|
23
|
+
41901464
|
24
|
+
</latitudeInMicroDegrees>
|
25
|
+
<longitudeInMicroDegrees>
|
26
|
+
12494510
|
27
|
+
</longitudeInMicroDegrees>
|
28
|
+
</geoPoint>
|
29
|
+
<address>
|
30
|
+
<streetAddress>
|
31
|
+
Via Nazionale, 10
|
32
|
+
</streetAddress>
|
33
|
+
<cityName>
|
34
|
+
Roma
|
35
|
+
</cityName>
|
36
|
+
<provinceCode>
|
37
|
+
Lazio
|
38
|
+
</provinceCode>
|
39
|
+
<postalCode>
|
40
|
+
00184
|
41
|
+
</postalCode>
|
42
|
+
<countryCode>
|
43
|
+
IT
|
44
|
+
</countryCode>
|
45
|
+
</address>
|
46
|
+
<encodedLocation>
|
47
|
+
qrvM3QDB3iJsoW5CCm5ELDnrheCfJDpb74yQwvnJlSeV2uWWM7SqEqhwvlaHnOM383ATHFNQRP9+vLgh5ZhGfUhZ7NSmi+eP68KgvuxciuTnoDePQNB14CXChk7/x2h+p01JSnpiHBosblWjonSiBZqdRAeFcqd7jmst7t3qnwCs7PYyXBOKw47hxdiiVPHxagzknR8mvhhR1XjYzfeDS7nZDDAyRFs3x1l7Eq7VG2uNXz0T25VpFEhJfbjXee0c2YbkwcTZJnZLSRKBvyvuudu7oyw2OwSARrTNDnT1gubbhFvThThB1sXIvaHPRlirQDuKHOw9Jdn31LS/wNuxl7OZgV5w631hTdHS/dZUiPTpd2AbGDOMEoPRfdUpkrVQ1fDFXswqXlwgWPVTlrK/B3TVoFR/emc7TztipecXqA9YSc6tMQzJ5IAONn8ZpzLV2tLnpb/s2Zx0y+uEofWTfCvfS5LJ9MFtCobL+x/j99jBpG48wf/4UPGAFuN3Hsa5ZIsgP5J5n85xJmCKtmFhJM+tdnBfXFEhW9egjchy/Optt+2cJzdmAXiPfnsBY5YWGixI12WETHstsvkkZw==
|
48
|
+
</encodedLocation>
|
49
|
+
<GeoLocation.Type>
|
50
|
+
GeoLocation
|
51
|
+
</GeoLocation.Type>
|
52
|
+
</rval>
|
53
|
+
<rval xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:type='InvalidGeoLocation'>
|
54
|
+
<GeoLocation.Type>
|
55
|
+
InvalidGeoLocation
|
56
|
+
</GeoLocation.Type>
|
57
|
+
</rval>
|
58
|
+
</getResponse>
|
59
|
+
</soap:Body>
|
60
|
+
</soap:Envelope>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<!-- Post to 'https://adwords-sandbox.google.com/api/adwords/info/v201008/InfoService' -->
|
2
|
+
|
3
|
+
<env:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:env='http://schemas.xmlsoap.org/soap/envelope/' xmlns='https://adwords.google.com/api/adwords/cm/v201008' xmlns:s='https://adwords.google.com/api/adwords/info/v201008'>
|
4
|
+
<env:Header>
|
5
|
+
<s:RequestHeader env:mustUnderstand='0'>
|
6
|
+
<authToken>
|
7
|
+
***censured***
|
8
|
+
</authToken>
|
9
|
+
<userAgent>
|
10
|
+
Sem4r Adwords Ruby Client Library (http://github.com/sem4r/sem4r)
|
11
|
+
</userAgent>
|
12
|
+
<developerToken>
|
13
|
+
***censured***
|
14
|
+
</developerToken>
|
15
|
+
</s:RequestHeader>
|
16
|
+
</env:Header>
|
17
|
+
<env:Body>
|
18
|
+
<s:get>
|
19
|
+
<s:selector>
|
20
|
+
<s:dateRange>
|
21
|
+
<min>
|
22
|
+
20100101
|
23
|
+
</min>
|
24
|
+
<max>
|
25
|
+
20101209
|
26
|
+
</max>
|
27
|
+
</s:dateRange>
|
28
|
+
<s:apiUsageType>
|
29
|
+
UNIT_COUNT
|
30
|
+
</s:apiUsageType>
|
31
|
+
</s:selector>
|
32
|
+
</s:get>
|
33
|
+
</env:Body>
|
34
|
+
</env:Envelope>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
|
2
|
+
<soap:Header>
|
3
|
+
<ResponseHeader xmlns:ns2='https://adwords.google.com/api/adwords/cm/v201008' xmlns='https://adwords.google.com/api/adwords/info/v201008'>
|
4
|
+
<ns2:requestId>
|
5
|
+
ac3eeab49b24416052180a26eab9e1ba
|
6
|
+
</ns2:requestId>
|
7
|
+
<ns2:operations>
|
8
|
+
1
|
9
|
+
</ns2:operations>
|
10
|
+
<ns2:responseTime>
|
11
|
+
171
|
12
|
+
</ns2:responseTime>
|
13
|
+
<ns2:units>
|
14
|
+
1
|
15
|
+
</ns2:units>
|
16
|
+
</ResponseHeader>
|
17
|
+
</soap:Header>
|
18
|
+
<soap:Body>
|
19
|
+
<getResponse xmlns='https://adwords.google.com/api/adwords/info/v201008' xmlns:ns2='https://adwords.google.com/api/adwords/cm/v201008'>
|
20
|
+
<rval>
|
21
|
+
<cost>
|
22
|
+
0
|
23
|
+
</cost>
|
24
|
+
</rval>
|
25
|
+
</getResponse>
|
26
|
+
</soap:Body>
|
27
|
+
</soap:Envelope>
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# -------------------------------------------------------------------------
|
3
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
# -------------------------------------------------------------------------
|
24
|
+
|
25
|
+
require File.expand_path(File.dirname(__FILE__) + '/../rspec_helper')
|
26
|
+
|
27
|
+
describe Operation do
|
28
|
+
include Sem4rSpecHelper
|
29
|
+
|
30
|
+
class MyOperand
|
31
|
+
|
32
|
+
def _xml(t)
|
33
|
+
t.hello
|
34
|
+
end
|
35
|
+
|
36
|
+
def xml(t, tag = nil)
|
37
|
+
if tag
|
38
|
+
t.__send__(tag, {"xsi:type"=>'MyOperand'}) { |t| _xml(t) }
|
39
|
+
else
|
40
|
+
_xml(t)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_xml(tag)
|
45
|
+
xml(Builder::XmlMarkup.new, tag)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should marshal in xml (operation.to_xml)" do
|
50
|
+
op = Operation.add(MyOperand.new)
|
51
|
+
op.to_xml.should == "<operations><operator>ADD</operator><operand xsi:type=\"MyOperand\"><hello/></operand></operations>"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should marshal in xml by builder (operation.xml)" do
|
55
|
+
op = Operation.add(MyOperand.new)
|
56
|
+
builder = Builder::XmlMarkup.new
|
57
|
+
xml = builder.tag!("top") { |t| op.xml(t) }
|
58
|
+
xml.should == "<top><operator>ADD</operator><operand xsi:type=\"MyOperand\"><hello/></operand></top>"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should add attributes to the top tag" do
|
62
|
+
op = Operation.add(MyOperand.new)
|
63
|
+
op.instance_eval { @attrs = {"a" => "b"} }
|
64
|
+
op.to_xml.should == "<operations a=\"b\"><operator>ADD</operator><operand xsi:type=\"MyOperand\"><hello/></operand></operations>"
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should add attribute type to the top tag" do
|
68
|
+
op = Operation.add(MyOperand.new)
|
69
|
+
op.instance_eval { @operation_type = "foo" }
|
70
|
+
op.to_xml.should == "<operations xsi:type=\"foo\"><operator>ADD</operator><operand xsi:type=\"MyOperand\"><hello/></operand></operations>"
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<!-- Post to 'https://adwords-sandbox.google.com/api/adwords/cm/v201008/ReportDefinitionService' -->
|
2
|
+
|
3
|
+
<env:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:env='http://schemas.xmlsoap.org/soap/envelope/' xmlns='https://adwords.google.com/api/adwords/cm/v201008'>
|
4
|
+
<env:Header>
|
5
|
+
<RequestHeader env:mustUnderstand='0'>
|
6
|
+
<authToken>
|
7
|
+
***censured***
|
8
|
+
</authToken>
|
9
|
+
<userAgent>
|
10
|
+
Sem4r Adwords Ruby Client Library (http://github.com/sem4r/sem4r)
|
11
|
+
</userAgent>
|
12
|
+
<developerToken>
|
13
|
+
***censured***
|
14
|
+
</developerToken>
|
15
|
+
</RequestHeader>
|
16
|
+
</env:Header>
|
17
|
+
<env:Body>
|
18
|
+
<get>
|
19
|
+
<selector/>
|
20
|
+
</get>
|
21
|
+
</env:Body>
|
22
|
+
</env:Envelope>
|
@@ -0,0 +1,73 @@
|
|
1
|
+
<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
|
2
|
+
<soap:Header>
|
3
|
+
<ResponseHeader xmlns='https://adwords.google.com/api/adwords/cm/v201008'>
|
4
|
+
<requestId>
|
5
|
+
7839692e0e3dcacb217c8e8aac710566
|
6
|
+
</requestId>
|
7
|
+
<operations>
|
8
|
+
1
|
9
|
+
</operations>
|
10
|
+
<responseTime>
|
11
|
+
245
|
12
|
+
</responseTime>
|
13
|
+
<units>
|
14
|
+
1
|
15
|
+
</units>
|
16
|
+
</ResponseHeader>
|
17
|
+
</soap:Header>
|
18
|
+
<soap:Body>
|
19
|
+
<getResponse xmlns='https://adwords.google.com/api/adwords/cm/v201008'>
|
20
|
+
<rval>
|
21
|
+
<entries>
|
22
|
+
<id>
|
23
|
+
9257
|
24
|
+
</id>
|
25
|
+
<selector>
|
26
|
+
<fields>
|
27
|
+
AdGroupId
|
28
|
+
</fields>
|
29
|
+
<fields>
|
30
|
+
Id
|
31
|
+
</fields>
|
32
|
+
<fields>
|
33
|
+
KeywordText
|
34
|
+
</fields>
|
35
|
+
<fields>
|
36
|
+
KeywordMatchType
|
37
|
+
</fields>
|
38
|
+
<fields>
|
39
|
+
Impressions
|
40
|
+
</fields>
|
41
|
+
<fields>
|
42
|
+
Clicks
|
43
|
+
</fields>
|
44
|
+
<fields>
|
45
|
+
Cost
|
46
|
+
</fields>
|
47
|
+
</selector>
|
48
|
+
<reportName>
|
49
|
+
Keywords performance report #1290336379254
|
50
|
+
</reportName>
|
51
|
+
<reportType>
|
52
|
+
KEYWORDS_PERFORMANCE_REPORT
|
53
|
+
</reportType>
|
54
|
+
<hasAttachment>
|
55
|
+
false
|
56
|
+
</hasAttachment>
|
57
|
+
<dateRangeType>
|
58
|
+
LAST_WEEK
|
59
|
+
</dateRangeType>
|
60
|
+
<downloadFormat>
|
61
|
+
CSV
|
62
|
+
</downloadFormat>
|
63
|
+
<creationTime>
|
64
|
+
20101210 105826 America/Los_Angeles
|
65
|
+
</creationTime>
|
66
|
+
</entries>
|
67
|
+
<totalNumEntries>
|
68
|
+
1
|
69
|
+
</totalNumEntries>
|
70
|
+
</rval>
|
71
|
+
</getResponse>
|
72
|
+
</soap:Body>
|
73
|
+
</soap:Envelope>
|