diff --git a/lib/WebGUI/Pluggable.pm b/lib/WebGUI/Pluggable.pm index 709d6bf77..7fb0c2400 100644 --- a/lib/WebGUI/Pluggable.pm +++ b/lib/WebGUI/Pluggable.pm @@ -46,7 +46,7 @@ These functions are available from this package: #------------------------------------------------------------------- -=head2 instanciate ( module, method, params ) +=head2 instanciate ( module, sub, params ) Dynamically ensures that a plugin module is loaded into memory. Then instanciates a new object from the module. Croaks on failure. @@ -54,6 +54,15 @@ Dynamically ensures that a plugin module is loaded into memory. Then instanciate The name of the module you'd like to load like "WebGUI::Asset::Snippet"; +=head3 sub + +The name of the constructor you would like to invoke from the module. Usually "new", or sometimes "create". + +=head3 params + +An array ref of params to send to the constructor. In WebGUI, the first param should be a WebGUI::Session +object. + =cut sub instanciate { diff --git a/lib/WebGUI/Shop/Ship.pm b/lib/WebGUI/Shop/Ship.pm index 325828deb..d590ef728 100644 --- a/lib/WebGUI/Shop/Ship.pm +++ b/lib/WebGUI/Shop/Ship.pm @@ -7,6 +7,7 @@ use WebGUI::International; use WebGUI::Shop::ShipDriver; use WebGUI::Pluggable; use WebGUI::Utility; +use WebGUI::Exception; =head1 NAME @@ -41,7 +42,8 @@ sub _loadDriver { =head2 create ( $session, $class, $options ) -The interface method for creating new, configured instances of ShipDriver. +The interface method for creating new, configured instances of ShipDriver. If the ShipperDriver throws an exception, it is propagated +back up to the top. =head3 $session @@ -60,17 +62,18 @@ A list of properties to assign to this ShipperDriver. See C for det sub create { my $class = shift; my $session = shift; - croak "create requires a session object" + WebGUI::Error::InvalidParam->throw(error => q{Must provide a session variable}) unless ref $session eq 'WebGUI::Session'; my $requestedClass = shift; - croak "create requires the name of a class to create an object" + WebGUI::Error::InvalidParam->throw(error => q{Must provide a class to create an object}) unless defined $requestedClass; - croak "The requested class $class is not enabled in your WebGUI configuration file" + WebGUI::Error::InvalidParam->throw(error => qq{The requested class $requestedClass is not enabled in your WebGUI configuration file}) unless isIn($requestedClass, @{ WebGUI::Shop::Ship->getDrivers($session) } ); my $options = shift; - croak "You must pass a hashref of options to create a new ShipDriver object" + WebGUI::Error::InvalidParam->throw(error => q{You must pass a hashref of options to create a new ShipDriver object}) unless defined($options) and ref $options eq 'HASH' and scalar keys %{ $options }; - + my $driver = eval { WebGUI::Pluggable::instanciate($requestedClass, 'create', [ $session, $options ]) }; + return $driver; } #------------------------------------------------------------------- @@ -82,14 +85,14 @@ from the WebGUI config file. =head3 $session -A WebGUI::Session object. +A WebGUI::Session object. A WebGUI::Error::InvalidParam exception will be thrown if it doesn't get one. =cut sub getDrivers { my $class = shift; my $session = shift; - croak "getDrivers requires a session object" + WebGUI::Error::InvalidParam->throw(error => q{Must provide a session variable}) unless ref $session eq 'WebGUI::Session'; return $session->config->get('shippingDrivers'); } @@ -103,7 +106,7 @@ with the key of the primary hash being the shipperId of the driver, and sub keys =head3 $session -A WebGUI::Session object. +A WebGUI::Session object. A WebGUI::Error::InvalidParam exception will be thrown if it doesn't get one. =head3 @@ -121,7 +124,8 @@ sub getOptions { =head2 new ( $session, $shipperId ) Looks up an existing ShipperDriver in the db by shipperId and returns -that object. +that object. If the ShipperDriver throws an exception, it is propagated +back up to the top. =head3 $session @@ -136,11 +140,16 @@ The ID of a shipper to look up and instanciate. sub new { my $class = shift; my $session = shift; - croak "new requires a session object" + WebGUI::Error::InvalidParam->throw(error => q{Must provide a session variable}) unless ref $session eq 'WebGUI::Session'; my $shipperId = shift; - croak "new requires a shipperId" + WebGUI::Error::InvalidParam->throw(error => q{Must provide a shipperId}) unless defined $shipperId; + my $requestedClass = $session->db->quickScalar('select className from shipper where shipperId=?',[$shipperId]); + WebGUI::Error::ObjectNotFound->throw(error => q{shipperId not found in db}, id => $shipperId) + unless $requestedClass; + my $driver = eval { WebGUI::Pluggable::instanciate($requestedClass, 'new', [ $session, $shipperId ]) }; + return $driver; } 1; diff --git a/lib/WebGUI/Shop/ShipDriver/FlatRate.pm b/lib/WebGUI/Shop/ShipDriver/FlatRate.pm index 3d7dd0213..8e692e0bf 100644 --- a/lib/WebGUI/Shop/ShipDriver/FlatRate.pm +++ b/lib/WebGUI/Shop/ShipDriver/FlatRate.pm @@ -36,7 +36,8 @@ Returns a shipping price. Calculates the shipping price using the following form =head3 $cart A WebGUI::Shop::Cart object. The contents of the cart are analyzed to calculate -the shipping costs. +the shipping costs. If no items in the cart require shipping, then no shipping +costs are assessed. =cut diff --git a/t/Shop/Ship.t b/t/Shop/Ship.t index 61a149d78..954732286 100644 --- a/t/Shop/Ship.t +++ b/t/Shop/Ship.t @@ -31,7 +31,7 @@ my $session = WebGUI::Test->session; #---------------------------------------------------------------------------- # Tests -my $tests = 7; +my $tests = 23; plan tests => 1 + $tests; #---------------------------------------------------------------------------- @@ -52,9 +52,19 @@ skip 'Unable to load module WebGUI::Shop::Ship', $tests unless $loaded; ####################################################################### my $drivers; +my $e; eval { $drivers = WebGUI::Shop::Ship->getDrivers(); }; -like ($@, qr/getDrivers requires a session object/, 'getDrivers croaks without session'); +$e = Exception::Class->caught(); +isa_ok($e, 'WebGUI::Error::InvalidParam', 'getDrivers takes an exception to not giving it a session variable'); +cmp_deeply( + $e, + methods( + error => 'Must provide a session variable', + ), + 'getDrivers: requires a session variable', +); + $drivers = WebGUI::Shop::Ship->getDrivers($session); @@ -71,19 +81,63 @@ cmp_deeply( ####################################################################### eval { $drivers = WebGUI::Shop::Ship->create(); }; -like ($@, qr/create requires a session object/, 'create croaks without session'); +$e = Exception::Class->caught(); +isa_ok($e, 'WebGUI::Error::InvalidParam', 'create takes an exception to not giving it a session variable'); +cmp_deeply( + $e, + methods( + error => 'Must provide a session variable', + ), + 'create: requires a session variable', +); eval { $drivers = WebGUI::Shop::Ship->create($session); }; -like ($@, qr/create requires the name of a class/, 'create croaks without a class'); +$e = Exception::Class->caught(); +isa_ok($e, 'WebGUI::Error::InvalidParam', 'create croaks without a class'); +cmp_deeply( + $e, + methods( + error => 'Must provide a class to create an object', + ), + 'create croaks without a class', +); + eval { $drivers = WebGUI::Shop::Ship->create($session, 'WebGUI::Shop::ShipDriver::FreeShipping'); }; -like ($@, qr/The requested class \S+ is not enabled in your WebGUI configuration file/, 'create croaks without a configured class'); +$e = Exception::Class->caught(); +isa_ok($e, 'WebGUI::Error::InvalidParam', 'create croaks without a configured class'); +cmp_deeply( + $e, + methods( + error => 'The requested class WebGUI::Shop::ShipDriver::FreeShipping is not enabled in your WebGUI configuration file', + ), + 'create croaks without a configured class', +); eval { $drivers = WebGUI::Shop::Ship->create($session, 'WebGUI::Shop::ShipDriver::FlatRate'); }; -like ($@, qr/You must pass a hashref of options to create a new ShipDriver object/, 'create croaks without options to build a object with'); +$e = Exception::Class->caught(); +isa_ok($e, 'WebGUI::Error::InvalidParam', 'create croaks without options to build a object with'); +cmp_deeply( + $e, + methods( + error => 'You must pass a hashref of options to create a new ShipDriver object', + ), + 'create croaks without options to build a object with', +); eval { $drivers = WebGUI::Shop::Ship->create($session, 'WebGUI::Shop::ShipDriver::FlatRate', {}); }; -like ($@, qr/You must pass a hashref of options to create a new ShipDriver object/, 'create croaks without options to build a object with'); +$e = Exception::Class->caught(); +isa_ok($e, 'WebGUI::Error::InvalidParam', 'create croaks without options to build a object with'); +cmp_deeply( + $e, + methods( + error => 'You must pass a hashref of options to create a new ShipDriver object', + ), + 'create croaks without options to build a object with', +); + +my $driver = WebGUI::Shop::Ship->create($session, 'WebGUI::Shop::ShipDriver::FlatRate', { enabled=>1, label=>q{Jake's Jailbird Airmail}}); +isa_ok($driver, 'WebGUI::Shop::ShipDriver::FlatRate', 'created a new, configured FlatRate driver'); ####################################################################### @@ -92,6 +146,48 @@ like ($@, qr/You must pass a hashref of options to create a new ShipDriver objec # ####################################################################### +my $oldDriver; + +eval { $oldDriver = WebGUI::Shop::Ship->new(); }; +$e = Exception::Class->caught(); +isa_ok($e, 'WebGUI::Error::InvalidParam', 'new takes exception to not giving it a session object'); +cmp_deeply( + $e, + methods( + error => 'Must provide a session variable', + ), + 'new takes exception to not giving it a session object', +); + +eval { $oldDriver = WebGUI::Shop::Ship->new($session); }; +$e = Exception::Class->caught(); +isa_ok($e, 'WebGUI::Error::InvalidParam', 'new takes exception to not giving it a shipperId'); +cmp_deeply( + $e, + methods( + error => 'Must provide a shipperId', + ), + 'new takes exception to not giving it a shipperId', +); + +eval { $oldDriver = WebGUI::Shop::Ship->new($session, 'notEverAnId'); }; +$e = Exception::Class->caught(); +isa_ok($e, 'WebGUI::Error::ObjectNotFound', 'new croaks unless the requested shipperId object exists in the db'); +cmp_deeply( + $e, + methods( + error => 'shipperId not found in db', + id => 'notEverAnId', + ), + 'new croaks unless the requested shipperId object exists in the db', +); + +my $driverCopy = WebGUI::Shop::Ship->new($session, $driver->shipperId); + +is($driverCopy->getId, $driver->getId, 'same id'); +is($driverCopy->className, $driver->className, 'same className'); +cmp_deeply($driverCopy->options, $driver->options, 'same options'); + } #----------------------------------------------------------------------------