goods 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +114 -0
- data/Rakefile +1 -0
- data/goods.gemspec +31 -0
- data/lib/goods/catalog.rb +32 -0
- data/lib/goods/categories_list.rb +26 -0
- data/lib/goods/category.rb +54 -0
- data/lib/goods/containable.rb +54 -0
- data/lib/goods/container.rb +58 -0
- data/lib/goods/currencies_list.rb +12 -0
- data/lib/goods/currency.rb +29 -0
- data/lib/goods/offer.rb +43 -0
- data/lib/goods/offers_list.rb +38 -0
- data/lib/goods/version.rb +3 -0
- data/lib/goods/xml/validator.rb +66 -0
- data/lib/goods/xml.rb +129 -0
- data/lib/goods.rb +42 -0
- data/lib/support/shops.dtd +149 -0
- data/spec/fixtures/empty_catalog.xml +15 -0
- data/spec/fixtures/simple_catalog.xml +74 -0
- data/spec/goods/catalog_spec.rb +56 -0
- data/spec/goods/categories_list_spec.rb +42 -0
- data/spec/goods/category_spec.rb +90 -0
- data/spec/goods/currencies_list_spec.rb +5 -0
- data/spec/goods/currency_spec.rb +39 -0
- data/spec/goods/offer_spec.rb +87 -0
- data/spec/goods/offers_list_spec.rb +80 -0
- data/spec/goods/xml/validator_spec.rb +25 -0
- data/spec/goods/xml_spec.rb +178 -0
- data/spec/goods_spec.rb +44 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/shared_examples_for_containable.rb +16 -0
- data/spec/support/shared_examples_for_container.rb +43 -0
- metadata +168 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Goods::Offer do
|
4
|
+
let(:books) { Goods::Category.new(id: "1", name: "Books") }
|
5
|
+
let(:rur) { Goods::Currency.new(id: "RUR", rate: 1, plus: 0) }
|
6
|
+
let(:valid_description) do
|
7
|
+
{id: "1", name: "The Lord of The Rings", category_id: "1", currency_id: "RUR", price: 10}
|
8
|
+
end
|
9
|
+
let(:valid_offer) do
|
10
|
+
offer = Goods::Offer.new(valid_description)
|
11
|
+
offer.category = books
|
12
|
+
offer.currency = rur
|
13
|
+
offer
|
14
|
+
end
|
15
|
+
|
16
|
+
it_should_behave_like "containable" do
|
17
|
+
let(:element) { valid_offer }
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#valid?" do
|
21
|
+
context "invalid cases" do
|
22
|
+
let(:invalid_offer) { Goods::Offer.new({}) }
|
23
|
+
|
24
|
+
[:id, :category_id, :currency_id, :price].each do |field|
|
25
|
+
it "should reject offers without #{field}" do
|
26
|
+
expect(invalid_offer).not_to be_valid
|
27
|
+
expect(invalid_offer.invalid_fields).to include(field)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should reject offers with non-positive price" do
|
32
|
+
invalid_offer = Goods::Offer.new(price: -5.0)
|
33
|
+
expect(invalid_offer).not_to be_valid
|
34
|
+
expect(invalid_offer.invalid_fields).to include(:price)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "valid cases" do
|
39
|
+
it "should accept offer when it has id, category, currency and price" do
|
40
|
+
expect(valid_offer).to be_valid
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
[:available, :description, :model, :name, :picture, :vendor].each do |field|
|
46
|
+
it "should have #{field}" do
|
47
|
+
expect(valid_offer).to respond_to(field)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should have floting point price" do
|
52
|
+
expect(Goods::Offer.new(price: 5).price).to be_kind_of(Float)
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#convert_currency" do
|
56
|
+
let(:usd) { Goods::Currency.new(id: "USD", rate: 30, plus: 0) }
|
57
|
+
|
58
|
+
it "should change currency" do
|
59
|
+
valid_offer.convert_currency(usd)
|
60
|
+
expect(valid_offer.currency).to be(usd)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should leave offer valid" do
|
64
|
+
valid_offer.convert_currency(usd)
|
65
|
+
expect(valid_offer).to be_valid
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should change price according to rate" do
|
69
|
+
valid_offer.convert_currency(usd)
|
70
|
+
expect(valid_offer.price).to eql(1.0/3)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#change_category" do
|
75
|
+
let(:printers) { Goods::Category.new(id: "print", name: "Printers") }
|
76
|
+
|
77
|
+
it "should change category to specified one" do
|
78
|
+
valid_offer.change_category(printers)
|
79
|
+
expect(valid_offer.category).to be(printers)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should leave offer valid" do
|
83
|
+
valid_offer.change_category(printers)
|
84
|
+
expect(valid_offer).to be_valid
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Goods::OffersList do
|
4
|
+
let(:categories) { Goods::CategoriesList.new([{id: "1", name: "Category"}]) }
|
5
|
+
let(:currencies) { Goods::CurrenciesList.new([{id: "RUR", rate: 1, plus: 0}]) }
|
6
|
+
let(:offers) { Goods::OffersList.new(categories, currencies) }
|
7
|
+
let(:subject) { offers }
|
8
|
+
|
9
|
+
it_should_behave_like "a container",
|
10
|
+
Goods::Offer,
|
11
|
+
Goods::Offer.new(id: "1", url: "url.com", category_id: "1", currency_id: "RUR", price: 10) do
|
12
|
+
let(:subject) { offers }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#add" do
|
16
|
+
it "should setup category and currency for offer" do
|
17
|
+
offer = Goods::Offer.new(id: "1", url: "url.com", category_id: "1", currency_id: "RUR", price: 10)
|
18
|
+
subject.add(offer)
|
19
|
+
|
20
|
+
expect(offer.category).to be(categories.find("1"))
|
21
|
+
expect(offer.currency).to be(currencies.find("RUR"))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#prune_categories" do
|
26
|
+
let(:categories) do
|
27
|
+
list = Goods::CategoriesList.new [
|
28
|
+
{id: "1", name: "root"},
|
29
|
+
{id: "11", name: "root", parent_id: "1"},
|
30
|
+
{id: "12", name: "root", parent_id: "11"}
|
31
|
+
]
|
32
|
+
list
|
33
|
+
end
|
34
|
+
let(:offers) do
|
35
|
+
list = Goods::OffersList.new categories, currencies, [
|
36
|
+
{id: "1", category_id: "1", currency_id: "RUR", price: 1},
|
37
|
+
{id: "2", category_id: "11", currency_id: "RUR", price: 1},
|
38
|
+
{id: "3", category_id: "12", currency_id: "RUR", price: 1}
|
39
|
+
]
|
40
|
+
list
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should raise error if level < 0" do
|
44
|
+
expect{ offers.prune_categories }.to raise_error(ArgumentError)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should replace deep categories with their parents on specified level" do
|
48
|
+
offers.prune_categories(1)
|
49
|
+
expect(offers.find("3").category).to be(categories.find("11"))
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should not affect offers with categories having lower level" do
|
53
|
+
offers.prune_categories(1)
|
54
|
+
expect(offers.find("1").category).to be(categories.find("1"))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#convert_currency" do
|
59
|
+
let(:currencies) do
|
60
|
+
Goods::CurrenciesList.new([
|
61
|
+
{id: "RUR", rate: 1, plus: 0},
|
62
|
+
{id: "USD", rate: 30, plus: 0},
|
63
|
+
{id: "GBP", rate: 50, plus: 0}
|
64
|
+
])
|
65
|
+
end
|
66
|
+
let(:offers) do
|
67
|
+
list = Goods::OffersList.new categories, currencies, [
|
68
|
+
{id: "1", category_id: "1", currency_id: "USD", price: 1},
|
69
|
+
{id: "2", category_id: "1", currency_id: "GBP", price: 1}
|
70
|
+
]
|
71
|
+
list
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should convert currency for all offers" do
|
75
|
+
expect(offers.find("1")).to receive(:convert_currency)
|
76
|
+
expect(offers.find("2")).to receive(:convert_currency)
|
77
|
+
offers.convert_currency(currencies.find("RUR"))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Goods::XML::Validator do
|
4
|
+
let(:valid_document) { File.read(File.expand_path("../../../fixtures/simple_catalog.xml", __FILE__)) }
|
5
|
+
let(:invalid_document) { File.read(File.expand_path("../../../fixtures/empty_catalog.xml", __FILE__)) }
|
6
|
+
|
7
|
+
describe "#valid?" do
|
8
|
+
it "should return true if document is valid according to dtd" do
|
9
|
+
validator = Goods::XML::Validator.new
|
10
|
+
expect(validator.valid? valid_document).to eql(true)
|
11
|
+
expect(validator.error).to be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return false if document is not valid" do
|
15
|
+
validator = Goods::XML::Validator.new
|
16
|
+
expect(validator.valid? invalid_document).to eql(false)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should have non-empty errors if document is not valid" do
|
20
|
+
validator = Goods::XML::Validator.new
|
21
|
+
validator.valid? invalid_document
|
22
|
+
expect(validator.error).not_to be_nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Goods::XML do
|
4
|
+
let(:simple_catalog_data) do
|
5
|
+
File.read(File.expand_path('../../fixtures/simple_catalog.xml', __FILE__))
|
6
|
+
end
|
7
|
+
let(:simple_catalog) { Goods::XML.new(simple_catalog_data) }
|
8
|
+
SIMPLE_CATALOG_CATEGORIES_COUNT = 9
|
9
|
+
SIMPLE_CATALOG_CURRENCIES_COUNT = 3
|
10
|
+
SIMPLE_CATALOG_OFFERS_COUNT = 2
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
it 'should use Nokogiri for parsing' do
|
14
|
+
params = ["string", "url", "encoding"]
|
15
|
+
expect(Nokogiri::XML::Document).to receive(:parse).with(*params)
|
16
|
+
|
17
|
+
Goods::XML.new(*params)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should parse valid document' do
|
21
|
+
expect(simple_catalog.instance_variable_get("@xml_source")).to be_kind_of(Nokogiri::XML::Document)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#categories" do
|
26
|
+
let(:categories) { simple_catalog.categories }
|
27
|
+
|
28
|
+
it "should extract all categories" do
|
29
|
+
expect(categories.count).to eq(SIMPLE_CATALOG_CATEGORIES_COUNT)
|
30
|
+
end
|
31
|
+
|
32
|
+
context "category format" do
|
33
|
+
let(:root_category) { categories[0] }
|
34
|
+
let(:child_category) { categories[1] }
|
35
|
+
|
36
|
+
it "should have an id" do
|
37
|
+
expect(root_category[:id]).to eq("1")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should have a name" do
|
41
|
+
expect(root_category[:name]).to eq("Оргтехника")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have nil parent_id for root category" do
|
45
|
+
expect(root_category[:parent_id]).to be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should have non-nil parent_id for child_category" do
|
49
|
+
expect(child_category[:parent_id]).to eq("1")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should call #extract_categories only at the first invocation' do
|
54
|
+
expect_any_instance_of(Goods::XML).to receive(:extract_categories).once.and_call_original
|
55
|
+
2.times { simple_catalog.categories }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#currencies" do
|
60
|
+
it "should extract all currencies" do
|
61
|
+
expect(simple_catalog.currencies.count).to eq(SIMPLE_CATALOG_CURRENCIES_COUNT)
|
62
|
+
end
|
63
|
+
|
64
|
+
context "currency format" do
|
65
|
+
let(:rur) { simple_catalog.currencies[0] }
|
66
|
+
let(:usd) { simple_catalog.currencies[1] }
|
67
|
+
let(:kzt) { simple_catalog.currencies[2] }
|
68
|
+
|
69
|
+
it "should have an id" do
|
70
|
+
expect(rur[:id]).to eq("RUR")
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should have a rate" do
|
74
|
+
expect(rur[:rate]).to eq("1")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should have a custom rate" do
|
78
|
+
expect(usd[:rate]).to eq("30")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should have a default rate" do
|
82
|
+
expect(kzt[:rate]).to eq("1")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should have a plus" do
|
86
|
+
expect(rur[:plus]).to eq("0")
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should have a default plus" do
|
90
|
+
expect(kzt[:plus]).to eq("0")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should call #extract_currencies only at the first invocation' do
|
95
|
+
expect_any_instance_of(Goods::XML).to receive(:extract_currencies).once.and_call_original
|
96
|
+
2.times { simple_catalog.currencies }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "#offers" do
|
101
|
+
it 'should extract all offers' do
|
102
|
+
expect(simple_catalog.offers.count).to eq(SIMPLE_CATALOG_OFFERS_COUNT)
|
103
|
+
end
|
104
|
+
|
105
|
+
context "offer format" do
|
106
|
+
let(:printer) { simple_catalog.offers[0] }
|
107
|
+
let(:book) { simple_catalog.offers[1] }
|
108
|
+
|
109
|
+
it "should have an id" do
|
110
|
+
expect(printer[:id]).to eq("123")
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should have availability status" do
|
114
|
+
expect(book[:available]).to eq(false)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should have default availability status" do
|
118
|
+
expect(printer[:available]).to eq(true)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should have a URL which is not empty" do
|
122
|
+
expect(printer[:url]).to eq("http://magazin.ru/product_page.asp?pid=14344")
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should have a nil URL if offer doesn't have one" do
|
126
|
+
expect(book[:url]).to be_nil
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should have a price" do
|
130
|
+
expect(printer[:price]).to eq(15000.00)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should have a currency_id" do
|
134
|
+
expect(printer[:currency_id]).to eq("RUR")
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should use first category_id" do
|
138
|
+
expect(printer[:category_id]).to eq("100")
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should use first picture if there at least one" do
|
142
|
+
expect(printer[:picture]).to eq("http://magazin.ru/img/device1.jpg")
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should have a nil picture if offer doesn't have one" do
|
146
|
+
expect(book[:picture]).to be_nil
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should have a description" do
|
150
|
+
expect(printer[:description]).to eq("A4, 64Mb, 600x600 dpi, USB 2.0, 29стр/мин ч/б / 15стр/мин цв, лотки на 100л и 250л, плотность до 175г/м, до 60000 стр/месяц")
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should have a non-empty name" do
|
154
|
+
expect(book[:name]).to eq("Все не так. В 2 томах. Том 1")
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should have a nil name if offer doesn't have one" do
|
158
|
+
expect(printer[:name]).to be_nil
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should have a non-empty vendor" do
|
162
|
+
expect(printer[:vendor]).to eq("НP")
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should have a nil vendor if offer doesn't have one" do
|
166
|
+
expect(book[:vendor]).to be_nil
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should have a non-empty model" do
|
170
|
+
expect(printer[:model]).to eq("Color LaserJet 3000")
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should have a nil model if offer doesn't have one" do
|
174
|
+
expect(book[:model]).to be_nil
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
data/spec/goods_spec.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Goods do
|
4
|
+
it 'should have a version number' do
|
5
|
+
expect(Goods::VERSION).to_not be_nil
|
6
|
+
end
|
7
|
+
|
8
|
+
describe ".from_string" do
|
9
|
+
let(:valid_document) { File.read(File.expand_path("../fixtures/simple_catalog.xml", __FILE__)) }
|
10
|
+
let(:invalid_document) { File.read(File.expand_path("../fixtures/empty_catalog.xml", __FILE__)) }
|
11
|
+
|
12
|
+
it "should return catalog if valid xml file is passed" do
|
13
|
+
expect(Goods::Catalog).to receive(:new).
|
14
|
+
with({string: valid_document, url: "url", encoding: "UTF-8"})
|
15
|
+
Goods.from_string(valid_document, "url", "UTF-8")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise error if invalid file is passed" do
|
19
|
+
expect { Goods.from_string(invalid_document) }.to raise_error(Goods::XML::InvalidFormatError)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe ".from_file" do
|
24
|
+
it "should load file and call .from_string" do
|
25
|
+
params = {
|
26
|
+
file: "file", string: "string", url: nil, encoding: "UTF-8"
|
27
|
+
}
|
28
|
+
expect(Goods).to receive(:load).with(params[:file]) { params[:string] }
|
29
|
+
expect(Goods).to receive(:from_string).with(params[:string], nil, params[:encoding])
|
30
|
+
Goods.from_file params[:file], params[:encoding]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".from_url" do
|
35
|
+
it "should load remote page and call .from_string" do
|
36
|
+
params = {
|
37
|
+
string: "string", url: "url", encoding: "UTF-8"
|
38
|
+
}
|
39
|
+
expect(Goods).to receive(:load).with(params[:url]) { params[:string] }
|
40
|
+
expect(Goods).to receive(:from_string).with(params[:string], params[:url], params[:encoding])
|
41
|
+
Goods.from_url params[:url], params[:encoding]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'goods'
|
3
|
+
|
4
|
+
Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f }
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
# Limit the spec run to only specs with the focus metadata. If no specs have
|
8
|
+
# the filtering metadata and `run_all_when_everything_filtered = true` then
|
9
|
+
# all specs will run.
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run all specs when none match the provided filter. This works well in
|
13
|
+
# conjunction with `config.filter_run :focus`, as it will run the entire
|
14
|
+
# suite when no specs have `:filter` metadata.
|
15
|
+
config.run_all_when_everything_filtered = true
|
16
|
+
|
17
|
+
# Run specs in random order to surface order dependencies. If you find an
|
18
|
+
# order dependency and want to debug it, you can fix the order by providing
|
19
|
+
# the seed, which is printed after each run.
|
20
|
+
# --seed 1234
|
21
|
+
#config.order = 'random'
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
shared_examples "containable" do
|
2
|
+
[:description, :id, :invalid_fields].each do |prop|
|
3
|
+
it "should give access to #{prop}" do
|
4
|
+
expect(element).to respond_to(prop)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "#reset_validation" do
|
9
|
+
it "should clear invalid_fields" do
|
10
|
+
element.instance_variable_set("@invalid_fields", [:a, :b])
|
11
|
+
expect(element.invalid_fields.size).to eql(2)
|
12
|
+
element.send :reset_validation
|
13
|
+
expect(element.invalid_fields).to be_empty
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
shared_examples "a container" do |containable_class, element|
|
2
|
+
describe "#add" do
|
3
|
+
context "when hash is passed" do
|
4
|
+
it "should at first create an object" do
|
5
|
+
expect(containable_class).to receive(:new) { element }
|
6
|
+
subject.add({})
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context "when object is passed" do
|
11
|
+
it "should not create new object" do
|
12
|
+
expect(containable_class).to_not receive(:new)
|
13
|
+
subject.add element
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should add to list valid elements" do
|
17
|
+
expect { subject.add(element) }.to change(subject, :size).by(1)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should remember invalid elements" do
|
21
|
+
allow(element).to receive(:valid?).and_return(false)
|
22
|
+
expect { subject.add(element) }.to change(subject.defectives, :size).by(1)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#find" do
|
28
|
+
[:one, :two].each do |el|
|
29
|
+
let(el) {
|
30
|
+
el = containable_class.new({})
|
31
|
+
allow(el).to receive(:valid?) { true }
|
32
|
+
allow(el).to receive(:id) { el.to_s.upcase }
|
33
|
+
el
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return element with correct id" do
|
38
|
+
subject.add(one); subject.add(two)
|
39
|
+
expect(subject.size).to eq(2)
|
40
|
+
expect(subject.find(one.id)).to eq(one)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: goods
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Artem Pyanykh
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0.beta1
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0.beta1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: libxml-ruby
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: nokogiri
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: |2
|
84
|
+
The purpose of this gem is to provide simple, yet reliable solution for parsing
|
85
|
+
YML (Yandex Market Language) files, with clean and convenient interface,
|
86
|
+
and extra capabilites, such as categories prunning.
|
87
|
+
email:
|
88
|
+
- artem.pyanykh@gmail.com
|
89
|
+
executables: []
|
90
|
+
extensions: []
|
91
|
+
extra_rdoc_files: []
|
92
|
+
files:
|
93
|
+
- .gitignore
|
94
|
+
- .rspec
|
95
|
+
- Gemfile
|
96
|
+
- LICENSE.txt
|
97
|
+
- README.md
|
98
|
+
- Rakefile
|
99
|
+
- goods.gemspec
|
100
|
+
- lib/goods.rb
|
101
|
+
- lib/goods/catalog.rb
|
102
|
+
- lib/goods/categories_list.rb
|
103
|
+
- lib/goods/category.rb
|
104
|
+
- lib/goods/containable.rb
|
105
|
+
- lib/goods/container.rb
|
106
|
+
- lib/goods/currencies_list.rb
|
107
|
+
- lib/goods/currency.rb
|
108
|
+
- lib/goods/offer.rb
|
109
|
+
- lib/goods/offers_list.rb
|
110
|
+
- lib/goods/version.rb
|
111
|
+
- lib/goods/xml.rb
|
112
|
+
- lib/goods/xml/validator.rb
|
113
|
+
- lib/support/shops.dtd
|
114
|
+
- spec/fixtures/empty_catalog.xml
|
115
|
+
- spec/fixtures/simple_catalog.xml
|
116
|
+
- spec/goods/catalog_spec.rb
|
117
|
+
- spec/goods/categories_list_spec.rb
|
118
|
+
- spec/goods/category_spec.rb
|
119
|
+
- spec/goods/currencies_list_spec.rb
|
120
|
+
- spec/goods/currency_spec.rb
|
121
|
+
- spec/goods/offer_spec.rb
|
122
|
+
- spec/goods/offers_list_spec.rb
|
123
|
+
- spec/goods/xml/validator_spec.rb
|
124
|
+
- spec/goods/xml_spec.rb
|
125
|
+
- spec/goods_spec.rb
|
126
|
+
- spec/spec_helper.rb
|
127
|
+
- spec/support/shared_examples_for_containable.rb
|
128
|
+
- spec/support/shared_examples_for_container.rb
|
129
|
+
homepage: https://github.com/ArtemPyanykh/goods
|
130
|
+
licenses:
|
131
|
+
- MIT
|
132
|
+
metadata: {}
|
133
|
+
post_install_message:
|
134
|
+
rdoc_options: []
|
135
|
+
require_paths:
|
136
|
+
- lib
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - '>='
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
requirements: []
|
148
|
+
rubyforge_project:
|
149
|
+
rubygems_version: 2.1.11
|
150
|
+
signing_key:
|
151
|
+
specification_version: 4
|
152
|
+
summary: Simple parser for YML (Yandex Market Language) files with a few twists.
|
153
|
+
test_files:
|
154
|
+
- spec/fixtures/empty_catalog.xml
|
155
|
+
- spec/fixtures/simple_catalog.xml
|
156
|
+
- spec/goods/catalog_spec.rb
|
157
|
+
- spec/goods/categories_list_spec.rb
|
158
|
+
- spec/goods/category_spec.rb
|
159
|
+
- spec/goods/currencies_list_spec.rb
|
160
|
+
- spec/goods/currency_spec.rb
|
161
|
+
- spec/goods/offer_spec.rb
|
162
|
+
- spec/goods/offers_list_spec.rb
|
163
|
+
- spec/goods/xml/validator_spec.rb
|
164
|
+
- spec/goods/xml_spec.rb
|
165
|
+
- spec/goods_spec.rb
|
166
|
+
- spec/spec_helper.rb
|
167
|
+
- spec/support/shared_examples_for_containable.rb
|
168
|
+
- spec/support/shared_examples_for_container.rb
|