actv 1.3.11 → 1.4.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.
@@ -1,12 +1,18 @@
1
1
  require 'faraday'
2
2
  require 'actv/article'
3
3
  require 'actv/article_search_results'
4
+ require 'actv/article_validator'
5
+ require 'actv/asset_validator'
4
6
  require 'actv/asset'
7
+ require 'actv/asset_factory'
8
+ require 'actv/author'
9
+ require 'actv/author_validator'
5
10
  require 'actv/configurable'
6
11
  require 'actv/error/forbidden'
7
12
  require 'actv/error/not_found'
8
13
  require 'actv/event'
9
14
  require 'actv/event_result'
15
+ require 'actv/event_validator'
10
16
  require 'actv/asset_stats_result'
11
17
  require 'actv/evergreen'
12
18
  require 'actv/sub_event'
@@ -53,33 +59,10 @@ module ACTV
53
59
  end
54
60
  alias search assets
55
61
 
56
- # Returns an asset with the specified ID in an array
57
- #
58
- # @authentication_required No
59
- # @return [ACTV::Asset] The requested asset.
60
- # @param id [String] An assset ID.
61
- # @param options [Hash] A customizable set of options.
62
- # @example Return the asset with the id BA288960-2718-4B20-B380-8F939596B123
63
- # ACTV.asset("BA288960-2718-4B20-B380-8F939596B123")
64
- def asset(id, params={})
65
- is_preview, params = params_include_preview? params
66
-
67
- if is_preview
68
- request_string = "/v2/assets/#{id}/preview"
69
- response = get("#{request_string}.json", params)
70
- else
71
- request_string = "/v2/assets"
72
- params = params.merge :id => id
73
- response = post("#{request_string}.json", params)
74
- end
75
-
76
- if response[:body].is_a? Array
77
- response[:body].map do |item|
78
- ACTV::Asset.from_response body: item
79
- end
80
- else
81
- [ACTV::Asset.from_response(response)]
82
- end
62
+ def asset id, params={}
63
+ is_preview = params.delete(:preview) == "true"
64
+ response = request_response id, params, is_preview
65
+ asset_from_response response
83
66
  end
84
67
 
85
68
  # Returns an organizer with the specified ID
@@ -380,6 +363,39 @@ module ACTV
380
363
 
381
364
  private
382
365
 
366
+ def request_response id, params, is_preview
367
+ if is_preview
368
+ asset_response_with_preview id, params
369
+ else
370
+ asset_response_without_preview id, params
371
+ end
372
+ end
373
+
374
+ def asset_response_with_preview id, params
375
+ request_string = "/v2/assets/#{id}/preview"
376
+ get "#{request_string}.json", params
377
+ end
378
+
379
+ def asset_response_without_preview id, params
380
+ request_string = "/v2/assets"
381
+ params = params.merge :id => id
382
+ post "#{request_string}.json", params
383
+ end
384
+
385
+ def asset_from_response response
386
+ if response[:body].is_a? Array
387
+ collect_assets response
388
+ else
389
+ Array(ACTV::Asset.from_response response)
390
+ end
391
+ end
392
+
393
+ def collect_assets response
394
+ response[:body].map do |response|
395
+ ACTV::Asset.from_response body: response
396
+ end
397
+ end
398
+
383
399
  def find_by_endurance_id_params endurance_id
384
400
  awe_legacy_guid = 'DFAA997A-D591-44CA-9FB7-BF4A4C8984F1'
385
401
  params = {
@@ -405,6 +421,5 @@ module ACTV
405
421
  params = params.with_indifferent_access
406
422
  return params.delete(:preview) == "true", params
407
423
  end
408
-
409
424
  end
410
425
  end
@@ -1,11 +1,15 @@
1
1
  require 'actv/asset'
2
2
 
3
3
  module ACTV
4
- class Event < ACTV::Asset
4
+ class Event < Asset
5
5
  attr_reader :salesStartDate, :salesEndDate, :activityStartDate, :activityEndDate
6
6
  alias sales_start_date salesStartDate
7
7
  alias sales_end_date salesEndDate
8
8
 
9
+ def self.valid? response
10
+ ACTV::EventValidator.new(response).valid?
11
+ end
12
+
9
13
  def online_registration_available?
10
14
  if is_present?(self.registrationUrlAdr)
11
15
  if is_present?(self.legacy_data) && is_present?(self.legacy_data.onlineRegistration)
@@ -120,8 +124,6 @@ module ACTV
120
124
  place.timezoneOffset + place.timezoneDST
121
125
  end
122
126
 
123
- ############
124
-
125
127
  def image_url
126
128
  defaultImage = 'http://www.active.com/images/events/hotrace.gif'
127
129
  image = ''
@@ -141,6 +143,10 @@ module ACTV
141
143
  image
142
144
  end
143
145
 
146
+ def is_event?
147
+ true
148
+ end
149
+
144
150
  alias online_registration? online_registration_available?
145
151
  alias reg_open? registration_open?
146
152
  alias reg_closed? registration_closed?
@@ -204,7 +210,6 @@ module ACTV
204
210
  return nil if time_string.nil? or time_string.empty?
205
211
  return Time.parse(time_string).utc
206
212
  end
207
-
208
213
  end
209
214
  end
210
215
 
@@ -0,0 +1,8 @@
1
+ require 'actv/asset_validator'
2
+ module ACTV
3
+ class EventValidator < AssetValidator
4
+ def valid?
5
+ category_is?('event') || taxonomy_has?('event')
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module ACTV
2
- VERSION = "1.3.11"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -1,44 +1,154 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ACTV::Article do
4
- context "shoulda matchers" do
5
- subject { ACTV::Article.new(assetGuid: 1) }
6
-
7
- it { should respond_to :summary }
8
- it { should respond_to :description }
9
- it { should respond_to :by_line }
10
- it { should respond_to :author_bio }
11
- it { should respond_to :author_photo }
12
- it { should respond_to :source }
13
- it { should respond_to :type }
14
- it { should respond_to :image }
15
- it { should respond_to :subtitle }
16
- it { should respond_to :footer }
17
- it { should respond_to :inline_ad }
18
- it { should respond_to :inline_ad? }
4
+ let(:descriptions) { [ { description: "article source", descriptionType: { descriptionTypeId: "1", descriptionTypeName: "articleSource" } },
5
+ { description: "article subtitle", descriptionType: { descriptionTypeId: "2", descriptionTypeName: "subtitle" } },
6
+ { description: "by Yason", descriptionType: { descriptionTypeId: "3", descriptionTypeName: "articleByLine" } },
7
+ { description: "article footer", descriptionType: { descriptionTypeId: "4", descriptionTypeName: "footer" } } ] }
8
+ let(:asset_images) { [] }
9
+ let(:asset_categories) { [] }
10
+ let(:asset_tags) { [] }
11
+ let(:asset_references) { [] }
12
+ let(:response) { { assetGuid: 1,
13
+ assetDescriptions: descriptions,
14
+ assetTags: asset_tags,
15
+ assetImages: asset_images,
16
+ assetCategories: asset_categories,
17
+ assetReferences: asset_references } }
18
+ subject(:article) { ACTV::Article.new response }
19
+
20
+ describe '#self.valid?' do
21
+ subject(:valid?) { ACTV::Article.valid? response }
22
+ context 'when the category name is articles' do
23
+ let(:asset_categories) { [ { category: { categoryName: "Articles", categoryTaxonomy: "" } } ] }
24
+ it { should be_true }
25
+ end
26
+ context 'when the category taxonomy is articles' do
27
+ let(:asset_categories) { [ { category: { categoryName: "", categoryTaxonomy: "Creative Work/Articles" } } ] }
28
+ it { should be_true }
29
+ end
30
+ context 'when there is no category taxonomy or name' do
31
+ it { should be_false }
32
+ end
19
33
  end
20
34
 
21
- describe '#inline_ad?' do
22
- context 'if inlindead is set to true' do
23
- let(:article) { ACTV::Article.new(assetGuid: 1, assetTags: [ { tag: { tagId: '1', tagName: 'true', tagDescription: 'inlinead' } } ]) }
24
- it 'should return true' do
25
- article.inline_ad?.should eq true
35
+ describe '#source' do
36
+ context 'when an articleSource description exists' do
37
+ its(:source) { should eq "article source" }
38
+ end
39
+ context 'when an articleSource description does not exist' do
40
+ let(:descriptions) { [] }
41
+ its(:source) { should be_nil }
42
+ end
43
+ end
44
+
45
+ describe '#type' do
46
+ context 'when an articleType tag description exists' do
47
+ let(:asset_tags) { [ { tag: { tagId: '2', tagName: 'mediagallery', tagDescription: 'articleType' } } ] }
48
+ its(:type) { should eq "mediagallery" }
49
+ end
50
+ context 'when an articleType tag description does not exist' do
51
+ its(:type) { should be_nil }
52
+ end
53
+ end
54
+
55
+ describe '#media_gallery?' do
56
+ context 'when the articleType tag is mediagallery' do
57
+ let(:asset_tags) { [ { tag: { tagId: '2', tagName: 'mediagallery', tagDescription: 'articleType' } } ] }
58
+ its(:media_gallery?) { should be_true }
59
+ end
60
+ context 'when the articleType tag is not mediagallery' do
61
+ its(:media_gallery?) { should be_false }
62
+ end
63
+ end
64
+
65
+ describe '#image' do
66
+ context 'when article has an image named image2' do
67
+ let(:asset_images) { [ { imageName: "image2" } ] }
68
+ it 'returns the image' do
69
+ expect(article.image).to be_a ACTV::AssetImage
26
70
  end
27
71
  end
72
+ context 'when article does not have an image named image2' do
73
+ it 'returns nil' do
74
+ expect(article.image).to be_nil
75
+ end
76
+ end
77
+ end
28
78
 
79
+ describe '#subtitle' do
80
+ context 'when a subtitle description exists' do
81
+ its(:subtitle) { should eq "article subtitle" }
82
+ end
83
+ context 'when a subtitle description does not exist' do
84
+ let(:descriptions) { [] }
85
+ its(:subtitle) { should be_nil }
86
+ end
87
+ end
88
+
89
+ describe '#footer' do
90
+ context 'when a footer description exists' do
91
+ its(:footer) { should eq "article footer" }
92
+ end
93
+ context 'when a footer description does not exist' do
94
+ let(:descriptions) { [] }
95
+ its(:footer) { should be_nil }
96
+ end
97
+ end
98
+
99
+ describe '#inline_ad?' do
100
+ context 'if inlindead is set to true' do
101
+ let(:asset_tags) { [ { tag: { tagId: '1', tagName: 'true', tagDescription: 'inlinead' } } ] }
102
+ its(:inline_ad?) { should be_true }
103
+ end
29
104
  context 'if inlindead is set to false' do
30
- let(:article) { ACTV::Article.new(assetGuid: 1, assetTags: [ { tag: { tagId: '1', tagName: 'false', tagDescription: 'inlinead' } } ]) }
31
- it 'should return false' do
32
- article.inline_ad?.should eq false
105
+ let(:asset_tags) { [ { tag: { tagId: '2', tagName: 'false', tagDescription: 'inlinead' } } ] }
106
+ its(:inline_ad?) { should be_false }
107
+ end
108
+ context 'if inlindead is not set' do
109
+ its(:inline_ad?) { should be_true }
110
+ end
111
+ end
112
+
113
+ describe '#author' do
114
+ context 'when an author reference exists' do
115
+ let(:asset_references) { [ { referenceAsset: { assetGuid: "123" }, referenceType: { referenceTypeName: "author" } } ] }
116
+ before do
117
+ stub_request(:post, "http://api.amp.active.com/v2/assets.json").
118
+ to_return(body: fixture("valid_author.json"))
33
119
  end
120
+ context 'when the author exists in a3pi' do
121
+ its(:author) { should be_a ACTV::Author }
122
+ end
123
+ context 'when the author does not exist in a3pi' do
124
+ before do
125
+ allow(ACTV).to receive(:asset).and_raise ACTV::Error::NotFound
126
+ end
127
+ its(:author) { should be_a ACTV::Author }
128
+ end
129
+ end
130
+ context 'when an author reference does not exist' do
131
+ its(:author) { should be_a ACTV::Author }
34
132
  end
133
+ end
35
134
 
36
- context 'if inlindead is not set' do
37
- let(:article) { ACTV::Article.new assetGuid: 1 }
135
+ describe '#is_article?' do
136
+ its(:is_article?) { should be_true }
137
+ end
38
138
 
39
- it 'should return true' do
40
- article.inline_ad?.should eq true
139
+ describe '#author_from_by_line' do
140
+ context 'when a by line is present' do
141
+ context 'when a match is found' do
142
+ its(:author_name_from_by_line) { should eq "Yason" }
41
143
  end
144
+ context 'when a match is not found' do
145
+ let(:descriptions) { [] }
146
+ its(:author_name_from_by_line) { should be_nil }
147
+ end
148
+ end
149
+ context 'when a by line is not present' do
150
+ let(:descriptions) { [] }
151
+ its(:author_name_from_by_line) { should be_nil }
42
152
  end
43
153
  end
44
- end
154
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe ACTV::ArticleValidator do
4
+ let(:asset_categories) { [] }
5
+ let(:response) { { assetGuid: 1, assetCategories: asset_categories } }
6
+ subject(:validator) { ACTV::ArticleValidator.new(response).valid? }
7
+
8
+ describe '#valid?' do
9
+ context 'when the response is valid' do
10
+ context 'because the category name is valid' do
11
+ let(:asset_categories) { [ { category: { categoryName: "Articles", categoryTaxonomy: "" } } ] }
12
+ it { should be_true }
13
+ end
14
+ context 'because the category taxonomy is valid' do
15
+ let(:asset_categories) { [ { category: { categoryName: "", categoryTaxonomy: "Person/Articles" } } ] }
16
+ it { should be_true }
17
+ end
18
+ end
19
+ context 'when the response is not valid' do
20
+ it { should be_false }
21
+ end
22
+ end
23
+ end
@@ -8,11 +8,10 @@ describe ACTV::AssetComponent do
8
8
  describe "#prices" do
9
9
  before(:each) do
10
10
  stub_post("/v2/assets.json").with(:body => {"id"=>true}).
11
- to_return(body: fixture("valid_component_asset.json"), headers: { content_type: "application/json; charset=utf-8" })
11
+ to_return(body: fixture("valid_component_asset.json"), headers: { content_type: "application/json; charset=utf-8" })
12
12
  end
13
13
 
14
14
  it 'returns the prices associated with the component' do
15
- expect(subject.prices).to be_an(Array)
16
15
  expect(subject.prices.first).to be_an(ACTV::AssetPrice)
17
16
  end
18
17
  end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe ACTV::AssetFactory do
4
+ let(:category_name) { "" }
5
+ let(:category_taxonomy) { "" }
6
+ let(:response) { {assetGuid: "111",
7
+ assetCategories: [{category: {categoryName: category_name,
8
+ categoryTaxonomy: category_taxonomy}}]} }
9
+ subject(:asset) { ACTV::AssetFactory.new(response).asset }
10
+
11
+ describe '#asset' do
12
+ context 'the response is not an author, event or article' do
13
+ it { should be_a ACTV::Asset }
14
+ end
15
+ context 'the response has an article category' do
16
+ let(:category_name) { "Articles" }
17
+ it { should be_a ACTV::Article }
18
+ end
19
+ context 'the response has an article taxonomy' do
20
+ let(:category_taxonomy) { "Running/Articles" }
21
+ it { should be_a ACTV::Article }
22
+ end
23
+ context 'the response has an event category' do
24
+ let(:category_name) { "Event" }
25
+ it { should be_a ACTV::Event }
26
+ end
27
+ context 'the response has an event taxonomy' do
28
+ let(:category_taxonomy) { "Race/Event" }
29
+ it { should be_a ACTV::Event }
30
+ end
31
+ context 'the response has an author category' do
32
+ let(:category_name) { "Author" }
33
+ it { should be_a ACTV::Author }
34
+ end
35
+ context 'the response has an author taxonomy' do
36
+ let(:category_taxonomy) { "Running/Author" }
37
+ it { should be_a ACTV::Author }
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ describe ACTV::AssetReference do
3
+ let(:asset_guid) { "123" }
4
+ let(:reference_type_name) { "Meow" }
5
+ let(:reference_hash) { {referenceAsset: {assetGuid: asset_guid},
6
+ referenceType: {referenceTypeName: reference_type_name}} }
7
+ subject(:asset_reference) { ACTV::AssetReference.new reference_hash }
8
+
9
+ describe '#id' do
10
+ it 'returns a guid' do
11
+ expect(asset_reference.id).to eq asset_guid
12
+ end
13
+ end
14
+
15
+ describe '#type' do
16
+ it 'returns a type' do
17
+ expect(asset_reference.type).to eq reference_type_name
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'pry'
3
2
 
4
3
  describe ACTV::Asset do
5
4
 
@@ -190,6 +189,32 @@ describe ACTV::Asset do
190
189
  end
191
190
  end
192
191
 
192
+ describe "is_event?" do
193
+ before(:each) do
194
+ stub_post("/v2/assets.json").with(:body => {"id"=>"valid_event"}).
195
+ to_return(body: fixture("valid_event.json"))
196
+ end
197
+
198
+ it "should return true if the asset has Events as an assetCategory" do
199
+ asset = ACTV.asset('valid_event').first
200
+ asset.is_event?.should be_true
201
+ end
202
+
203
+ it "should return true if the asset has no assetCategories but the sourceSystem is Active.com Articles" do
204
+ asset = ACTV.asset('valid_event').first
205
+ asset.stub(:assetCategories).and_return([])
206
+ asset.is_event?.should be_true
207
+ end
208
+
209
+ it "should return false if no assetCategory of Event" do
210
+ stub_post("/v2/assets.json").with(:body => {"id"=>"valid_article"}).
211
+ to_return(body: fixture("valid_article.json"))
212
+
213
+ asset = ACTV.asset('valid_article').first
214
+ asset.is_event?.should be_false
215
+ end
216
+ end
217
+
193
218
  describe "is_article?" do
194
219
  before(:each) do
195
220
  stub_post("/v2/assets.json").with(:body => {"id"=>"valid_article"}).
@@ -282,7 +307,7 @@ describe ACTV::Asset do
282
307
  end
283
308
  end
284
309
 
285
- context "and articles_source? returns true" do
310
+ context "and acm? returns true" do
286
311
  let(:asset) { ACTV::Asset.new assetGuid: 1, sourceSystem: {legacyGuid: "CA4EA0B1-7377-470D-B20D-BF6BEA23F040"} }
287
312
 
288
313
  context 'and kids_interest? is true' do
@@ -309,7 +334,7 @@ describe ACTV::Asset do
309
334
  asset.stub activenet?: false
310
335
  asset.stub awcamps?: false
311
336
  asset.stub awcamps30?: false
312
- asset.stub articles_source?: false
337
+ asset.stub acm?: false
313
338
  end
314
339
 
315
340
  it 'evaluates to false' do
@@ -485,4 +510,27 @@ describe ACTV::Asset do
485
510
  end
486
511
  end
487
512
 
513
+ describe '#references' do
514
+ let(:asset_references) { [] }
515
+ let(:response) { { assetGuid: 1, assetReferences: asset_references } }
516
+ let(:asset) { ACTV::Asset.new response }
517
+ context 'when there are asset references' do
518
+ let(:asset_references) { [ { referenceAsset: { assetGuid: "123" },
519
+ referenceType: { referenceTypeName: "author" } } ] }
520
+ it 'returns an array of asset reference objects' do
521
+ expect(asset.references.first).to be_a ACTV::AssetReference
522
+ end
523
+ end
524
+ context 'when there are no asset references' do
525
+ it 'returns an empty array' do
526
+ expect(asset.references).to be_empty
527
+ end
528
+ end
529
+ context 'when there is no asset references field' do
530
+ let(:response) { { assetGuid: 1 } }
531
+ it 'returns an empty array' do
532
+ expect(asset.references).to be_empty
533
+ end
534
+ end
535
+ end
488
536
  end