// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software Foundation;
// either version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: TestSearchFeedEvents.java,v 1.8 2006/07/18 10:19:49 spyromus Exp $
//
package com.salas.bb.domain;
import org.jmock.Mock;
import org.jmock.MockObjectTestCase;
import com.salas.bb.domain.query.articles.Query;
import com.salas.bb.domain.query.articles.ArticleStatusProperty;
import com.salas.bb.domain.query.ICriteria;
import com.salas.bb.domain.query.general.StringEqualsCO;
import com.salas.bb.domain.utils.DomainEventsListener;
import com.salas.bb.core.SearchFeedsManager;
import java.util.Date;
/**
* This suite contains tests for <code>SearchFeed</code> unit.
*/
public class TestSearchFeedEvents extends MockObjectTestCase
{
private static int articlesCounter = 0;
private SearchFeed searchFeed;
private DirectFeed dataFeed;
private Mock listener;
protected void setUp()
throws Exception
{
super.setUp();
listener = new Mock(IFeedListener.class);
dataFeed = new DirectFeed();
StandardGuide standardGuide = new StandardGuide();
standardGuide.add(dataFeed);
GuidesSet guidesSet = new GuidesSet();
guidesSet.add(standardGuide);
DomainEventsListener domainEventsListener = new DomainEventsListener(guidesSet);
searchFeed = new SearchFeed();
searchFeed.setBaseTitle("Unread");
searchFeed.setArticlesLimit(1);
searchFeed.setQuery(createArticlesQuery(false));
searchFeed.addListener((IFeedListener)listener.proxy());
standardGuide.add(searchFeed);
SearchFeedsManager manager = new SearchFeedsManager(guidesSet);
domainEventsListener.addDomainListener(manager);
}
/**
* Tests events when adding single article matching the criteria.
*/
public void testSingleAdditionOfMatchingArticle()
{
searchFeed.setArticlesLimit(1);
assertEquals(0, searchFeed.getArticlesCount());
// adding unread article
StandardArticle unreadArticle = createArticle(false);
expectArticleAdded(unreadArticle);
expectUnreadCounterChange(0, 1);
dataFeed.appendArticle(unreadArticle);
listener.verify();
}
/**
* Firing events on the query change.
*/
public void testQueryChange()
{
searchFeed.setArticlesLimit(1);
assertEquals(0, searchFeed.getArticlesCount());
// We have four articles: two read and two unread.
// The indices of articles reflect their order, meaning the greater index --
// the newer article.
StandardArticle unreadArticle1 = createArticle(false);
StandardArticle unreadArticle2 = createArticle(false);
StandardArticle readArticle1 = createArticle(true);
StandardArticle readArticle2 = createArticle(true);
// When we will be adding articles we expect the first unread to be added
// first and later replaced by second unread as it's newer and limit is set
// to 1.
expectArticleAdded(unreadArticle1);
expectUnreadCounterChange(0, 1);
expectArticleAdded(unreadArticle2);
expectArticleRemoved(unreadArticle1);
dataFeed.appendArticle(unreadArticle1);
dataFeed.appendArticle(unreadArticle2);
dataFeed.appendArticle(readArticle1);
dataFeed.appendArticle(readArticle2);
listener.verify();
// Wen we will be changing query we expect the unread article to be replaced
// with read article.
Query readQuery = createArticlesQuery(true);
expectUnreadCounterChange(1, 0);
expectQueryChange(searchFeed.getQuery(), readQuery);
expectProcessingChange(true);
expectArticleRemoved(unreadArticle2);
expectArticleAdded(readArticle1);
expectArticleRemoved(readArticle1);
expectArticleAdded(readArticle2);
expectProcessingChange(false);
expectUpdateTimeChange();
searchFeed.setQuery(readQuery);
listener.verify();
}
private void expectUpdateTimeChange()
{
listener.expects(once()).method("propertyChanged").with(same(searchFeed),
eq(DirectFeed.PROP_LAST_UPDATE_TIME), not(eq(-1l)), not(eq(-1l)));
}
/**
* Tests replacement of leaving articles (which do not match any more) with the
* articles from back-pack (which aren't visible because of articlesLimit).
*/
public void testReplacement()
{
searchFeed.setArticlesLimit(1);
assertEquals(0, searchFeed.getArticlesCount());
// We have two unread articles. We will be reading them and watching
// how the changes in visibility are reported.
StandardArticle unreadArticle1 = createArticle(false);
StandardArticle unreadArticle2 = createArticle(false);
expectArticleAdded(unreadArticle1);
expectUnreadCounterChange(0, 1);
expectArticleAdded(unreadArticle2);
expectArticleRemoved(unreadArticle1);
dataFeed.appendArticle(unreadArticle1);
dataFeed.appendArticle(unreadArticle2);
listener.verify();
// Now read the second to let it go and to let first appear
expectArticleRemoved(unreadArticle2);
expectUnreadCounterChange(1, 0);
unreadArticle2.setRead(true);
listener.verify();
}
private void expectProcessingChange(boolean falseToTrue)
{
listener.expects(once()).method("propertyChanged").with(same(searchFeed),
eq(SearchFeed.PROP_PROCESSING), eq(!falseToTrue), eq(falseToTrue));
}
private void expectQueryChange(Query oldQuery, Query newQuery)
{
listener.expects(once()).method("propertyChanged").with(same(searchFeed),
eq(SearchFeed.PROP_QUERY), same(oldQuery), same(newQuery));
}
private void expectArticleRemoved(StandardArticle aUnreadArticle)
{
listener.expects(once()).method("articleRemoved").with(same(searchFeed),
same(aUnreadArticle));
}
private void expectArticleAdded(StandardArticle aUnreadArticle)
{
listener.expects(once()).method("articleAdded").with(same(searchFeed),
same(aUnreadArticle));
}
private void expectUnreadCounterChange(int from, int to)
{
listener.expects(once()).method("propertyChanged").with(same(searchFeed),
eq(IFeed.PROP_UNREAD_ARTICLES_COUNT), eq(from), eq(to));
}
private static synchronized StandardArticle createArticle(boolean read)
{
String txt = Integer.toString(articlesCounter);
StandardArticle article = new StandardArticle(txt);
article.setTitle(txt);
article.setRead(read);
article.setPublicationDate(new Date(articlesCounter));
articlesCounter++;
return article;
}
private static Query createArticlesQuery(boolean read)
{
Query sampleQuery = new Query();
ICriteria sampleCriteria = sampleQuery.addCriteria();
sampleCriteria.setProperty(ArticleStatusProperty.INSTANCE);
sampleCriteria.setComparisonOperation(StringEqualsCO.INSTANCE);
sampleCriteria.setValue(read
? ArticleStatusProperty.VALUE_READ
: ArticleStatusProperty.VALUE_UNREAD);
return sampleQuery;
}
}