Skip to content

Commit a86646c

Browse files
committed
extends direct page crawler spec
1 parent 43d3e71 commit a86646c

File tree

9 files changed

+226
-19
lines changed

9 files changed

+226
-19
lines changed

Diff for: app/connectors/menards.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ class Menards < BaseConnector
77

88
def process_listing(node)
99
id = node[0]
10-
# sku = node[1]
1110
visit_product_page(id)
1211
fetch_product_attributes(id)
1312
store_product_attributes(@listing_attrs)
@@ -53,6 +52,9 @@ def fetch_product_attributes(menards_id)
5352
vendor_price: driver.doc.at('#totalItemPrice').children.first.text.strip }
5453
end
5554

55+
def store_product_attributes(listing_attrs)
56+
end
57+
5658
private
5759

5860
def page_not_found?

Diff for: app/crawlers/direct_page_access_crawler.rb

+28-10
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@ def fetch_product_nodes(file_path)
1818
end
1919

2020
# Creates listings from
21-
# fetched @nodes
22-
def process_listings(nodes)
23-
@nodes.each_with_index do |node, index|
21+
# injected nodes (default: @nodes)
22+
def process_listings(nodes = @nodes)
23+
nodes.each_with_index do |node, index|
24+
binding.pry
25+
next if invalid_node?(node)
2426
next if data_exists?(node)
25-
next if nil_id?(node)
2627
output_process_info(node, index)
27-
validate_listing(id, sku, index)
28-
index % 20 == 0 ? connector.restart : connector.process_listing(node, index)
28+
# validate_listing(id, sku, index)
29+
dispatch_action(node, index)
30+
# (index != 0 && index % 20 == 0) ? connector.restart : connector.process_listing(node)
2931
end
3032
end
3133

@@ -44,25 +46,41 @@ def validate_connector_type(obj)
4446
# returns 'true' if listing's vendor
4547
# data is present
4648
def data_exists?(node)
47-
if Listing.data_present?(node[1],
48-
connector.abbrev)
49+
if Listing.data_present?(node.values.first, connector.abbrev)
4950
Notifier.raise_data_exists
5051
return true
5152
end
5253
end
5354

5455
# returns 'true' if node's
5556
# 'id' or 'sku' are missing
57+
# or if 'id' is '#N/A'
5658
def invalid_node?(node)
57-
if node[0].nil? || node[1].nil?
59+
if node.keys.first.nil? ||
60+
node.keys.first.empty? ||
61+
node.values.first.nil? ||
62+
node.values.first.empty? ||
63+
node.keys.first.to_s == '#N/A'
5864
Notifier.raise_invalid_node
5965
return true
6066
end
6167
end
6268

6369
# Outputs process info to STDOUT
6470
def output_process_info(node, index)
65-
Notifier.output_process_info(id, sku, index)
71+
Notifier.output_process_info(node, index)
72+
end
73+
74+
# Dispatches action based on current index param
75+
# - when reaches % 20 restarts driver
76+
# - else proceeds with data storing
77+
def dispatch_action(node, index)
78+
case
79+
when index > 0 && index % 20 == 0
80+
connector.restart
81+
else
82+
connector.process_listing(node)
83+
end
6684
end
6785

6886
end

Diff for: app/models/listing.rb

+6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ def self.append_vendor_attrs(sku, attrs)
1818

1919
def self.record_exists?(sku)
2020
find_by(sku: sku).present?
21+
end
2122

23+
# Constructs hash of
24+
# '{ vendor_id: sku }'
25+
# based on vendor injected
26+
def to_node(vendor)
27+
Hash[vendors["#{vendor}"][:vendor_id], sku]
2228
end
2329

2430
def self.get_price(sku)

Diff for: app/utilities/notifier.rb

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
class Notifier
2+
class << self
3+
4+
def output_process_info(node, index)
5+
end
6+
7+
def raise_invalid_node
8+
end
9+
10+
def raise_data_exists
11+
end
12+
13+
end
14+
end

Diff for: spec/connectors/menards_spec.rb

+4
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@
115115

116116
context 'storing product attributes' do
117117

118+
it 'should stor product attributes' do
119+
pending
120+
end
121+
118122
it 'should store product attributes' do
119123
expect_any_instance_of(BaseConnector)
120124
.to receive(:store_attrs)

Diff for: spec/crawlers/direct_page_access_crawler_spec.rb

+156-6
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929
DirectPageAccessCrawler.new(fake_connector)
3030
end
3131

32-
end
32+
end # driver validation
3333

34-
end
34+
end # init
3535

3636
describe 'fetching product nodes' do
3737

@@ -48,18 +48,168 @@
4848
expect(crawler.nodes).to_not be_nil
4949
end
5050

51-
end
51+
end # fetching nodes
5252

5353
describe 'processing' do
5454

55+
before do
56+
57+
allow(connector).to receive(:fetch_product_attributes)
58+
allow(connector).to receive(:store_product_attributes)
59+
end
60+
61+
it 'should iterate through stored nodes' do
62+
csv = "#{Rails.root}/spec/fixtures/CSVs/sample_nodes.csv"
63+
crawler.fetch_product_nodes(csv)
64+
expect(crawler.process_listings).to be_valid
65+
end
66+
5567
it 'should iterate through listing nodes' do
56-
listings = create_list(:listing, 3)
68+
listings = create_list(:listing, 1, :with_menards_attrs)
69+
nodes = [listings.first.to_node('menards')]
5770
expect(connector)
5871
.to receive(:process_listing)
72+
.with(nodes.first)
73+
crawler.process_listings(nodes)
74+
end
75+
76+
it 'should output process details' do
77+
listings = create_list(:listing, 1, :with_menards_attrs)
78+
nodes = [listings.first.to_node('menards')]
79+
expect(crawler)
80+
.to receive(:output_process_info)
5981
.with(nodes.first, 0)
60-
subject.process_listings(nodes)
82+
crawler.process_listings(nodes)
6183
end
6284

63-
end
85+
describe 'node validation' do
86+
87+
it 'should check if node has "sku" and "id" values' do
88+
listings = create_list(:listing, 1, :with_menards_attrs)
89+
node = listings.first.to_node('menards')
90+
allow(connector).to receive(:fetch_product_attributes)
91+
allow(connector).to receive(:store_product_attributes)
92+
expect(crawler)
93+
.to receive(:invalid_node?)
94+
.with(node)
95+
.once
96+
crawler.process_listings([node])
97+
end
98+
99+
context 'when node is invalid' do
100+
101+
describe 'beacuse of an empty id' do
102+
103+
let(:node) { {'': '234' } }
104+
105+
it 'should identify the invalid node' do
106+
expect(crawler.send(:invalid_node?, node))
107+
.to be_truthy
108+
end
109+
110+
it 'should skip invalid node' do
111+
nodes = { 'a': 1, '': 2 }
112+
expect(crawler)
113+
.to receive(:output_process_info)
114+
.once
115+
crawler.process_listings(nodes)
116+
117+
end
118+
119+
it 'should not process invalid node' do
120+
expect(connector)
121+
.to_not receive(:process_listing)
122+
crawler.process_listings([node])
123+
end
124+
125+
it 'should notify of invalid node' do
126+
expect(Notifier)
127+
.to receive(:raise_invalid_node)
128+
crawler.process_listings([node])
129+
end
130+
131+
132+
end
133+
134+
describe 'because of an invalid id' do
135+
136+
let(:node) { { '#N/A': '123' } }
137+
138+
it 'should identify the invalid node' do
139+
expect(crawler.send(:invalid_node?, node))
140+
.to be_truthy
141+
end
142+
143+
it 'should skip listing processing for that node' do
144+
expect(connector)
145+
.to_not receive(:process_listing)
146+
crawler.process_listings([node])
147+
end
148+
149+
it 'should notify of invalid node' do
150+
expect(Notifier)
151+
.to receive(:raise_invalid_node)
152+
crawler.process_listings([node])
153+
end
154+
155+
end
156+
157+
describe 'beacuse of an empty sku' do
158+
159+
let(:node) { {'123': '' } }
160+
161+
it 'should identify the invalid node' do
162+
expect(crawler.send(:invalid_node?, node))
163+
.to be_truthy
164+
end
165+
166+
it 'should skip listing processing for that node' do
167+
expect(connector)
168+
.to_not receive(:process_listing)
169+
crawler.process_listings([node])
170+
end
171+
172+
it 'should notify of invalid node' do
173+
expect(Notifier)
174+
.to receive(:raise_invalid_node)
175+
crawler.process_listings([node])
176+
end
177+
178+
end # empty sku
179+
180+
end # invalid node
181+
182+
end # node validation
183+
184+
describe 'listing data validation' do
185+
186+
it 'should check if listing vendor data already exists' do
187+
listings = create_list(:listing, 1, :with_menards_attrs)
188+
node = listings.first.to_node('menards')
189+
expect(crawler)
190+
.to receive(:data_exists?)
191+
.with(node)
192+
.once
193+
crawler.process_listings([node])
194+
end
195+
196+
context 'when listing vendor data already exists' do
197+
198+
let(:listing) { create(:listing,
199+
:with_menards_attrs,
200+
:with_menards_url) }
201+
202+
it 'should notify about existing data' do
203+
nodes = [listing.to_node('menards')]
204+
expect(Notifier)
205+
.to receive(:raise_data_exists)
206+
crawler.process_listings(nodes)
207+
end
208+
209+
end # when listing.vendors data exists
210+
211+
end # listing data validation
212+
213+
end # listing processing
64214

65215
end

Diff for: spec/factories/listings.rb

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@
66
menards: {
77
vendor_url: Faker::Internet.url,
88
vendor_id: Faker::Number.number(10),
9-
vendor_sku: Faker::Code.isbn,
9+
vendor_sku: sku,
1010
vendor_title: Faker::Commerce.product_name,
1111
vendor_price: Faker::Commerce.price
1212
},
1313
hd: {}
1414
} }
1515
end
16+
1617
trait :with_menards_url do
1718
menards_url Faker::Internet.url
1819
end
20+
1921
end
22+
2023
end

Diff for: spec/fixtures/CSVs/.~lock.sample_nodes.csv#

-1
This file was deleted.

Diff for: spec/models/listing_spec.rb

+11
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,15 @@
7777

7878
end
7979

80+
describe 'helper methods' do
81+
82+
it 'should construct a node hash' do
83+
listing = create(:listing, :with_menards_attrs)
84+
expect(listing.to_node('menards')).to eq(
85+
Hash[listing.sku, listing.vendors[:menards][:vendor_id]]
86+
)
87+
end
88+
89+
end
90+
8091
end

0 commit comments

Comments
 (0)