# vim:syntax=perl #------------------------------------------------------------------- # WebGUI is Copyright 2001-2009 Plain Black Corporation. #------------------------------------------------------------------- # Please read the legal notices (docs/legal.txt) and the license # (docs/license.txt) that came with this distribution before using # this software. #------------------------------------------------------------------ # http://www.plainblack.com info@plainblack.com #------------------------------------------------------------------ # Write a little about what this script tests. # # use FindBin; use strict; use lib "$FindBin::Bin/../../lib"; use Test::More; use Test::Deep; use Exception::Class; use Data::Dumper; use JSON; use WebGUI::Test; # Must use this before any other WebGUI modules use WebGUI::Session; use WebGUI::Text; use WebGUI::Asset::Sku::Product; use WebGUI::VersionTag; #---------------------------------------------------------------------------- # Init my $session = WebGUI::Test->session; #---------------------------------------------------------------------------- # Tests my $tests = 65; plan tests => 1 + $tests; #---------------------------------------------------------------------------- # put your tests here my $class = 'WebGUI::Asset::Wobject::Shelf'; my $loaded = use_ok($class); my ($e, $failure); SKIP: { skip "Unable to load module $class", $tests unless $loaded; my $root = WebGUI::Asset->getRoot($session); my $shelf = $root->addChild({className => $class}); ####################################################################### # # import # ####################################################################### eval { $shelf->importProducts(); }; $e = Exception::Class->caught(); isa_ok($e, 'WebGUI::Error::InvalidParam', 'importProducts: error handling for an undefined path to file'); is($e->error, 'Must provide the path to a file', 'importProducts: error handling for an undefined path to file'); eval { $shelf->importProducts('/path/to/nowhere'); }; $e = Exception::Class->caught(); isa_ok($e, 'WebGUI::Error::InvalidFile', 'importProducts: error handling for file that does not exist in the filesystem'); is($e->error, 'File could not be found', 'importProducts: error handling for file that does not exist in the filesystem'); cmp_deeply( $e, methods( brokenFile => '/path/to/nowhere', ), 'importTaxData: error handling for file that does not exist in the filesystem', ); my $productsFile = WebGUI::Test->getTestCollateralPath('productTables/goodProductTable.csv'); SKIP: { skip 'Root will cause this test to fail since it does not obey file permissions', 3 if $< == 0; my $originalChmod = (stat $productsFile)[2]; chmod oct(0000), $productsFile; eval { $shelf->importProducts($productsFile); }; $e = Exception::Class->caught(); isa_ok($e, 'WebGUI::Error::InvalidFile', 'importProducts: error handling for file that cannot be read'); is($e->error, 'File is not readable', 'importProducts: error handling for file that that cannot be read'); cmp_deeply( $e, methods( brokenFile => $productsFile, ), 'importProducts: error handling for file that that cannot be read', ); chmod $originalChmod, $productsFile; } $failure=0; eval { $failure = $shelf->importProducts( WebGUI::Test->getTestCollateralPath('productTables/missingHeaders.csv'), ); }; ok (!$failure, 'Product data is not imported when headers are missing'); $e = Exception::Class->caught(); isa_ok($e, 'WebGUI::Error::InvalidFile', 'importProducts: a file with a missing header column'); cmp_deeply( $e, methods( error => 'Bad header found in the CSV file', brokenFile => WebGUI::Test->getTestCollateralPath('productTables/missingHeaders.csv'), ), 'importProducts: error handling for a file with a missing header', ); $failure=0; eval { $failure = $shelf->importProducts( WebGUI::Test->getTestCollateralPath('productTables/badHeaders.csv'), ); }; ok (!$failure, 'Product data is not imported when the headers are wrong'); $e = Exception::Class->caught(); isa_ok($e, 'WebGUI::Error::InvalidFile', 'importProducts: a file with bad headers'); cmp_deeply( $e, methods( error => 'Bad header found in the CSV file', brokenFile => WebGUI::Test->getTestCollateralPath('productTables/badHeaders.csv'), ), 'importProducts: error handling for a file with a missing header', ); my $pass=0; $pass = $shelf->importProducts( WebGUI::Test->getTestCollateralPath('productTables/goodProductTable.csv'), ); ok($pass, 'Products imported'); my $count = $session->db->quickScalar('select count(*) from Product'); is($count, 2, 'two products were imported'); my $soda = WebGUI::Asset::Sku->newBySku($session, 'soda'); isa_ok($soda, 'WebGUI::Asset::Sku::Product'); is($soda->getTitle(), 'Sweet Soda-bottled in Oregon', 'Title set correctly for soda'); is($soda->get('url'), 'sweet-soda-bottled-in-oregon', 'URL for new product from the title'); is($soda->get('menuTitle'), $soda->getTitle, 'menuTitle is the same as title'); my $sodaCollateral = $soda->getAllCollateral('variantsJSON'); cmp_deeply( $sodaCollateral, [ { varSku => 'soda-sweet', shortdesc => 'Sweet Soda', price => 0.95, weight => 0.95, quantity => 500, variantId => ignore(), }, ], 'collateral set correctly for soda' ); my $shirt = WebGUI::Asset::Sku->newBySku($session, 't-shirt'); isa_ok($shirt, 'WebGUI::Asset::Sku::Product'); is($shirt->getTitle(), 'Colored T-Shirts', 'Title set correctly for t-shirt'); my $shirtCollateral = $shirt->getAllCollateral('variantsJSON'); cmp_deeply( $shirtCollateral, [ { varSku => 'red-t-shirt', shortdesc => 'Red T-Shirt', price => '5.00', weight => '1.33', quantity => '1000', variantId => ignore(), }, { varSku => 'blue-t-shirt', shortdesc => 'Blue T-Shirt', price => '5.25', weight => '1.33', quantity => '2000', variantId => ignore(), }, ], 'collateral set correctly for shirt' ); ####################################################################### # # export # ####################################################################### my $productsOut = $shelf->exportProducts(); isa_ok($productsOut, 'WebGUI::Storage', 'exportProducts returns a Storage object'); is(scalar @{ $productsOut->getFiles }, 1, 'The storage contains just 1 file...'); is(scalar $productsOut->getFiles->[0], 'siteProductData.csv', '...with the correct filename'); my $productData = $productsOut->getFileContentsAsScalar($productsOut->getFiles->[0]); my @productData = split /\n/, $productData; is(scalar @productData, 4, 'productData should have 4 entries, 1 header + 3 data'); is($productData[0], 'mastersku,title,varSku,shortdescription,price,weight,quantity', 'header line is okay'); @productData = map { [ WebGUI::Text::splitCSV($_) ] } @productData[1..3]; my ($sodas, $shirts) = ([], []); foreach my $productData (@productData) { if ($productData->[0] eq 'soda') { push @{ $sodas }, $productData; } elsif ($productData->[0] eq 't-shirt') { push @{ $shirts }, $productData; } } is(scalar @{ $sodas }, 1, 'just 1 soda'); is(scalar @{ $shirts }, 2, '2 shirts'); cmp_deeply( $sodas, [ ['soda', 'Sweet Soda-bottled in Oregon', 'soda-sweet', 'Sweet Soda', 0.95, 0.95, 500] ], 'soda data is okay' ); ####################################################################### # # import, part 2 # ####################################################################### $pass=0; $pass = $shelf->importProducts( WebGUI::Test->getTestCollateralPath('productTables/secondProductTable.csv'), ); ok($pass, 'Products imported for the second time'); $count = $session->db->quickScalar('select count(*) from Product'); is($count, 3, 'three products were imported'); $soda = WebGUI::Asset::Sku->newBySku($session, 'soda'); $sodaCollateral = $soda->getAllCollateral('variantsJSON'); cmp_deeply( $sodaCollateral, [ { varSku => 'soda-sweet', shortdesc => 'Sweet Soda', price => '1.00', weight => 0.85, quantity => 500, variantId => ignore(), }, ], 'collateral updated correctly for soda' ); $shirt = WebGUI::Asset::Sku->newBySku($session, 't-shirt'); $shirtCollateral = $shirt->getAllCollateral('variantsJSON'); cmp_deeply( $shirtCollateral, [ { varSku => 'red-t-shirt', shortdesc => 'Red T-Shirt', price => '5.00', weight => '1.33', quantity => '500', variantId => ignore(), }, { varSku => 'blue-t-shirt', shortdesc => 'Blue T-Shirt', price => '5.25', weight => '1.33', quantity => '2000', variantId => ignore(), }, ], 'collateral updated correctly for shirt' ); my $record = WebGUI::Asset::Sku->newBySku($session, 'classical-records-1'); isa_ok($record, 'WebGUI::Asset::Sku::Product'); my $recordCollateral = $record->getAllCollateral('variantsJSON'); cmp_deeply( $recordCollateral, [ { varSku => 'track-16', shortdesc => 'Track 16', price => '3.25', weight => '0.00', quantity => 50, variantId => ignore(), }, ], 'collateral set correctly for classical record' ); ####################################################################### # # import, part 3 # ####################################################################### $pass=0; $pass = $shelf->importProducts( WebGUI::Test->getTestCollateralPath('productTables/thirdProductTable.csv'), ); ok($pass, 'Products imported for the third time'); $count = $session->db->quickScalar('select count(*) from Product'); is($count, 3, 'still have 3 products, nothing new added'); $soda = WebGUI::Asset::Sku->newBySku($session, 'soda'); is($soda->getTitle(), 'Sweet Soda-totally organic', 'Title updated correctly for soda'); is($soda->get('menuTitle'), 'Sweet Soda-totally organic', 'menuTitle updated correctly for soda'); is($soda->get('url'), 'sweet-soda-bottled-in-oregon', 'URL for updated product from the original title, not the updated title'); $shirt = WebGUI::Asset::Sku->newBySku($session, 't-shirt'); $shirtCollateral = $shirt->getAllCollateral('variantsJSON'); cmp_deeply( $shirtCollateral, [ { varSku => 'red-t-shirt', shortdesc => 'Red T-Shirt', price => '5.00', weight => '1.33', quantity => '500', variantId => ignore(), }, { varSku => 'blue-t-shirt', shortdesc => 'Blue T-Shirt', price => '5.25', weight => '1.33', quantity => '2000', variantId => ignore(), }, ], 'collateral updated correctly for shirt' ); $record = WebGUI::Asset::Sku->newBySku($session, 'classical-records-1'); $recordCollateral = $record->getAllCollateral('variantsJSON'); cmp_deeply( $recordCollateral, [ { varSku => 'track-16', shortdesc => 'Track 16', price => '3.25', weight => '0.00', quantity => 50, variantId => ignore(), }, { varSku => 'track-9', shortdesc => 'Track 9', price => '3.25', weight => '0.00', quantity => 55, variantId => ignore(), }, ], 'collateral added correctly for classical record' ); $shelf->purge; undef $shelf; $record = WebGUI::Asset::Sku->newBySku($session, 'classical-records-1'); is($record, undef, 'deleting a shelf deletes all products beneath it'); ####################################################################### # # import, quoted headers and fields # ####################################################################### my $shelf2 = $root->addChild({className => $class}); $pass = 0; eval { $pass = $shelf2->importProducts( WebGUI::Test->getTestCollateralPath('productTables/quotedTable.csv'), ); }; ok($pass, 'Able to load a table with quoted fields'); $e = Exception::Class->caught(); is($e, '', 'No exception thrown on a file with quoted fields'); is($shelf2->getChildCount, 3, 'imported 3 children skus for shelf2 with quoted fields'); $shelf2->purge; undef $shelf2; ####################################################################### # # import, windows line endings # ####################################################################### $shelf2 = WebGUI::Asset->getRoot($session)->addChild({className => $class}); $pass = 0; eval { $pass = $shelf2->importProducts( WebGUI::Test->getTestCollateralPath('productTables/windowsTable.csv'), ); }; ok($pass, 'Able to load a table with windows style newlines'); $e = Exception::Class->caught(); is($e, '', 'No exception thrown on a file with quoted fields'); is($shelf2->getChildCount, 2, 'imported 2 children skus for shelf2 with windows line endings fields'); $shelf2->purge; undef $shelf2; ####################################################################### # # import, old sku column header # ####################################################################### $shelf2 = WebGUI::Asset->getRoot($session)->addChild({className => $class}); $pass = 0; eval { $pass = $shelf2->importProducts( WebGUI::Test->getTestCollateralPath('productTables/windowsTable.csv'), ); }; ok($pass, 'Able to load a table with old style, sku instead of varSku'); $e = Exception::Class->caught(); is($e, '', 'No exception thrown on a file old headers'); is($shelf2->getChildCount, 2, 'imported 2 children skus for shelf2 with old headers'); $shelf2->purge; undef $shelf2; ##Clear out this tag so we can do downstream work. my $tag = WebGUI::VersionTag->getWorking($session); $tag->commit; WebGUI::Test->addToCleanup($tag); ####################################################################### # # import, funky data in the price column # ####################################################################### my $shelf3 = WebGUI::Asset->getRoot($session)->addChild({className => $class}); $pass = 0; eval { $pass = $shelf3->importProducts( WebGUI::Test->getTestCollateralPath('productTables/dollarsigns.csv'), ); }; ok($pass, 'Able to load a table with odd characters in the price column'); $e = Exception::Class->caught(); is($e, '', '... no exception thrown'); is($shelf3->getChildCount, 1, '...imported 1 child sku for shelf3 with old headers'); my $sign = $shelf3->getFirstChild(); my $signCollateral = $sign->getAllCollateral('variantsJSON'); cmp_deeply( $signCollateral, [ { varSku => 'dollar signs', shortdesc => 'Silver Dollar Signs', price => '5.00', weight => '0.33', quantity => '1000', variantId => ignore(), }, ], 'collateral set correctly for sign' ); $shelf3->purge; undef $shelf3; ##Clear out this tag so we can do downstream work. my $tag = WebGUI::VersionTag->getWorking($session); $tag->commit; WebGUI::Test->addToCleanup($tag); ####################################################################### # # Template variables # ####################################################################### my $tommy = WebGUI::User->create($session); my $warden = WebGUI::User->create($session); WebGUI::Test->addToCleanup($tommy, $warden); my $inGroup = WebGUI::Group->new($session, 'new'); WebGUI::Test->addToCleanup($inGroup); $inGroup->addUsers([$tommy->getId]); my $testTemplate = $root->addChild({ className => 'WebGUI::Asset::Template', parser => 'WebGUI::Asset::Template::HTMLTemplate', template => q|{ "noViewableSkus":"","emptyShelf":""}|, }); my $testShelf = $root->addChild({ className => $class, templateId => $testTemplate->getId, }); my $tag2 = WebGUI::VersionTag->getWorking($session); WebGUI::Test->addToCleanup($tag2); $tag2->commit; $session->user({userId => 1}); $testShelf->prepareView; my $json = $testShelf->view; my $vars = eval { from_json($json) }; ok( $vars->{emptyShelf}, 'empty shelf: yes'); ok( $vars->{noViewableSkus}, 'viewable skus: none'); my $privateSku = $testShelf->addChild({ className => 'WebGUI::Asset::Sku::Product', groupIdView => $inGroup->getId, title => 'Private Product', }); my $tag3 = WebGUI::VersionTag->getWorking($session); WebGUI::Test->addToCleanup($tag3); $tag3->commit; $session->user({user => $tommy}); $testShelf->prepareView; $json = $testShelf->view; $vars = eval { from_json($json) }; ok( !$vars->{emptyShelf}, 'empty shelf, no'); ok( !$vars->{noViewableSkus}, 'viewable skus: yes for user in group'); $session->user({user => $warden}); $testShelf->prepareView; $json = $testShelf->view; $vars = eval { from_json($json) }; ok( !$vars->{emptyShelf}, 'empty shelf, no'); ok( $vars->{noViewableSkus}, 'viewable skus: none for user not in viewable group'); }