simple_shipping 0.4.6
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/.document +5 -0
- data/.metrics +6 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.simplecov +43 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +201 -0
- data/LICENSE.txt +21 -0
- data/README.markdown +207 -0
- data/Rakefile +68 -0
- data/VERSION +1 -0
- data/coverage/.resultset.json +1579 -0
- data/lib/colorized_text.rb +34 -0
- data/lib/simple_shipping.rb +27 -0
- data/lib/simple_shipping/abstract.rb +11 -0
- data/lib/simple_shipping/abstract/builder.rb +47 -0
- data/lib/simple_shipping/abstract/client.rb +111 -0
- data/lib/simple_shipping/abstract/model.rb +40 -0
- data/lib/simple_shipping/abstract/request.rb +27 -0
- data/lib/simple_shipping/abstract/response.rb +26 -0
- data/lib/simple_shipping/address.rb +22 -0
- data/lib/simple_shipping/contact.rb +24 -0
- data/lib/simple_shipping/demo.rb +9 -0
- data/lib/simple_shipping/demo/base.rb +71 -0
- data/lib/simple_shipping/demo/fedex.rb +46 -0
- data/lib/simple_shipping/demo/ups.rb +68 -0
- data/lib/simple_shipping/exceptions.rb +40 -0
- data/lib/simple_shipping/fedex.rb +14 -0
- data/lib/simple_shipping/fedex/client.rb +41 -0
- data/lib/simple_shipping/fedex/package_builder.rb +24 -0
- data/lib/simple_shipping/fedex/party_builder.rb +50 -0
- data/lib/simple_shipping/fedex/request.rb +54 -0
- data/lib/simple_shipping/fedex/response.rb +5 -0
- data/lib/simple_shipping/fedex/shipment_builder.rb +123 -0
- data/lib/simple_shipping/fedex/shipment_request.rb +14 -0
- data/lib/simple_shipping/fedex/shipment_response.rb +12 -0
- data/lib/simple_shipping/package.rb +43 -0
- data/lib/simple_shipping/party.rb +21 -0
- data/lib/simple_shipping/shipment.rb +42 -0
- data/lib/simple_shipping/ups.rb +24 -0
- data/lib/simple_shipping/ups/client.rb +46 -0
- data/lib/simple_shipping/ups/package_builder.rb +101 -0
- data/lib/simple_shipping/ups/party_builder.rb +38 -0
- data/lib/simple_shipping/ups/request.rb +27 -0
- data/lib/simple_shipping/ups/response.rb +63 -0
- data/lib/simple_shipping/ups/ship_accept_request.rb +21 -0
- data/lib/simple_shipping/ups/ship_accept_response.rb +6 -0
- data/lib/simple_shipping/ups/ship_client.rb +70 -0
- data/lib/simple_shipping/ups/ship_confirm_request.rb +22 -0
- data/lib/simple_shipping/ups/ship_confirm_response.rb +6 -0
- data/lib/simple_shipping/ups/shipment_builder.rb +66 -0
- data/lib/simple_shipping/ups/shipment_request.rb +22 -0
- data/lib/simple_shipping/ups/shipment_response.rb +6 -0
- data/lib/simple_shipping/ups/void_client.rb +50 -0
- data/lib/simple_shipping/ups/void_request.rb +42 -0
- data/lib/simple_shipping/ups/void_response.rb +6 -0
- data/lib/tasks/demo.rake +58 -0
- data/script/ups_certification.rb +140 -0
- data/simple_shipping.gemspec +168 -0
- data/spec/fixtures/fedex_shipment_request.soap.xml.erb +85 -0
- data/spec/fixtures/fedex_shipment_response.soap.xml.erb +182 -0
- data/spec/fixtures/ups_shipment_request.soap.xml.erb +88 -0
- data/spec/fixtures/ups_shipment_response.soap.xml.erb +58 -0
- data/spec/fixtures/ups_shipment_response_with_faked_label_data.soap.xml.erb +54 -0
- data/spec/fixtures/ups_void_request.soap.xml.erb +29 -0
- data/spec/fixtures/ups_void_response.soap.xml.erb +21 -0
- data/spec/lib/simple_shipping/address_spec.rb +19 -0
- data/spec/lib/simple_shipping/contact_spec.rb +28 -0
- data/spec/lib/simple_shipping/exceptions_spec.rb +58 -0
- data/spec/lib/simple_shipping/fedex/package_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/party_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response/shipment_reponse_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/shipment_builder_spec.rb +23 -0
- data/spec/lib/simple_shipping/package_spec.rb +32 -0
- data/spec/lib/simple_shipping/party_spec.rb +18 -0
- data/spec/lib/simple_shipping/shipment_spec.rb +35 -0
- data/spec/lib/simple_shipping/ups/package_builder_spec.rb +26 -0
- data/spec/lib/simple_shipping/ups/party_builder_spec.rb +47 -0
- data/spec/lib/simple_shipping/ups/response/shipment_response_spec.rb +5 -0
- data/spec/lib/simple_shipping/ups/response_spec.rb +33 -0
- data/spec/lib/simple_shipping/ups/shipment_builder_spec.rb +19 -0
- data/spec/requests/fedex_spec.rb +47 -0
- data/spec/requests/ups_spec.rb +75 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/custom_matchers/basic_matcher.rb +13 -0
- data/spec/support/custom_matchers/have_attribute_matcher.rb +22 -0
- data/spec/support/custom_matchers/have_default_value_matcher.rb +26 -0
- data/spec/support/custom_matchers/have_errors_on_matcher.rb +23 -0
- data/spec/support/custom_matchers/validate_inclusion_of_matcher.rb +37 -0
- data/spec/support/custom_matchers/validate_presence_of_matcher.rb +24 -0
- data/spec/support/custom_matchers/validate_submodel_matcher.rb +44 -0
- data/spec/support/shared_behaviours/builders_behaviour.rb +9 -0
- data/spec/support/shared_behaviours/responses_behaviour.rb +10 -0
- data/tmp/metric_fu/_data/20131210.yml +9964 -0
- data/wsdl/fedex/ship_service_v10.wsdl +5566 -0
- data/wsdl/ups/Ship.wsdl +120 -0
- data/wsdl/ups/Void.wsdl +58 -0
- metadata +308 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SimpleShipping::Ups
|
4
|
+
describe PartyBuilder do
|
5
|
+
it_should_behave_like "builders"
|
6
|
+
|
7
|
+
it 'validate account number if party is shipper' do
|
8
|
+
shipper = SimpleShipping::Party.new
|
9
|
+
|
10
|
+
shipper.stub!(:valid? => true)
|
11
|
+
lambda {
|
12
|
+
PartyBuilder.build(shipper, :shipper => true)
|
13
|
+
}.should raise_error SimpleShipping::ValidationError
|
14
|
+
|
15
|
+
shipper.stub!(:account_number => '123')
|
16
|
+
lambda {
|
17
|
+
PartyBuilder.build(shipper, :shipper => true)
|
18
|
+
}.should_not raise_error SimpleShipping::ValidationError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "build" do
|
23
|
+
it "should include all addresses" do
|
24
|
+
contact = SimpleShipping::Contact.new(:phone_number => "5555555555", :person_name => "Frank")
|
25
|
+
address = SimpleShipping::Address.new(:country_code => "US", :state_code => "IL", :city => "Chicago", :postal_code => "60622")
|
26
|
+
address.street_line = "foo"
|
27
|
+
address.street_line_2 = "bar"
|
28
|
+
address.street_line_3 = "baz"
|
29
|
+
|
30
|
+
shipper = SimpleShipping::Party.new(:contact => contact, :address => address)
|
31
|
+
party = PartyBuilder.build(shipper)
|
32
|
+
party['Address']['AddressLine'].should have(3).addresses
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should exclude nil addresses" do
|
36
|
+
contact = SimpleShipping::Contact.new(:phone_number => "5555555555", :person_name => "Frank")
|
37
|
+
address = SimpleShipping::Address.new(:country_code => "US", :state_code => "IL", :city => "Chicago", :postal_code => "60622")
|
38
|
+
address.street_line = "foo"
|
39
|
+
address.street_line_2 = nil
|
40
|
+
address.street_line_3 = "baz"
|
41
|
+
|
42
|
+
shipper = SimpleShipping::Party.new(:contact => contact, :address => address)
|
43
|
+
party = PartyBuilder.build(shipper)
|
44
|
+
party['Address']['AddressLine'].should have(2).addresses
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleShipping::Ups::Response do
|
4
|
+
it_should_behave_like "responses"
|
5
|
+
|
6
|
+
context "when success response is received" do
|
7
|
+
subject { response }
|
8
|
+
|
9
|
+
let(:response_fixture) { fixture("ups_shipment_response") }
|
10
|
+
let(:http_response) { ::HTTPI::Response.new(200, {}, response_fixture) }
|
11
|
+
let(:savon_response) do
|
12
|
+
::Savon::Response.new(
|
13
|
+
http_response,
|
14
|
+
{
|
15
|
+
strip_namespaces: true,
|
16
|
+
convert_response_tags_to: ->(tag) { tag.snakecase.to_sym }
|
17
|
+
},
|
18
|
+
{}
|
19
|
+
)
|
20
|
+
end
|
21
|
+
let(:response) { ::SimpleShipping::Ups::ShipmentResponse.new(savon_response) }
|
22
|
+
|
23
|
+
its(:shipment_identification_number) { should eq("1Z35679R0294268838") }
|
24
|
+
its(:tracking_number) { should eq("1Z35679R0294268838") }
|
25
|
+
|
26
|
+
describe "label image" do
|
27
|
+
let(:response_fixture) { fixture("ups_shipment_response_with_faked_label_data") }
|
28
|
+
|
29
|
+
# HTML_IMAGE_DATA is the Base64 decoded version of SFRNTF9JTUFHRV9EQVRB
|
30
|
+
its(:label_html) { should eq("HTML_IMAGE_DATA") }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleShipping::Ups::ShipmentBuilder do
|
4
|
+
it_should_behave_like "builders"
|
5
|
+
|
6
|
+
describe 'validation' do
|
7
|
+
it 'validates inclusion of service_types' do
|
8
|
+
shipment = SimpleShipping::Shipment.new
|
9
|
+
shipment.stub!(:valid? => true)
|
10
|
+
|
11
|
+
lambda {
|
12
|
+
SimpleShipping::Ups::ShipmentBuilder.build(shipment, :service_type => :ground)
|
13
|
+
}.should_not raise_error SimpleShipping::ValidationError
|
14
|
+
lambda {
|
15
|
+
SimpleShipping::Ups::ShipmentBuilder.build(shipment, :service_type => :bad)
|
16
|
+
}.should raise_error SimpleShipping::ValidationError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "FedEx integration test" do
|
4
|
+
before { Timecop.freeze }
|
5
|
+
after { Timecop.return }
|
6
|
+
|
7
|
+
#let(:credentials) do
|
8
|
+
# YAML.load_file(SimpleShipping::DEMO_CREDENTIALS_FILE)['fedex'].symbolize_keys!
|
9
|
+
#end
|
10
|
+
|
11
|
+
let(:credentials) {{
|
12
|
+
:key => 'fedex key',
|
13
|
+
:password => 'secret word',
|
14
|
+
:account_number => '101010101',
|
15
|
+
:meter_number => '202020202'
|
16
|
+
}}
|
17
|
+
|
18
|
+
let(:demo) do
|
19
|
+
options = credentials.merge(:live => false)
|
20
|
+
SimpleShipping::Demo::Fedex.new(options)
|
21
|
+
end
|
22
|
+
|
23
|
+
context "#shipment_request" do
|
24
|
+
it "builds correct SOAP request envelope" do
|
25
|
+
req_matcher = lambda do |req|
|
26
|
+
expected = Nokogiri::XML(fixture(:fedex_shipment_request, credentials))
|
27
|
+
actual = Nokogiri::XML(req.body)
|
28
|
+
|
29
|
+
actual.root.should be_equivalent_to(expected.root).respecting_element_order
|
30
|
+
|
31
|
+
req.headers['Soapaction'].should == %{"processShipment"}
|
32
|
+
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
req = stub_http_request(:post, demo.fedex_client.class.testing_address).
|
37
|
+
with(&req_matcher).
|
38
|
+
to_return(:body => fixture(:fedex_shipment_response), :status => 200, :headers => {})
|
39
|
+
|
40
|
+
resp = demo.shipment_request
|
41
|
+
|
42
|
+
resp.label_image_base64.should be_present
|
43
|
+
|
44
|
+
req.should have_been_made
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "UPS test" do
|
4
|
+
let(:credentials) {{
|
5
|
+
:username => "Joe13",
|
6
|
+
:password => "JoesSecretWord",
|
7
|
+
:account_number => "1010101",
|
8
|
+
:access_license_number => "Joe's license"
|
9
|
+
}}
|
10
|
+
|
11
|
+
let(:demo) do
|
12
|
+
options = credentials.merge!(:live => false)
|
13
|
+
SimpleShipping::Demo::Ups.new(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:erb_request_vars) do
|
17
|
+
credentials.merge(:shipment_identification_number => demo.shipment_identification_number)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "ship_client" do
|
21
|
+
describe "#shipment_request" do
|
22
|
+
it "builds correct SOAP request envelope" do
|
23
|
+
req_matcher = lambda do |req|
|
24
|
+
expected = Nokogiri::XML(fixture(:ups_shipment_request, erb_request_vars))
|
25
|
+
actual = Nokogiri::XML(req.body)
|
26
|
+
|
27
|
+
actual.root.should be_equivalent_to(expected.root)
|
28
|
+
#actual.root.to_s.should == expected.root.to_s
|
29
|
+
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
req = stub_http_request(:post, demo.ship_client.class.testing_address).
|
34
|
+
with(&req_matcher).
|
35
|
+
to_return(:body => fixture(:ups_shipment_response), :status => 200, :headers => {})
|
36
|
+
|
37
|
+
resp = demo.shipment_request(
|
38
|
+
|
39
|
+
)
|
40
|
+
|
41
|
+
|
42
|
+
resp.label_image_base64.should be_present
|
43
|
+
|
44
|
+
req.should have_been_made
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "void client" do
|
50
|
+
describe "#void_request" do
|
51
|
+
it "builds correct SOAP request envelope" do
|
52
|
+
req_matcher = lambda do |req|
|
53
|
+
expected = Nokogiri::XML(fixture(:ups_void_request, erb_request_vars))
|
54
|
+
actual = Nokogiri::XML(req.body)
|
55
|
+
|
56
|
+
actual.root.should be_equivalent_to(expected.root)
|
57
|
+
#actual.root.to_s.should == expected.root.to_s
|
58
|
+
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
req = stub_http_request(:post, demo.void_client.class.testing_address).
|
63
|
+
with(&req_matcher).
|
64
|
+
to_return(:body => fixture(:ups_void_response), :status => 200, :headers => {})
|
65
|
+
|
66
|
+
expect{ demo.void_request }.to(
|
67
|
+
# NOTE: Exception message is important! This is how we can find out whether SOAP request was made correct -- aignatyev 20130204
|
68
|
+
raise_exception(SimpleShipping::RequestError, /No shipment found within the allowed void period/)
|
69
|
+
)
|
70
|
+
|
71
|
+
req.should have_been_made
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'simple_shipping'
|
5
|
+
|
6
|
+
require "simplecov"
|
7
|
+
require "simplecov-rcov-text"
|
8
|
+
|
9
|
+
SimpleCov.formatter = SimpleCov::Formatter::RcovTextFormatter
|
10
|
+
SimpleCov.start do
|
11
|
+
add_filter "/spec/"
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
require "savon/mock/spec_helper"
|
16
|
+
require 'webmock/rspec'
|
17
|
+
require "timecop"
|
18
|
+
require "erubis"
|
19
|
+
require 'equivalent-xml'
|
20
|
+
|
21
|
+
# Requires supporting files with custom matchers and macros, etc,
|
22
|
+
# in ./support/ and its subdirectories.
|
23
|
+
require File.expand_path("../support/custom_matchers/basic_matcher", __FILE__)
|
24
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
25
|
+
|
26
|
+
RSpec.configure do |config|
|
27
|
+
config.include SimpleShipping::CustomMatchers
|
28
|
+
config.include Savon::SpecHelper
|
29
|
+
config.after(:each) { savon.unmock! }
|
30
|
+
|
31
|
+
config.before(:each) do
|
32
|
+
# We are going to enable webmock in some spec on-demand.
|
33
|
+
# This is the reason why this config directive is placed in before(:each) hook -- aignatyev 20130204
|
34
|
+
WebMock.disable_net_connect!(:allow_localhost => true)
|
35
|
+
end
|
36
|
+
|
37
|
+
def fixtures_dir
|
38
|
+
Pathname.new(File.expand_path('../fixtures', __FILE__))
|
39
|
+
end
|
40
|
+
|
41
|
+
def fixture(name, vars = {})
|
42
|
+
path = fixtures_dir.join(name.to_s + ".soap.xml.erb")
|
43
|
+
template = File.open(path).read
|
44
|
+
|
45
|
+
Erubis::Eruby.new(template).result(vars)
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class HaveAttributeMatcher < BasicMatcher
|
4
|
+
def initialize(attribute)
|
5
|
+
@attribute = attribute.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
model.respond_to?(@attribute) &&
|
10
|
+
model.respond_to?("#{@attribute}=")
|
11
|
+
end
|
12
|
+
|
13
|
+
def description
|
14
|
+
"have attribute #{@attribute.inspect}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def have_attribute(attr_name)
|
19
|
+
HaveAttributeMatcher.new(attr_name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class HaveDefaultValueMatcher < BasicMatcher
|
4
|
+
def initialize(value)
|
5
|
+
@value = value
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
model.send(@attribute) == @value
|
10
|
+
end
|
11
|
+
|
12
|
+
def for_attribute(attribute)
|
13
|
+
@attribute = attribute.to_sym
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
"have default value #{@value.inspect} for attribute #{@attribute.inspect}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def have_default_value(value)
|
23
|
+
HaveDefaultValueMatcher.new(value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class HaveErrorsOnMatcher < BasicMatcher
|
4
|
+
|
5
|
+
def initialize(attribute)
|
6
|
+
@attribute = attribute.to_sym
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?(model)
|
10
|
+
model.valid?
|
11
|
+
!!model.errors.messages[@attribute]
|
12
|
+
end
|
13
|
+
|
14
|
+
def description
|
15
|
+
"have errors on #{@attribute.inspect}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def have_errors_on(attr_name)
|
20
|
+
HaveErrorsOnMatcher.new(attr_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class ValidateInclusionOfMatcher < BasicMatcher
|
4
|
+
def initialize(attribute)
|
5
|
+
@attribute = attribute.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
@enumeration.each do |value|
|
10
|
+
model.send("#{@attribute}=", value)
|
11
|
+
return false if has_error?(model)
|
12
|
+
end
|
13
|
+
model.send("#{@attribute}=", "ANOTHER_VALUE_#{rand}")
|
14
|
+
has_error?(model)
|
15
|
+
end
|
16
|
+
|
17
|
+
def in(*enumeration)
|
18
|
+
@enumeration = enumeration
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def description
|
23
|
+
"validate inclusion of #{@attribute.inspect} in #{@enumeration.inspect}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def has_error?(model)
|
27
|
+
model.valid?
|
28
|
+
model.errors.messages[@attribute] and
|
29
|
+
model.errors.messages[@attribute].include?("is not included in the list")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_inclusion_of(attr_name)
|
34
|
+
ValidateInclusionOfMatcher.new(attr_name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class ValidatePresenceOfMatcher < BasicMatcher
|
4
|
+
def initialize(attribute)
|
5
|
+
@attribute = attribute.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
model.send("#{@attribute}=", nil)
|
10
|
+
model.valid?
|
11
|
+
model.errors.messages[@attribute] and
|
12
|
+
model.errors.messages[@attribute].include? "can't be blank"
|
13
|
+
end
|
14
|
+
|
15
|
+
def description
|
16
|
+
"validate presence of #{@attribute.inspect}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_presence_of(attr_name)
|
21
|
+
ValidatePresenceOfMatcher.new(attr_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class ValidateSubmodelMatcher < BasicMatcher
|
4
|
+
def initialize(attribute)
|
5
|
+
@attribute = attribute.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
@model = model
|
10
|
+
|
11
|
+
@model.send("#{@attribute}=", Class.new.new)
|
12
|
+
return false unless has_error?
|
13
|
+
|
14
|
+
submodel = @class.new
|
15
|
+
submodel.stub!(:valid? => false)
|
16
|
+
@model.send("#{@attribute}=", submodel)
|
17
|
+
return false unless has_error?
|
18
|
+
|
19
|
+
submodel.stub!(:valid? => true)
|
20
|
+
@model.send("#{@attribute}=", submodel)
|
21
|
+
!has_error?
|
22
|
+
end
|
23
|
+
|
24
|
+
def as(klass)
|
25
|
+
@class = klass
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def description
|
30
|
+
"validate submodel #{@attribute.inspect} as instance of #{@class}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def has_error?
|
34
|
+
@model.valid?
|
35
|
+
!!@model.errors.messages[@attribute]
|
36
|
+
end
|
37
|
+
private :has_error?
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_submodel(attr_name)
|
41
|
+
ValidateSubmodelMatcher.new(attr_name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|