Merge branch 'master' of git://github.com/pdonelan/webgui into filepump

This commit is contained in:
Colin Kuskie 2009-05-16 14:44:27 -07:00
commit 8e3891a7bd
44 changed files with 5516 additions and 80 deletions

View file

@ -150,7 +150,7 @@ $canViewMaker->prepare(
},
);
plan tests => 103
plan tests => 104
+ scalar(@fixIdTests)
+ scalar(@fixTitleTests)
+ 2*scalar(@getTitleTests) #same tests used for getTitle and getMenuTitle
@ -391,6 +391,7 @@ is($importNode->fixUrl('/extras2'), '_extras2', 'underscore prepended to URLs th
is($importNode->fixUrl('one.html/two.html'), 'one/two.html', 'extensions are not allowed higher up in the path');
is($importNode->fixUrl('one.html/two.html/three.html'), 'one/two/three.html', 'extensions are not allowed anywhere in the path');
is($importNode->fixUrl('one.one.html/two.html/three.html'), 'one/two/three.html', 'multiple dot extensions are removed in any path element');
is($importNode->fixUrl('.startsWithDot'), '.startswithdot', 'leading dots are okay');
##Now, check duplicate URLs

391
t/Asset/Story.t Normal file
View file

@ -0,0 +1,391 @@
#-------------------------------------------------------------------
# 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
#-------------------------------------------------------------------
use FindBin;
use strict;
use lib "$FindBin::Bin/../lib";
use WebGUI::Test;
use WebGUI::Session;
use WebGUI::Storage;
use Test::More; # increment this value for each test you create
use Test::Deep;
use Data::Dumper;
my $tests = 42;
plan tests => 1
+ $tests
;
#TODO: This script tests certain aspects of WebGUI::Storage and it should not
my $session = WebGUI::Test->session;
my $class = 'WebGUI::Asset::Story';
my $loaded = use_ok($class);
my $story;
my $wgBday = WebGUI::Test->webguiBirthday;
my $defaultNode = WebGUI::Asset->getDefault($session);
my $archive = $defaultNode->addChild({
className => 'WebGUI::Asset::Wobject::StoryArchive',
title => 'Test Archive',
#1234567890123456789012
assetId => 'TestStoryArchiveAsset1',
});
my $topic = $defaultNode->addChild({
className => 'WebGUI::Asset::Wobject::StoryTopic',
title => 'Test Topic',
#1234567890123456789012
assetId => 'TestStoryTopicAsset123',
keywords => 'tango,yankee',
});
my $archiveTag = WebGUI::VersionTag->getWorking($session);
$archiveTag->commit;
my $storage1 = WebGUI::Storage->create($session);
my $storage2 = WebGUI::Storage->create($session);
WebGUI::Test->storagesToDelete($storage1, $storage2);
SKIP: {
skip "Unable to load module $class", $tests unless $loaded;
############################################################
#
# validParent
#
############################################################
ok(! WebGUI::Asset::Story->validParent($session), 'validParent: no session asset');
$session->asset($defaultNode);
ok(! WebGUI::Asset::Story->validParent($session), 'validParent: wrong type of asset');
$session->asset($archive);
ok( WebGUI::Asset::Story->validParent($session), 'validParent: StoryArchive is valid');
############################################################
#
# Make a new one. Test defaults
#
############################################################
$story = $archive->addChild({
className => 'WebGUI::Asset::Story',
title => 'Story 1',
subtitle => 'The story of a CMS',
byline => 'JT Smith',
});
isa_ok($story, 'WebGUI::Asset::Story', 'Created a Story asset');
is($story->get('photo'), '[]', 'by default, photos is an empty JSON array');
is($story->get('isHidden'), 1, 'by default, stories are hidden');
$story->update({isHidden => 0});
is($story->get('isHidden'), 1, 'stories cannot be set to not be hidden');
is($story->get('state'), 'published', 'Story is published');
{
##Version control does not alter the current object's status, fetch an updated copy from the
##db.
my $storyDB = WebGUI::Asset->newByUrl($session, $story->getUrl);
is($storyDB->get('status'), 'approved', 'Story is approved');
}
############################################################
#
# getArchive
#
############################################################
is($story->getArchive->getId, $archive->getId, 'getArchive gets the parent archive for the Story');
############################################################
#
# Photo JSON
#
############################################################
my $photoData = $story->getPhotoData();
cmp_deeply(
$photoData, [],
'getPhotoData: returns an empty array ref with no JSON data'
);
$story->setPhotoData([
{
byLine => 'Andrew Dufresne',
caption => 'Shawshank Prison',
},
]);
is($story->get('photo'), q|[{"caption":"Shawshank Prison","byLine":"Andrew Dufresne"}]|, 'setPhotoData: set JSON in the photo property');
$photoData = $story->getPhotoData();
$photoData->[0]->{caption}="My cell";
cmp_deeply(
$story->getPhotoData,
[
{
byLine => 'Andrew Dufresne',
caption => 'Shawshank Prison',
},
],
'getPhotoData does not return an unsafe reference'
);
$story->setPhotoData();
cmp_deeply(
$story->getPhotoData, [],
'setPhotoData: wipes the stored data if nothing is passed'
);
############################################################
#
# formatDuration
#
############################################################
is($story->formatDuration(time() - (24*3600+15)), '1 Day(s)', 'formatDuration, 1 day');
is($story->formatDuration(time() - (48*3600+15)), '2 Day(s)', 'formatDuration, 2 day');
like($story->formatDuration($wgBday), qr{Year.s.}, 'formatDuration: a long time ago');
is($story->formatDuration(time() - (3600+5)), '1 Hour(s)', 'formatDuration: 1 hour');
is($story->formatDuration(time() - (60+5)), '1 Minute(s)', 'formatDuration: 1 minute');
is($story->formatDuration(time() - (7200+120)), '2 Hour(s), 2 Minute(s)', 'formatDuration: 2 hours, 2 minutes');
############################################################
#
# getCrumbTrail
#
############################################################
cmp_deeply(
$story->getCrumbTrail,
[
{
title => $archive->getTitle,
url => $archive->getUrl,
},
{
title => $story->getTitle,
url => $story->getUrl,
},
],
'getCrumbTrail: with no topic set'
);
$story->topic($topic);
cmp_deeply(
$story->getCrumbTrail,
[
{
title => $archive->getTitle,
url => $archive->getUrl,
},
{
title => $topic->getTitle,
url => $topic->getUrl,
},
{
title => $story->getTitle,
url => $story->getUrl,
},
],
'getCrumbTrail: with topic set'
);
$story->topic('');
############################################################
#
# getRssData
#
############################################################
can_ok($story, 'getRssData');
cmp_deeply(
$story->getRssData,
{
title => 'Story 1',
description => 'The story of a CMS',
'link' => re('story-1$'),
author => 'JT Smith',
date => $story->get('lastModified'),
},
'getRssData: returns correct data'
);
$story->update({headline => 'WebGUI, Web Done Right'});
is($story->getRssData->{title}, 'WebGUI, Web Done Right', '... headline preferred over title if present');
############################################################
#
# viewTemplateVariables
#
############################################################
$story->update({
highlights => "one\ntwo\nthree",
keywords => "foxtrot,tango,whiskey",
});
is($story->get('highlights'), "one\ntwo\nthree", 'highlights set correctly for template var check');
$storage1->addFileFromFilesystem(WebGUI::Test->getTestCollateralPath('gooey.jpg'));
$storage2->addFileFromFilesystem(WebGUI::Test->getTestCollateralPath('lamp.jpg'));
$story->setPhotoData([
{
storageId => $storage1->getId,
caption => 'Mascot for a popular CMS',
byLine => 'Darcy Gibson',
alt => 'Gooey',
title => 'Mascot',
url => 'http://www.webgui.org',
},
{
storageId => $storage2->getId,
caption => 'The Lamp',
byLine => 'Aladdin',
alt => 'Lamp',
title => '',
url => 'http://www.lamp.com',
},
]);
my $viewVariables = $story->viewTemplateVariables;
#diag Dumper $viewVariables;
cmp_deeply(
$viewVariables->{highlights_loop},
[
{ highlight => "one", },
{ highlight => "two", },
{ highlight => "three", },
],
'viewTemplateVariables: highlights_loop is okay'
);
is($viewVariables->{title}, 'Story 1', '... title is okay');
is($viewVariables->{headline}, 'WebGUI, Web Done Right', '... headline is okay');
cmp_bag(
$viewVariables->{keyword_loop},
[
{ keyword => "foxtrot", url => '/home/test-archive?func=view;keywords=foxtrot', },
{ keyword => "tango", url => '/home/test-archive?func=view;keywords=tango', },
{ keyword => "whiskey", url => '/home/test-archive?func=view;keywords=whiskey', },
],
'viewTemplateVariables: keywords_loop is okay'
);
is ($viewVariables->{updatedTimeEpoch}, $story->get('revisionDate'), 'viewTemplateVariables: updatedTimeEpoch');
cmp_deeply(
$viewVariables->{photo_loop},
[
{
imageUrl => re('gooey.jpg'),
imageCaption => 'Mascot for a popular CMS',
imageByline => 'Darcy Gibson',
imageAlt => 'Gooey',
imageTitle => 'Mascot',
imageLink => 'http://www.webgui.org',
},
{
imageUrl => re('lamp.jpg'),
imageCaption => 'The Lamp',
imageByline => 'Aladdin',
imageAlt => 'Lamp',
imageTitle => '',
imageLink => 'http://www.lamp.com',
},
],
'viewTemplateVariables: photo_loop is okay'
);
ok(! $viewVariables->{singlePhoto}, 'viewVariables: singlePhoto: there is more than 1');
ok( $viewVariables->{hasPhotos}, 'viewVariables: hasPhotos: it has photos');
##Simulate someone deleting the file stored in the storage object.
$storage2->deleteFile('lamp.jpg');
$viewVariables = $story->viewTemplateVariables;
cmp_deeply(
$viewVariables->{photo_loop},
[
{
imageUrl => re('gooey.jpg'),
imageCaption => 'Mascot for a popular CMS',
imageByline => 'Darcy Gibson',
imageAlt => 'Gooey',
imageTitle => 'Mascot',
imageLink => 'http://www.webgui.org',
},
],
'viewTemplateVariables: photo_loop: if the storage has no files, it is not shown'
);
ok($viewVariables->{singlePhoto}, 'viewVariables: singlePhoto: there is just 1');
ok($viewVariables->{hasPhotos}, 'viewVariables: hasPhotos: it has photos');
############################################################
#
# duplicatePhotoData
#
############################################################
$photoData = $story->getPhotoData;
$photoData->[0]->{storageId} = re('^[A-Za-z0-9_-]{22}$');
$photoData->[1]->{storageId} = re('^[A-Za-z0-9_-]{22}$');
my $newPhotoData = $story->duplicatePhotoData;
cmp_deeply(
$newPhotoData,
$photoData,
'duplicatePhotoData: checking JSON data minus storage locations'
);
isnt($newPhotoData->[0]->{storageId}, $photoData->[0]->{storageId}, '... and storage 0 is duplicated');
isnt($newPhotoData->[1]->{storageId}, $photoData->[1]->{storageId}, '... and storage 1 is duplicated');
WebGUI::Test->storagesToDelete( map { $_->{storageId} } @{ $newPhotoData } );
############################################################
#
# exportAssetData
#
############################################################
my $exportData = $story->exportAssetData;
isa_ok($exportData, 'HASH', 'exportAssetData');
cmp_bag(
$exportData->{storage},
[
$storage1->getId,
$storage2->getId,
],
'...asset package data has the storage locations in it'
);
}
END {
$story->purge if $story;
$archive->purge if $archive;
$topic->purge if $topic;
$archiveTag->rollback;
WebGUI::VersionTag->getWorking($session)->rollback;
}

View file

@ -0,0 +1,653 @@
# 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 File::Copy qw/mv/;
use File::Path;
use Data::Dumper;
use Path::Class;
use WebGUI::Test; # Must use this before any other WebGUI modules
use WebGUI::Test::Maker::Permission;
use WebGUI::Session;
use WebGUI::Text;
use WebGUI::Utility;
use WebGUI::DateTime;
use DateTime;
################################################################
#
# setup session, users and groups for this test
#
################################################################
my $session = WebGUI::Test->session;
my $staff = WebGUI::Group->new($session, 'new');
WebGUI::Test->groupsToDelete($staff);
$staff->name('Reporting Staff');
my $reporter = WebGUI::User->new($session, 'new');
$reporter->username('reporter');
my $editor = WebGUI::User->new($session, 'new');
$editor->username('editor');
my $reader = WebGUI::User->new($session, 'new');
$reader->username('reader');
$staff->addUsers([$reporter->userId]);
my $archive = 'placeholder for Test::Maker::Permission';
my $canPostMaker = WebGUI::Test::Maker::Permission->new();
$canPostMaker->prepare({
object => $archive,
session => $session,
method => 'canPostStories',
pass => [3, $editor, $reporter ],
fail => [1, $reader ],
});
my $tests = 45
+ $canPostMaker->plan
;
plan tests => 1
+ $tests;
#----------------------------------------------------------------------------
# put your tests here
my $class = 'WebGUI::Asset::Wobject::StoryArchive';
my $loaded = use_ok($class);
my $storage;
my $versionTag;
my $creationDateSth = $session->db->prepare('update asset set creationDate=? where assetId=?');
SKIP: {
skip "Unable to load module $class", $tests unless $loaded;
$archive = WebGUI::Asset->getDefault($session)->addChild({className => $class, title => 'My Stories', url => '/home/mystories'});
$versionTag = WebGUI::VersionTag->getWorking($session);
$versionTag->commit;
isa_ok($archive, 'WebGUI::Asset::Wobject::StoryArchive', 'created StoryArchive');
################################################################
#
# canPostStories
#
################################################################
$archive->update({
ownerUserId => $editor->userId,
groupToPost => $staff->getId,
});
is($archive->get('groupToPost'), $staff->getId, 'set Staff group to post to Story Archive');
$canPostMaker->{_tests}->[0]->{object} = $archive;
$canPostMaker->run();
################################################################
#
# getFolder
#
################################################################
##Note, this is just to prevent date rollover from happening.
##We'll test implicit getFolder later on.
my $now = time();
my $todayFolder = $archive->getFolder($now);
isa_ok($todayFolder, 'WebGUI::Asset::Wobject::Folder', 'getFolder created a Folder');
is($archive->getChildCount, 1, 'getFolder created a child');
my $dt = DateTime->from_epoch(epoch => $now, time_zone => $session->datetime->getTimeZone);
my $folderName = $dt->strftime('%B_%d_%Y');
$folderName =~ s/^(\w+_)0/$1/;
is($todayFolder->getTitle, $folderName, 'getFolder: folder has the right name');
my $folderUrl = join '/', $archive->getUrl, lc $folderName;
is($todayFolder->getUrl, $folderUrl, 'getFolder: folder has the right URL');
is($todayFolder->getParent->getId, $archive->getId, 'getFolder: created folder has the right parent');
is($todayFolder->get('state'), 'published', 'getFolder: created folder is published');
is($todayFolder->get('status'), 'approved', 'getFolder: created folder is approved');
my $sameFolder = $archive->getFolder($now);
is($sameFolder->getId, $todayFolder->getId, 'call with same time returns the same folder');
undef $sameFolder;
my ($startOfDay, $endOfDay) = $session->datetime->dayStartEnd($now);
$sameFolder = $archive->getFolder($startOfDay);
is($sameFolder->getId, $todayFolder->getId, 'call within same day(start) returns the same folder');
undef $sameFolder;
$sameFolder = $archive->getFolder($endOfDay);
is($sameFolder->getId, $todayFolder->getId, 'call within same day(end) returns the same folder');
undef $sameFolder;
$todayFolder->purge;
is($archive->getChildCount, 0, 'leaving with an empty archive');
################################################################
#
# addChild
#
################################################################
my $child = $archive->addChild({className => 'WebGUI::Asset::Wobject::StoryTopic'});
is($child, undef, 'addChild: Will only add Stories');
$child = $archive->addChild({className => 'WebGUI::Asset::Story', title => 'First Story'});
isa_ok($child, 'WebGUI::Asset::Story', 'addChild added and returned a Story');
is($archive->getChildCount, 1, 'addChild: added it to the archive');
my $folder = $archive->getFirstChild();
isa_ok($folder, 'WebGUI::Asset::Wobject::Folder', 'Folder was added to Archive');
is($folder->getChildCount, 1, 'The folder has 1 child...');
is($folder->getFirstChild->getTitle, 'First Story', '... and it is the correct child');
################################################################
#
# getKeywordFilename
#
################################################################
##Note, this method depends heavily on the default installed language pack.
##Because of that, we'll only test for whether or not url->urlize is called.
is ($archive->getKeywordFilename('camelCase'), 'keyword_camelcase.html', 'getKeywordFilename returns a lower case keyword with _keyword.html appended');
################################################################
#
# viewTemplateVariables
#
################################################################
my $wgBday = WebGUI::Test->webguiBirthday;
my $oldFolder = $archive->getFolder($wgBday);
my $yesterday = $now-24*3600;
my $newFolder = $archive->getFolder($yesterday);
my ($wgBdayMorn,undef) = $session->datetime->dayStartEnd($wgBday);
my ($yesterdayMorn,undef) = $session->datetime->dayStartEnd($yesterday);
my $story = $oldFolder->addChild({ className => 'WebGUI::Asset::Story', title => 'WebGUI is released', keywords => 'roger,foxtrot,echo'});
$creationDateSth->execute([$wgBday, $story->getId]);
{
my $storyDB = WebGUI::Asset->newByUrl($session, $story->getUrl);
is ($storyDB->get('status'), 'approved', 'addRevision always calls for an autocommit');
}
my $pastStory = $newFolder->addChild({ className => 'WebGUI::Asset::Story', title => "Yesterday is history" });
$creationDateSth->execute([$yesterday, $pastStory->getId]);
my $templateVars;
$templateVars = $archive->viewTemplateVariables();
cmp_deeply(
$templateVars,
superhashof({
searchHeader => ignore(),
searchForm => ignore(),
searchButton => ignore(),
searchFooter => ignore(),
}),
'viewTemplateVars: search variables present'
);
cmp_deeply(
$templateVars,
superhashof({
rssUrl => $archive->getRssFeedUrl,
atomUrl => $archive->getAtomFeedUrl,
}),
'viewTemplateVars: RSS and Atom feed template variables'
);
KEY: foreach my $key (keys %{ $templateVars }) {
next KEY if isIn($key, qw/canPostStories addStoryUrl date_loop mode/);
delete $templateVars->{$key};
}
cmp_deeply(
$templateVars,
{
canPostStories => 0,
mode => 'view',
addStoryUrl => '',
date_loop => [
{
epochDate => ignore(),
story_loop => [ {
creationDate => ignore(),
url => re('first-story'),
title => 'First Story',
}, ],
},
{
epochDate => $yesterdayMorn,
story_loop => [{
creationDate => $yesterday,
url => re('yesterday-is-history'),
title => "Yesterday is history",
}, ],
},
{
epochDate => $wgBdayMorn,
story_loop => [ {
creationDate => $wgBday,
url => '/home/mystories/august_16_2001/webgui-is-released',
title => 'WebGUI is released',
}, ],
},
]
},
'viewTemplateVariables: returns expected template variables with 3 stories in different folders'
);
my $story2 = $folder->addChild({ className => 'WebGUI::Asset::Story', title => 'Story 2', keywords => "roger,foxtrot"});
my $story3 = $folder->addChild({ className => 'WebGUI::Asset::Story', title => 'Story 3', keywords => "foxtrot,echo"});
my $story4 = $folder->addChild({ className => 'WebGUI::Asset::Story', title => 'Story 4', keywords => "roger,echo"});
foreach my $storilet ($story2, $story3, $story4) {
$session->db->write("update asset set creationDate=$now where assetId=?",[$storilet->getId]);
}
$archive->update({storiesPerPage => 3});
##Don't assume that Admin and Visitor have the same timezone.
$session->user({userId => 3});
($wgBdayMorn,undef) = $session->datetime->dayStartEnd($wgBday);
$templateVars = $archive->viewTemplateVariables();
KEY: foreach my $key (keys %{ $templateVars }) {
next KEY if isIn($key, qw/canPostStories addStoryUrl date_loop/);
delete $templateVars->{$key};
}
cmp_deeply(
$templateVars,
{
canPostStories => 1,
addStoryUrl => '/home/mystories?func=add;class=WebGUI::Asset::Story',
date_loop => [
{
epochDate => ignore(),
story_loop => [
{
creationDate => ignore(),
url => re('first-story'),
title => 'First Story',
},
{
creationDate => ignore(),
url => ignore(),
title => 'Story 2',
},
{
creationDate => ignore(),
url => ignore(),
title => 'Story 3',
},
],
},
],
},
'viewTemplateVariables: returns expected template variables with several stories in 3 different folders'
);
TODO: {
local $TODO = "viewTemplateVariables code to write";
ok(0, 'Check that Stories from the future are not displayed unless the user canEdit this StoryArchive');
}
################################################################
#
# viewTemplateVariables, keywords search mode
#
################################################################
$session->request->setup_body({ keyword => 'foxtrot' } );
$archive->update({storiesPerPage => 25});
$templateVars = $archive->viewTemplateVariables('keyword');
is($templateVars->{mode}, 'keyword', 'viewTemplateVariables mode == keyword');
cmp_deeply(
$templateVars->{date_loop},
[
{
epochDate => ignore(),
story_loop => [
{
creationDate => ignore(),
url => ignore(),
title => 'Story 2',
},
{
creationDate => ignore(),
url => ignore(),
title => 'Story 3',
},
],
},
{
epochDate => $wgBdayMorn,
story_loop => [
{
creationDate => ignore(),
url => ignore(),
title => 'WebGUI is released',
},
],
},
],
'viewTemplateVariables: keyword mode returns the correct assets in the same form as view mode'
);
$archive->update({storiesPerPage => 3});
$session->request->setup_body({ } );
################################################################
#
# viewTemplateVariables, search mode
#
################################################################
$session->request->setup_body({ query => 'echo' } );
$archive->update({storiesPerPage => 25});
$templateVars = $archive->viewTemplateVariables('search');
is($templateVars->{mode}, 'search', 'viewTemplateVariables mode == search');
cmp_bag(
$templateVars->{date_loop},
[
{
epochDate => ignore(),
story_loop => [
{
creationDate => ignore(),
url => ignore(),
title => 'Story 3',
},
{
creationDate => ignore(),
url => ignore(),
title => 'Story 4',
},
],
},
{
epochDate => $wgBdayMorn,
story_loop => [
{
creationDate => ignore(),
url => ignore(),
title => 'WebGUI is released',
},
],
},
],
'viewTemplateVariables: search mode returns the correct assets in the same form as view mode'
);
################################################################
#
# viewTemplateVariables, export mode
#
################################################################
$session->scratch->set('isExporting', 1);
$archive->update({ storiesPerPage => 3, });
$templateVars = $archive->viewTemplateVariables();
ok( ( !exists $templateVars->{searchHeader}
&& !exists $templateVars->{searchForm}
&& !exists $templateVars->{searchButton}
&& !exists $templateVars->{searchForm}
),
'... export mode, no search variables present'
);
cmp_deeply(
$templateVars,
superhashof({
rssUrl => $archive->getStaticRssFeedUrl,
atomUrl => $archive->getStaticAtomFeedUrl,
}),
'... export mode, RSS and Atom feed template variables show the static url'
);
my $storyCount = 0;
foreach my $date_loop (@{ $templateVars->{date_loop} }) {
$storyCount += scalar @{ $date_loop->{story_loop} };
}
cmp_ok($storyCount, '>', 3, '... export mode, pagination increased beyond storiesPerPage');
$session->scratch->delete('isExporting');
################################################################
#
# tagCloud template variable in view
#
################################################################
$templateVars = $archive->viewTemplateVariables();
my @anchors = simpleHrefParser($templateVars->{keywordCloud});
my @expectedAnchors = ();
foreach my $keyword(qw/echo foxtrot roger/) {
push @expectedAnchors, [ $keyword, '/home/mystories?func=view;keyword='.$keyword ];
}
cmp_bag(
\@anchors,
\@expectedAnchors,
'keywordCloud template variable has keywords and correct links',
);
################################################################
#
# tagCloud template variable in view, exportMode
#
################################################################
$session->scratch->set('isExporting', 1);
$templateVars = $archive->viewTemplateVariables();
@anchors = simpleHrefParser($templateVars->{keywordCloud});
@expectedAnchors = ();
foreach my $keyword(qw/echo foxtrot roger/) {
push @expectedAnchors, [ $keyword, '/home/mystories/keyword_'.$keyword.'.html' ];
}
cmp_bag(
\@anchors,
\@expectedAnchors,
'... keywordCloud template variable has keywords and correct links in export mode',
);
$session->scratch->delete('isExporting');
################################################################
#
# RSS and Atom checks
#
################################################################
is($archive->getRssFeedUrl, '/home/mystories?func=viewRss', 'RSS Feed Url');
is($archive->getAtomFeedUrl, '/home/mystories?func=viewAtom', 'Atom Feed Url');
$archive->update({itemsPerFeed => 3});
cmp_deeply(
$archive->getRssFeedItems(),
[
{
title => 'First Story',
description => ignore(),
'link' => ignore(),
date => ignore(),
author => ignore(),
},
{
title => 'Story 2',
description => ignore(),
'link' => ignore(),
date => ignore(),
author => ignore(),
},
{
title => 'Story 3',
description => ignore(),
'link' => ignore(),
date => ignore(),
author => ignore(),
},
],
'rssFeedItems'
);
################################################################
#
# export Collateral tests
#
################################################################
my $exportStorage = WebGUI::Storage->create($session);
WebGUI::Test->storagesToDelete($exportStorage);
my $basedir = Path::Class::Dir->new($exportStorage->getPath);
$exportStorage->addFileFromScalar('index', 'export story archive content');
my $assetDir = $basedir->subdir('mystories');
my $assetFile = $assetDir->file('index.html');
mkpath($assetDir->stringify);
mv($exportStorage->getPath('index'), $assetFile->stringify);
$archive->exportAssetCollateral($assetFile, {}, $session);
my $exportedFiles = $exportStorage->getFiles();
cmp_bag(
$exportedFiles,
[qw/
mystories.rss mystories
mystories.atom
/],
'exportAssetCollateral: feed files exported'
);
cmp_bag(
[ map { $_->relative($assetDir)->stringify } $assetDir->children ],
[qw/
keyword_echo.html
keyword_roger.html
keyword_foxtrot.html
index.html
/],
'exportAssetCollateral: keyword files exported into correct dir (below the asset)'
);
my $roger = $exportStorage->getFileContentsAsScalar('mystories/keyword_roger.html');
my @rogerStories = map { $_->[0] } fetchKeywordAssetList($roger);
cmp_bag(
\@rogerStories,
[
'Story 2',
'Story 4',
'WebGUI is released',
],
'... contents of roger keyword file'
);
my $foxtrot = $exportStorage->getFileContentsAsScalar('mystories/keyword_foxtrot.html');
my @foxtrotStories = map { $_->[0] } fetchKeywordAssetList($foxtrot);
cmp_bag(
\@foxtrotStories,
[
'Story 2',
'Story 3',
'WebGUI is released',
],
'... contents of foxtrot keyword file'
);
my $echo = $exportStorage->getFileContentsAsScalar('mystories/keyword_echo.html');
my @echoStories = map { $_->[0] } fetchKeywordAssetList($echo);
cmp_bag(
\@echoStories,
[
'Story 3',
'Story 4',
'WebGUI is released',
],
'... contents of echo keyword file'
);
################################################################
#
# getKeywordStaticURL
#
################################################################
is($archive->getKeywordStaticURL('foo'), '/home/mystories/keyword_foo.html', 'getKeywordStaticURL: returns absolute URL to keyword file');
$archive->update({ url => '/home/mystories.arch' });
is($archive->getKeywordStaticURL('bar'), '/home/mystories/keyword_bar.html', '... correct URL with file extension');
$archive->update({ url => '/home/mystories' });
}
#----------------------------------------------------------------------------
# Cleanup
END {
if (defined $archive and ref $archive eq $class) {
$archive->purge;
}
if ($versionTag) {
$versionTag->rollback;
}
foreach my $user ($editor, $reporter, $reader) {
$user->delete if defined $user;
}
$creationDateSth->finish;
}
sub simpleHrefParser {
my ($text) = @_;
my $p = HTML::TokeParser->new(\$text);
my @anchors = ();
while (my $token = $p->get_tag('a')) {
my $url = $token->[1]{href} || "-";
my $label = $p->get_trimmed_text("/a");
push @anchors, [ $label, $url ];
}
return @anchors;
}
sub fetchKeywordAssetList {
my ($text) = @_;
my @anchors = ();
my $p = HTML::TokeParser->new(\$text);
TOKEN: while (my $token = $p->get_tag('ul')) {
next TOKEN unless $token->[1]->{class} eq 'keywordAssetList';
while (my $token = $p->get_tag('/ul', 'a')) {
last TOKEN if $token->[0] eq '/ul';
my $url = $token->[1]{href} || "-";
my $label = $p->get_trimmed_text("/a");
push @anchors, [ $label, $url ];
}
}
return @anchors;
}

View file

@ -0,0 +1,323 @@
# 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 Data::Dumper;
use WebGUI::Test; # Must use this before any other WebGUI modules
use WebGUI::Session;
use WebGUI::Text;
#----------------------------------------------------------------------------
# Init
my $session = WebGUI::Test->session;
#----------------------------------------------------------------------------
# Tests
my $tests = 18;
plan tests => 1 + $tests;
#----------------------------------------------------------------------------
# put your tests here
my $class = 'WebGUI::Asset::Wobject::StoryTopic';
my $loaded = use_ok($class);
my $versionTag = WebGUI::VersionTag->getWorking($session);
my $archive = WebGUI::Asset->getDefault($session)->addChild({className => 'WebGUI::Asset::Wobject::StoryArchive', title => 'My Stories', url => '/home/mystories'});
my $now = time();
my $nowFolder = $archive->getFolder($now);
my $yesterday = $now-24*3600;
my $newFolder = $archive->getFolder($yesterday);
my $creationDateSth = $session->db->prepare('update asset set creationDate=? where assetId=?');
my $pastStory = $newFolder->addChild({ className => 'WebGUI::Asset::Story', title => "Yesterday is history", keywords => 'andy,norton'});
$creationDateSth->execute([$yesterday, $pastStory->getId]);
my @staff = qw/norton hadley mert trout/;
my @inmates = qw/bogs red brooks andy heywood tommy jake skeet/;
my @characters = (@staff, @inmates, );
my @stories = ();
my $storyHandler = {};
STORY: foreach my $name (@characters) {
my $namedStory = $nowFolder->addChild({ className => 'WebGUI::Asset::Story', title => $name, keywords => $name, } );
$storyHandler->{$name} = $namedStory;
$creationDateSth->execute([$now, $namedStory->getId]);
}
$storyHandler->{bogs}->update({subtitle => 'drinking his food through a straw'});
my $topic;
SKIP: {
skip "Unable to load module $class", $tests unless $loaded;
$topic = WebGUI::Asset->getDefault($session)->addChild({ className => 'WebGUI::Asset::Wobject::StoryTopic', title => 'Popular inmates in Shawshank Prison', keywords => join(',', @inmates)});
isa_ok($topic, 'WebGUI::Asset::Wobject::StoryTopic', 'made a Story Topic');
$topic->update({
storiesPer => 6,
storiesShort => 3,
});
$versionTag->commit;
################################################################
#
# viewTemplateVariables
#
################################################################
my $templateVars;
$templateVars = $topic->viewTemplateVariables();
cmp_deeply(
$templateVars,
superhashof({
rssUrl => $topic->getRssFeedUrl,
atomUrl => $topic->getAtomFeedUrl,
}),
'viewTemplateVars: RSS and Atom feed template variables'
);
cmp_deeply(
$templateVars->{story_loop},
[
{
title => 'bogs',
url => $session->url->append($topic->getUrl, 'func=viewStory;assetId='.$storyHandler->{'bogs'}->getId),
creationDate => $now,
},
{
title => 'red',
url => $session->url->append($topic->getUrl, 'func=viewStory;assetId='.$storyHandler->{'red'}->getId),
creationDate => $now,
},
{
title => 'brooks',
url => $session->url->append($topic->getUrl, 'func=viewStory;assetId='.$storyHandler->{'brooks'}->getId),
creationDate => $now,
},
],
'viewTemplateVars has right number and contents in the story_loop'
);
ok(
! exists $templateVars->{topStoryTitle}
&& ! exists $templateVars->{topStoryUrl}
&& ! exists $templateVars->{topStoryCreationDate}
&& ! exists $templateVars->{topStorySubtitle},
'topStory variables not present unless in standalone mode'
);
ok(! $templateVars->{standAlone}, 'viewTemplateVars: not in standalone mode');
$topic->{_standAlone} = 1;
$templateVars = $topic->viewTemplateVariables();
cmp_deeply(
$templateVars->{story_loop},
[
{
title => 'red',
url => $session->url->append($topic->getUrl, 'func=viewStory;assetId='.$storyHandler->{'red'}->getId),
creationDate => $now,
},
{
title => 'brooks',
url => $session->url->append($topic->getUrl, 'func=viewStory;assetId='.$storyHandler->{'brooks'}->getId),
creationDate => $now,
},
{
title => 'andy',
url => $session->url->append($topic->getUrl, 'func=viewStory;assetId='.$storyHandler->{'andy'}->getId),
creationDate => $now,
},
{
title => 'heywood',
url => $session->url->append($topic->getUrl, 'func=viewStory;assetId='.$storyHandler->{'heywood'}->getId),
creationDate => $now,
},
{
title => 'tommy',
url => $session->url->append($topic->getUrl, 'func=viewStory;assetId='.$storyHandler->{'tommy'}->getId),
creationDate => $now,
},
],
'viewTemplateVars has right number and contents in the story_loop in standalone mode. Top story not present in story_loop'
);
is($templateVars->{topStoryTitle}, 'bogs', '... topStoryTitle');
is(
$templateVars->{topStorySubtitle},
'drinking his food through a straw',
'... topStorySubtitle'
);
is(
$templateVars->{topStoryUrl},
$session->url->append($topic->getUrl, 'func=viewStory;assetId='.$storyHandler->{'bogs'}->getId),
'... topStoryUrl'
);
is($templateVars->{topStoryCreationDate}, $now, '... topStoryCreationDate');
ok($templateVars->{standAlone}, '... standAlone mode=1');
my $storage = WebGUI::Storage->create($session);
WebGUI::Test->storagesToDelete($storage);
$storyHandler->{bogs}->setPhotoData([{
caption => "Octopus seen at the scene of Mrs. Dufresne's murder.",
byLine => 'Elmo Blatch',
alt => 'The suspect',
}]);
$templateVars = $topic->viewTemplateVariables();
ok(
! exists $templateVars->{topStoryImageUrl}
&& ! exists $templateVars->{topStoryImageByLine}
&& ! exists $templateVars->{topStoryImageAlt}
&& ! exists $templateVars->{topStoryImageCaption},
'... no photo template variables, since there is no storage location'
);
my $bogsData = $storyHandler->{bogs}->getPhotoData();
$bogsData->[0]->{storageId} = $storage->getId;
$storyHandler->{bogs}->setPhotoData($bogsData);
$templateVars = $topic->viewTemplateVariables();
ok(
! exists $templateVars->{topStoryImageUrl}
&& ! exists $templateVars->{topStoryImageByLine}
&& ! exists $templateVars->{topStoryImageAlt}
&& ! exists $templateVars->{topStoryImageCaption},
'... no photo template variables, since there is no file in the storage location'
);
$storage->addFileFromFilesystem(WebGUI::Test->getTestCollateralPath('gooey.jpg'));
$templateVars = $topic->viewTemplateVariables();
cmp_deeply(
[ @{ $templateVars }{qw/topStoryImageUrl topStoryImageByline topStoryImageAlt topStoryImageCaption/} ],
[
$storage->getUrl('gooey.jpg'),
'Elmo Blatch',
'The suspect',
"Octopus seen at the scene of Mrs. Dufresne's murder.",
],
'... photo template variables set'
);
$topic->update({
storiesShort => 20,
});
$topic->{_standAlone} = 0;
$templateVars = $topic->viewTemplateVariables;
my @topicInmates = map { $_->{title} } @{ $templateVars->{story_loop} };
cmp_deeply(
\@topicInmates,
[@inmates, 'Yesterday is history'], #extra for pastStory
'viewTemplateVariables: is only finding things with its keywords'
);
$session->scratch->set('isExporting', 1);
$topic->update({
storiesShort => 3,
});
$templateVars = $topic->viewTemplateVariables;
cmp_deeply(
$templateVars->{story_loop},
[
{
title => 'bogs',
url => $storyHandler->{'bogs'}->getUrl,
creationDate => $now,
},
{
title => 'red',
url => $storyHandler->{'red'}->getUrl,
creationDate => $now,
},
{
title => 'brooks',
url => $storyHandler->{'brooks'}->getUrl,
creationDate => $now,
},
],
'... export mode, URLs are the regular story URLs'
);
cmp_deeply(
$templateVars,
superhashof({
rssUrl => $topic->getStaticRssFeedUrl,
atomUrl => $topic->getStaticAtomFeedUrl,
}),
'... export mode, RSS and Atom feed template variables show the static url'
);
$session->scratch->delete('isExporting');
################################################################
#
# getRssFeedItems
#
################################################################
$topic->update({
storiesPer => 3,
});
cmp_deeply(
$topic->getRssFeedItems(),
[
{
title => 'bogs',
description => ignore(),
'link' => ignore(),
date => ignore(),
author => ignore(),
},
{
title => 'red',
description => ignore(),
'link' => ignore(),
date => ignore(),
author => ignore(),
},
{
title => 'brooks',
description => ignore(),
'link' => ignore(),
date => ignore(),
author => ignore(),
},
],
'rssFeedItems'
);
}
#----------------------------------------------------------------------------
# Cleanup
END {
$archive->purge if $archive;
$topic->purge if $topic;
if ($versionTag) {
$versionTag->rollback;
}
}

192
t/AssetAspect/RssFeed.t Normal file
View file

@ -0,0 +1,192 @@
# 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 File::Path;
use Data::Dumper;
use WebGUI::Test; # Must use this before any other WebGUI modules
use WebGUI::Session;
use WebGUI::Asset;
use WebGUI::Asset::RssAspectDummy;
#----------------------------------------------------------------------------
# Init
my $session = WebGUI::Test->session;
WebGUI::Test->originalConfig('exportPath');
#----------------------------------------------------------------------------
# Tests
plan tests => 21; # Increment this number for each test you create
#----------------------------------------------------------------------------
# put your tests here
my $dummy = WebGUI::Asset->getDefault($session)->addChild({
className => 'WebGUI::Asset::RssAspectDummy',
url => '/home/shawshank',
title => 'Dummy Title',
synopsis => 'Dummy Synopsis',
description => 'Dummy Description',
});
#####################################################
#
# get URLs
#
#####################################################
can_ok($dummy, qw/getAtomFeedUrl getRssFeedUrl getRdfFeedUrl/);
is($dummy->getAtomFeedUrl, '/home/shawshank?func=viewAtom', 'getAtomFeedUrl');
is($dummy->getRssFeedUrl, '/home/shawshank?func=viewRss', 'getRssFeedUrl');
is($dummy->getRdfFeedUrl, '/home/shawshank?func=viewRdf', 'getRdfFeedUrl');
can_ok($dummy, qw/getStaticAtomFeedUrl getStaticRssFeedUrl getStaticRdfFeedUrl/);
is($dummy->getStaticAtomFeedUrl, '/home/shawshank.atom', 'getStaticAtomFeedUrl');
is($dummy->getStaticRssFeedUrl, '/home/shawshank.rss', 'getStaticRssFeedUrl');
is($dummy->getStaticRdfFeedUrl, '/home/shawshank.rdf', 'getStaticRdfFeedUrl');
$dummy->update({ url => 'dot.extension', });
is($dummy->getAtomFeedUrl, '/dot.extension?func=viewAtom', 'getAtomFeedUrl, url with extension');
is($dummy->getRssFeedUrl, '/dot.extension?func=viewRss', 'getRssFeedUrl, url with extension');
is($dummy->getRdfFeedUrl, '/dot.extension?func=viewRdf', 'getRdfFeedUrl, url with extension');
is($dummy->getStaticAtomFeedUrl, '/dot.extension.atom', 'getStaticAtomFeedUrl, url with extension');
is($dummy->getStaticRssFeedUrl, '/dot.extension.rss', 'getStaticRssFeedUrl, url with extension');
is($dummy->getStaticRdfFeedUrl, '/dot.extension.rdf', 'getStaticRdfFeedUrl, url with extension');
$dummy->update({ url => '/home/shawshank', });
#####################################################
#
# getFeed
#
#####################################################
my $feed = XML::FeedPP::RSS->new();
my $newFeed = $dummy->getFeed($feed);
isa_ok($newFeed, 'XML::FeedPP::RSS');
is($newFeed, $feed, 'getFeed returns the same object');
cmp_deeply(
$feed,
methods(
title => 'Dummy Title',
description => 'Dummy Synopsis', ##Not description
link => '/home/shawshank',
copyright => '',
),
'... title, description, link inherit from asset by default, copyright unset'
);
cmp_bag(
[ $feed->get_item() ],
[
methods(
title => 'this title',
description => 'this description',
'link' => 'this link',
guid => 'this link',
),
methods(
title => 'another title',
description => 'another description', ##Not description
guid => re('^[a-zA-Z0-9\-_]{22}'), ##GUID is a GUID since there's no link
),
],
'... contains 2 feed items with the correct contents'
);
$dummy->update({
feedCopyright => 'copyright 2009 Plain Black Corporation',
feedTitle => 'Rita Hayworth and the Shawshank Redemption',
feedDescription => 'A good movie, providing loads of testing collateral',
});
$feed = $dummy->getFeed(XML::FeedPP::RSS->new());
cmp_deeply(
$feed,
methods(
title => 'Rita Hayworth and the Shawshank Redemption',
description => 'A good movie, providing loads of testing collateral',
link => '/home/shawshank',
copyright => 'copyright 2009 Plain Black Corporation',
),
'... feed settings override asset defaults, copyright'
);
#####################################################
#
# exportAssetCollateral
#
#####################################################
my $exportStorage = WebGUI::Storage->create($session);
WebGUI::Test->storagesToDelete($exportStorage);
my $basedir = Path::Class::Dir->new($exportStorage->getPath);
my $assetdir = $basedir->subdir('shawshank');
my $indexfile = $assetdir->file('index.html');
mkpath($assetdir->stringify);
$dummy->exportAssetCollateral($indexfile, {}, $session);
cmp_bag(
$exportStorage->getFiles(),
[qw/
shawshank.rss shawshank
shawshank.atom
/],
'exportAssetCollateral: feed files exported, index.html file'
);
$exportStorage = WebGUI::Storage->create($session);
WebGUI::Test->storagesToDelete($exportStorage);
$basedir = Path::Class::Dir->new($exportStorage->getPath);
my $assetfile = $basedir->file('shawshank.html');
$dummy->exportAssetCollateral($assetfile, {}, $session);
cmp_bag(
$exportStorage->getFiles(),
[qw/
shawshank.html.rss
shawshank.html.atom
/],
'exportAssetCollateral: feed files exported, shawshank.html file'
);
#####################################################
#
# exportAssetCollateral
#
#####################################################
#----------------------------------------------------------------------------
# Cleanup
END {
$dummy->purge;
my $tag = WebGUI::VersionTag->getWorking($session, 'noCreate');
$tag->rollback if $tag;
}
#vim:ft=perl

View file

@ -96,7 +96,28 @@ my @macroParamSets = (
},
);
my $numTests = scalar @filterSets + scalar @macroParamSets;
my @htmlTextSets = (
{
inputText => q|I wish I could tell you that Andy fought the good fight.|,
output => q|I wish I could tell you that Andy fought the good fight.|,
comment => 'bare text',
},
{
inputText => q|The man likes to play chess; let's get him some rocks. |,
output => q|The man likes to play chess; let's get him some rocks.|,
comment => 'bare text with ending space has that space removed',
},
{
inputText => q|<p>Do you enjoy working in the laundry?</p>|,
output => qq|\nDo you enjoy working in the laundry?\n|,
comment => 'text in paragraph tag nested inside newlines',
},
);
my $numTests = scalar @filterSets
+ scalar @macroParamSets
+ scalar @htmlTextSets
;
plan tests => $numTests;
@ -109,3 +130,8 @@ foreach my $testSet (@macroParamSets) {
WebGUI::HTML::makeParameterSafe(\$testSet->{inputText});
is($testSet->{inputText}, $testSet->{output}, $testSet->{comment});
}
foreach my $testSet (@htmlTextSets) {
my $text = WebGUI::HTML::html2text($testSet->{inputText});
is($text, $testSet->{output}, $testSet->{comment});
}

View file

@ -18,6 +18,10 @@ use lib "$FindBin::Bin/../lib";
use JSON qw( from_json to_json );
use Test::More;
use File::Spec;
use Data::Dumper;
use MIME::Parser;
use Encode qw/decode/;
use WebGUI::Test;
use WebGUI::Mail::Send;
@ -36,19 +40,26 @@ BEGIN {
$hasServer = 1 unless $@;
}
# See if we have an SMTP server to use
# See if we have an SMTP server to use
my ( $smtpd );
my $SMTP_HOST = 'localhost';
my $SMTP_PORT = '54921';
if ($hasServer) {
$session->setting->set( 'smtpServer', $SMTP_HOST . ':' . $SMTP_PORT );
my $smtpd = File::Spec->catfile( WebGUI::Test->root, 't', 'smtpd.pl' );
open MAIL, "perl $smtpd $SMTP_HOST $SMTP_PORT 5 |"
or die "Could not open pipe to SMTPD: $!";
sleep 1; # Give the smtpd time to establish itself
}
#----------------------------------------------------------------------------
# Tests
plan tests => 6; # Increment this number for each test you create
plan tests => 11; # Increment this number for each test you create
#----------------------------------------------------------------------------
# Test create
@ -122,6 +133,7 @@ is( $mime->parts(0)->as_string =~ m/\n/, $newlines,
);
# TODO: Test that addHtml creates a body with the right content type
my $smtpServerOk = 0;
#----------------------------------------------------------------------------
# Test emailOverride
@ -137,22 +149,24 @@ SKIP: {
if ( !$hasServer ) {
skip "Cannot test emailOverride: Module Net::SMTP::Server not loaded!", $numtests;
}
$smtpServerOk = 1;
# Override the emailOverride
my $oldEmailOverride = $session->config->get('emailOverride');
$session->config->set( 'emailOverride', 'dufresne@localhost' );
my $oldEmailToLog = $session->config->get('emailToLog');
$session->config->set( 'emailToLog', 0 );
# Send the mail
my $mail
= WebGUI::Mail::Send->create( $session, {
to => 'norton@localhost',
} );
$mail->addText( 'His judgement cometh and that right soon.' );
my $received = sendToServer( $mail );
if (!$received) {
skip "Cannot test emailOverride: No response received from smtpd", $numtests;
}
@ -162,17 +176,104 @@ SKIP: {
"Email TO: address is overridden",
);
my $parser = MIME::Parser->new();
my $parsed_message = $parser->parse_data($received->{contents});
my $head = $parsed_message->head;
my $messageId = decode('MIME-Header', $head->get('Message-Id'));
like ($messageId, qr/^<WebGUI-([a-zA-Z0-9\-_]){22}@\w+\.\w{2,4}>$/, 'Message-Id is valid');
# Restore the emailOverride
$session->config->set( 'emailOverride', $oldEmailOverride );
$session->config->set( 'emailToLog', $oldEmailToLog );
}
SKIP: {
my $numtests = 4; # Number of tests in this block
skip "Cannot test message ids", $numtests unless $smtpServerOk;
# Send the mail
my $mail
= WebGUI::Mail::Send->create( $session, {
to => 'norton@localhost',
} );
$mail->addText( "I understand you're a man who knows how to get things." );
my $received = sendToServer( $mail );
if (!$received) {
skip "Cannot test messageIds: No response received from smtpd", $numtests;
}
# Test the mail
my $parser = MIME::Parser->new();
my $parsed_message = $parser->parse_data($received->{contents});
my $head = $parsed_message->head;
my $messageId = decode('MIME-Header', $head->get('Message-Id'));
chomp $messageId;
like ($messageId, qr/^<WebGUI-([a-zA-Z0-9\-_]){22}@\w+\.\w{2,4}>$/, 'generated Message-Id is valid');
# Send the mail
$mail
= WebGUI::Mail::Send->create( $session, {
to => 'norton@localhost',
messageId => '<leadingAngleOnly@localhost.localdomain',
} );
$mail->addText( "What say you there, fuzzy-britches? Feel like talking?" );
$received = sendToServer( $mail );
$parsed_message = $parser->parse_data($received->{contents});
$head = $parsed_message->head;
$messageId = decode('MIME-Header', $head->get('Message-Id'));
chomp $messageId;
is($messageId, '<leadingAngleOnly@localhost.localdomain>', 'bad messageId corrected (added ending angle)');
# Send the mail
$mail
= WebGUI::Mail::Send->create( $session, {
to => 'norton@localhost',
messageId => 'endingAngleOnly@localhost.localdomain>',
} );
$mail->addText( "Dear Warden, You were right. Salvation lies within." );
$received = sendToServer( $mail );
$parsed_message = $parser->parse_data($received->{contents});
$head = $parsed_message->head;
$messageId = decode('MIME-Header', $head->get('Message-Id'));
chomp $messageId;
is($messageId, '<endingAngleOnly@localhost.localdomain>', 'bad messageId corrected (added starting angle)');
# Send the mail
$mail
= WebGUI::Mail::Send->create( $session, {
to => 'red@localhost',
messageId => 'noAngles@localhost.localdomain',
} );
$mail->addText( "Neither are they. You have to be human first. They don't qualify." );
$received = sendToServer( $mail );
$parsed_message = $parser->parse_data($received->{contents});
$head = $parsed_message->head;
$messageId = decode('MIME-Header', $head->get('Message-Id'));
chomp $messageId;
is($messageId, '<noAngles@localhost.localdomain>', 'bad messageId corrected (added both angles)');
}
# TODO: Test the emailToLog config setting
#----------------------------------------------------------------------------
# Cleanup
END {
close MAIL
or die "Could not close pipe to SMTPD: $!";
sleep 1;
$session->db->write('delete from mailQueue');
}
#----------------------------------------------------------------------------
@ -189,21 +290,17 @@ END {
# by a MIME::Entity parser
sub sendToServer {
my $mail = shift;
my $smtpd = File::Spec->catfile( WebGUI::Test->root, 't', 'smtpd.pl' );
open MAIL, "perl $smtpd $SMTP_HOST $SMTP_PORT |"
or die "Could not open pipe to SMTPD: $!";
sleep 1; # Give the smtpd time to establish itself
$mail->send;
my $status = $mail->send;
my $json;
while ( my $line = <MAIL> ) {
$json .= $line;
if ($status) {
$json = <MAIL>;
}
else {
$json = ' { "error": "mail not sent" } ';
}
if (!$json) {
$json = ' { "error": "error in getting mail" } ';
}
close MAIL
or die "Could not close pipe to SMTPD: $!";
return from_json( $json );
}

View file

@ -17,19 +17,23 @@ use FindBin;
use strict;
use lib "$FindBin::Bin/lib";
use Test::More;
use Data::Dumper;
use WebGUI::Test; # Must use this before any other WebGUI modules
use WebGUI::Session;
use WebGUI::Form::Text;
use WebGUI::Form::HTMLArea;
#----------------------------------------------------------------------------
# Init
my $session = WebGUI::Test->session;
my $newUser = WebGUI::User->create( $session );
WebGUI::Test->usersToDelete($newUser);
#----------------------------------------------------------------------------
# Tests
plan tests => 17; # Increment this number for each test you create
plan tests => 20; # Increment this number for each test you create
#----------------------------------------------------------------------------
# Test the creation of ProfileField
@ -66,19 +70,42 @@ like( $ff, qr/value="$ffvalue"[^>]+selected/, 'html returned contains value, uiL
$ff = undef;
$ffvalue = undef;
ok( $ff = $aliasField->formField(undef, undef, $newUser), 'formField method returns something, alias field, defaulted user' );
my $ffvalue = $newUser->profileField('alias');
$ffvalue = $newUser->profileField('alias');
like( $ff, qr/$ffvalue/, 'html returned contains value, alias field, defaulted user' );
$ff = undef;
$ffvalue = undef;
ok( $ff = $uilevelField->formField(undef, undef, $newUser), 'formField method returns something, uiLevel field, defaulted user' );
my $ffvalue = $newUser->profileField('uiLevel');
$ffvalue = $newUser->profileField('uiLevel');
like( $ff, qr/$ffvalue/, 'html returned contains value, uiLevel field, defaulted user' );
#########################################################
#
# set, changing fieldTypes
#
#########################################################
my $newProfileField = WebGUI::ProfileField->create($session, 'testField', {
fieldType => 'Text',
label => 'Test Field',
});
my $textFieldType = lc WebGUI::Form::Text->getDatabaseFieldType();
my $htmlFieldType = lc WebGUI::Form::HTMLArea->getDatabaseFieldType();
my $fieldSpec = $session->db->quickHashRef('describe userProfileData testField');
is (lc $fieldSpec->{Type}, $textFieldType, 'test field created with correct type for text field');
$newProfileField->set({ fieldType => 'HTMLArea' });
is($newProfileField->get('fieldType'), 'HTMLArea', 'test field updated to HTMLArea');
$fieldSpec = $session->db->quickHashRef('describe userProfileData testField');
is (lc $fieldSpec->{Type}, $htmlFieldType, 'database updated along with profile field object');
#----------------------------------------------------------------------------
# Cleanup
END {
$newUser->delete;
$newProfileField->delete;
}

View file

@ -0,0 +1,127 @@
#-------------------------------------------------------------------
# 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
#-------------------------------------------------------------------
use FindBin;
use strict;
use lib "$FindBin::Bin/../../lib";
use WebGUI::Test;
use WebGUI::Asset;
use WebGUI::Asset::Story;
use WebGUI::Asset::Wobject::StoryArchive;
use WebGUI::Workflow::Activity::ArchiveOldStories;
use Data::Dumper;
use Test::More;
use Test::Deep;
plan tests => 6; # increment this value for each test you create
my $session = WebGUI::Test->session;
$session->user({userId => 3});
my $home = WebGUI::Asset->getDefault($session);
my $wgBday = WebGUI::Test->webguiBirthday;
my $creationDateSth = $session->db->prepare('update asset set creationDate=? where assetId=?');
my $archive1 = $home->addChild({
className => 'WebGUI::Asset::Wobject::StoryArchive',
title => '2001 Stories',
archiveAfter => 50*365*24*3600, ##50 years ago
});
my $birthdayFolder = $archive1->getFolder($wgBday);
$creationDateSth->execute([$wgBday, $birthdayFolder->getId]);
my @oldStories = ();
push @oldStories, $birthdayFolder->addChild({ className => 'WebGUI::Asset::Story',});
push @oldStories, $birthdayFolder->addChild({ className => 'WebGUI::Asset::Story',});
foreach my $story (@oldStories) {
$creationDateSth->execute([$wgBday, $story->getId]);
}
my $archive2 = $home->addChild({
className => 'WebGUI::Asset::Wobject::StoryArchive',
title => 'Stories from last week',
archiveAfter => 10*24*3600, #10 days ago
});
my $weekAgo = time() - (7*24*3600);
my $weekFolder = $archive2->getFolder($weekAgo);
my $weekStory = $weekFolder->addChild({className => 'WebGUI::Asset::Story',});
$creationDateSth->execute([$weekAgo, $weekFolder->getId]);
$creationDateSth->execute([$weekAgo, $weekStory->getId]);
my $versionTag = WebGUI::VersionTag->getWorking($session);
$versionTag->commit;
my $workflow = WebGUI::Workflow->create($session,
{
enabled => 1,
objectType => 'None',
mode => 'realtime',
},
);
my $activity = $workflow->addActivity('WebGUI::Workflow::Activity::ArchiveOldStories');
my $instance1 = WebGUI::Workflow::Instance->create($session,
{
workflowId => $workflow->getId,
skipSpectreNotification => 1,
}
);
my $retVal;
$retVal = $instance1->run();
is($retVal, 'complete', 'First workflow was run');
$retVal = $instance1->run();
is($retVal, 'done', 'Workflow is done');
my $archivedAssets = $home->getLineage(
['descendants'],
{
includeOnlyClasses => ['WebGUI::Asset::Story', 'WebGUI::Asset::Wobject::Folder', 'WebGUI::Asset::Wobject::StoryArchive'],
statusToInclude => ['archived'],
},
);
cmp_bag( $archivedAssets, [ ], 'Nothing archived.');
$archive2->update({ archiveAfter => 5*24*3600, });
my $instance2 = WebGUI::Workflow::Instance->create($session,
{
workflowId => $workflow->getId,
skipSpectreNotification => 1,
}
);
$retVal = $instance2->run();
is($retVal, 'complete', 'Second workflow was run');
$retVal = $instance2->run();
is($retVal, 'done', 'Workflow is done');
$archivedAssets = $home->getLineage(
['descendants'],
{
includeOnlyClasses => ['WebGUI::Asset::Story', 'WebGUI::Asset::Wobject::Folder', 'WebGUI::Asset::Wobject::StoryArchive'],
statusToInclude => ['archived'],
},
);
cmp_bag( $archivedAssets, [ $weekStory->getId, $weekFolder->getId ], 'Nothing archived.');
END {
$creationDateSth->finish;
$versionTag->rollback;
$workflow->delete;
}

View file

@ -90,4 +90,3 @@ END {
defined $session &&
$session->config->set('macros', $originalMacros);
}

View file

@ -0,0 +1,74 @@
package WebGUI::Asset::RssAspectDummy;
=head1 LEGAL
-------------------------------------------------------------------
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
-------------------------------------------------------------------
=cut
use strict;
use Tie::IxHash;
use Class::C3;
use base qw/WebGUI::AssetAspect::RssFeed WebGUI::Asset/;
=head1 NAME
Package WebGUI::Asset::RssAspectDummy
=head1 DESCRIPTION
A dummy module for testing the RssAspect. The module really doesn't
do anything, except provide suport modules for testing.
The module inherits directly from WebGUI::Asset.
=head1 SYNOPSIS
use WebGUI::Asset::RssAspectDummy;
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
=head2 getRssFeedItems ( )
Returns an arrayref of hashrefs, containing information on stories
for generating an RSS and Atom feeds.
=cut
sub getRssFeedItems {
return [
{
title => 'this title',
description => 'this description',
'link' => 'this link',
author => 'this author',
date => 'this date',
},
{
title => 'another title',
description => 'another description',
author => 'another author',
date => 'another date',
},
];
}
1;
#vim:ft=perl

View file

@ -374,6 +374,20 @@ sub session {
return $SESSION;
}
#----------------------------------------------------------------------------
=head2 webguiBirthday ( )
This constant is used in several tests, so it's reproduced here so it can
be found easy. This is the epoch date when WebGUI was released.
=cut
sub webguiBirthday {
return 997966800 ;
}
#----------------------------------------------------------------------------

View file

@ -1,6 +1,7 @@
my $HOST = shift;
my $PORT = shift;
my $EMAILS = shift || 1;
die "HOST must be first argument"
unless $HOST;
@ -13,17 +14,26 @@ use Net::SMTP::Server::Client;
my $server = Net::SMTP::Server->new( $HOST, $PORT );
while ( my $conn = $server->accept ) {
my $counter = 0;
$| = 1;
CONNECTION: while ( my $conn = $server->accept ) {
my $client = Net::SMTP::Server::Client->new( $conn );
$client->process;
print to_json({
to => $client->{TO},
from => $client->{FROM},
contents => $client->{MSG},
counter => $counter,
emails => $EMAILS,
});
exit(0);
print "\n";
last CONNECTION if ++$counter >= $EMAILS;
}
sleep 3;
exit(0);
=head1 NAME