Content of file DefaultBlogViewControllerTest.java
/*
* #%L
* *********************************************************************************************************************
*
* NorthernWind - lightweight CMS
* http://northernwind.tidalwave.it - git clone https://bitbucket.org/tidalwave/northernwind-src.git
* %%
* Copyright (C) 2011 - 2023 Tidalwave s.a.s. (http://tidalwave.it)
* %%
* *********************************************************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* *********************************************************************************************************************
*
*
* *********************************************************************************************************************
* #L%
*/
package it.tidalwave.northernwind.frontend.ui.component.blog;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.ZonedDateTime;
import it.tidalwave.util.Id;
import it.tidalwave.util.Key;
import it.tidalwave.util.LocalizedDateTimeFormatters;
import it.tidalwave.role.ContextManager;
import it.tidalwave.role.spi.DefaultContextManagerProvider;
import it.tidalwave.northernwind.core.model.Content;
import it.tidalwave.northernwind.core.model.HttpStatusException;
import it.tidalwave.northernwind.core.model.Request;
import it.tidalwave.northernwind.core.model.RequestContext;
import it.tidalwave.northernwind.core.model.RequestLocaleManager;
import it.tidalwave.northernwind.core.model.ResourcePath;
import it.tidalwave.northernwind.core.model.ResourceProperties;
import it.tidalwave.northernwind.core.model.Site;
import it.tidalwave.northernwind.core.model.SiteNode;
import it.tidalwave.northernwind.frontend.ui.RenderContext;
import it.tidalwave.northernwind.frontend.ui.spi.DefaultRenderContext;
import it.tidalwave.northernwind.frontend.ui.component.blog.DefaultBlogViewController.TagAndCount;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import it.tidalwave.northernwind.core.impl.model.mock.MockContentSiteFinder;
import it.tidalwave.northernwind.core.impl.model.mock.MockSiteNodeSiteFinder;
import lombok.extern.slf4j.Slf4j;
import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;
import static it.tidalwave.northernwind.util.CollectionFunctions.*;
import static it.tidalwave.northernwind.core.impl.model.mock.MockModelFactory.*;
import static it.tidalwave.northernwind.frontend.ui.component.Properties.*;
import static it.tidalwave.northernwind.frontend.ui.component.blog.BlogViewController.*;
import static it.tidalwave.northernwind.frontend.ui.component.blog.DefaultBlogViewController.DEFAULT_TIMEZONE;
import static it.tidalwave.northernwind.frontend.ui.component.nodecontainer.NodeContainerViewController.*;
import static org.mockito.Mockito.*;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
/***********************************************************************************************************************
*
* @author Fabrizio Giudici
*
**********************************************************************************************************************/
@Slf4j
public class DefaultBlogViewControllerTest
{
static class UnderTest extends DefaultBlogViewController
{
public final List<Content> _fullPosts = new ArrayList<>();
public final List<Content> _leadInPosts = new ArrayList<>();
public final List<Content> _linkedPosts = new ArrayList<>();
public final List<TagAndCount> tagsAndCount = new ArrayList<>();
public UnderTest (@Nonnull final SiteNode siteNode,
@Nonnull final BlogView view,
@Nonnull final RequestLocaleManager requestLocaleManager)
{
super(siteNode, view, requestLocaleManager);
}
@Override
protected void renderPosts (@Nonnull final List<Content> fullPosts,
@Nonnull final List<Content> leadinPosts,
@Nonnull final List<Content> linkedPosts)
{
_fullPosts.addAll(fullPosts);
_leadInPosts.addAll(leadinPosts);
_linkedPosts.addAll(linkedPosts);
}
@Override
protected void renderTagCloud (@Nonnull final Collection<TagAndCount> tagsAndCount)
{
this.tagsAndCount.addAll(tagsAndCount);
}
}
private static final String SITE_NODE_RELATIVE_URI = "/blogNode";
private SiteNode siteNode;
private UnderTest underTest;
private ResourceProperties viewProperties;
private RenderContext renderContext;
private Request request;
private RequestContext requestContext;
private RequestLocaleManager requestLocaleManager;
private MockPosts mockPosts;
private final Id viewId = new Id("viewId");
/*******************************************************************************************************************
*
******************************************************************************************************************/
@BeforeMethod
private void setup()
throws Exception
{
ContextManager.Locator.set(new DefaultContextManagerProvider()); // TODO: try to get rid of this
final Site site = createMockSite();
MockSiteNodeSiteFinder.registerTo(site);
MockContentSiteFinder.registerTo(site);
viewProperties = createMockProperties();
final ResourceProperties siteNodeProperties = createMockProperties();
siteNode = createMockSiteNode(site);
when(siteNode.getProperties()).thenReturn(siteNodeProperties);
when(siteNode.getPropertyGroup(eq(viewId))).thenReturn(viewProperties);
when(siteNode.getRelativeUri()).thenReturn(ResourcePath.of(SITE_NODE_RELATIVE_URI));
final BlogView view = mock(BlogView.class);
when(view.getId()).thenReturn(viewId);
request = mock(Request.class);
requestContext = mock(RequestContext.class);
renderContext = new DefaultRenderContext(request, requestContext);
when(request.getPathParams(same(siteNode))).thenReturn(ResourcePath.EMPTY);
requestLocaleManager = mock(RequestLocaleManager.class);
mockPosts = new MockPosts(site, viewProperties);
underTest = new UnderTest(siteNode, view, requestLocaleManager);
underTest.initialize();
}
/*******************************************************************************************************************
*
******************************************************************************************************************/
@Test(dataProvider = "postRenderingTestData")
public void must_properly_render_posts (final int seed,
final int maxFullItems,
final int maxLeadinItems,
final int maxItems,
@Nonnull final String pathParams,
@Nonnull final String expectedTitle,
@Nonnull final List<Integer> expectedFullPostIds,
@Nonnull final List<Integer> expectedLeadInPostIds,
@Nonnull final List<Integer> expectedLinkedPostIds)
throws Exception
{
// given
mockPosts.createMockData(seed);
when(viewProperties.getProperty(P_MAX_FULL_ITEMS)).thenReturn(Optional.of(maxFullItems));
when(viewProperties.getProperty(P_MAX_LEADIN_ITEMS)).thenReturn(Optional.of(maxLeadinItems));
when(viewProperties.getProperty(P_MAX_ITEMS)).thenReturn(Optional.of(maxItems));
when(request.getPathParams(same(siteNode))).thenReturn(ResourcePath.of(pathParams));
underTest.prepareRendering(renderContext);
// when
underTest.renderView(renderContext);
// then
underTest._fullPosts.forEach (post -> log.info(">>>> full: {}", post));
underTest._leadInPosts.forEach(post -> log.info(">>>> lead in: {}", post));
underTest._linkedPosts.forEach(post -> log.info(">>>> linked: {}", post));
final List<Integer> actualFullPostsIds = getPostIds(underTest._fullPosts);
final List<Integer> actualLeadInPostsIds = getPostIds(underTest._leadInPosts);
final List<Integer> actualLinkedPostsIds = getPostIds(underTest._linkedPosts);
assertThat("full posts", actualFullPostsIds, is(expectedFullPostIds));
assertThat("leadIn posts", actualLeadInPostsIds, is(expectedLeadInPostIds));
assertThat("all posts", actualLinkedPostsIds, is(expectedLinkedPostIds));
final List<Content> allPosts = concat(underTest._fullPosts, underTest._leadInPosts, underTest._linkedPosts);
final List<ZonedDateTime> publishingDates = allPosts
.stream()
.map(post -> post.getProperty(Content.P_PUBLISHING_DATE).get())
.collect(toList());
assertSortedInReverseOrder(publishingDates);
if (!"/tags".equals(pathParams))
{
assertThat(underTest.tagsAndCount.size(), is(0)); // TODO: should be: method not called
}
else
{
assertThat(underTest.tagsAndCount.size(), is(10));
}
}
/*******************************************************************************************************************
*
******************************************************************************************************************/
@Test(dataProvider = "postRenderingTestDataNotFound",
expectedExceptions = HttpStatusException.class,
expectedExceptionsMessageRegExp = ".*httpStatus=404.*")
public void must_throw_NotFound (final int seed,
final int maxFullItems,
final int maxLeadinItems,
final int maxItems,
@Nonnull final String pathParams)
throws Exception
{
// given
mockPosts.createMockData(seed);
when(viewProperties.getProperty(P_MAX_FULL_ITEMS)).thenReturn(Optional.of(maxFullItems));
when(viewProperties.getProperty(P_MAX_LEADIN_ITEMS)).thenReturn(Optional.of(maxLeadinItems));
when(viewProperties.getProperty(P_MAX_ITEMS)).thenReturn(Optional.of(maxItems));
when(request.getPathParams(same(siteNode))).thenReturn(ResourcePath.of(pathParams));
underTest.prepareRendering(renderContext);
// when
underTest.renderView(renderContext);
// then should throw exception
}
/*******************************************************************************************************************
*
******************************************************************************************************************/
@Test(dataProvider = "postRenderingTestDataBadRequest",
expectedExceptions = HttpStatusException.class,
expectedExceptionsMessageRegExp = ".*httpStatus=400.*")
public void must_throw_BadRequest_with_bad_path_params (final int seed,
final int maxFullItems,
final int maxLeadinItems,
final int maxItems,
@Nonnull final String pathParams)
throws Exception
{
// given
mockPosts.createMockData(seed);
when(viewProperties.getProperty(P_MAX_FULL_ITEMS)).thenReturn(Optional.of(maxFullItems));
when(viewProperties.getProperty(P_MAX_LEADIN_ITEMS)).thenReturn(Optional.of(maxLeadinItems));
when(viewProperties.getProperty(P_MAX_ITEMS)).thenReturn(Optional.of(maxItems));
when(request.getPathParams(same(siteNode))).thenReturn(ResourcePath.of(pathParams));
underTest.prepareRendering(renderContext);
// when
underTest.renderView(renderContext);
// then should throw exception
}
/*******************************************************************************************************************
*
******************************************************************************************************************/
@Test(dataProvider = "tagCloudRenderingTestData")
public void must_properly_render_tag_cloud (final int seed,
final List<TagAndCount> expectedTags)
throws Exception
{
// given
mockPosts.createMockData(seed);
when(viewProperties.getProperty(P_TAG_CLOUD)).thenReturn(Optional.of(true));
underTest.prepareRendering(renderContext);
// when
underTest.renderView(renderContext);
// then
final List<Content> allPosts = concat(underTest._fullPosts, underTest._leadInPosts, underTest._linkedPosts);
assertThat("full posts", underTest._fullPosts.size(), is(0)); // TODO: should be: method not called
assertThat("leadIn posts", underTest._leadInPosts.size(), is(0)); // TODO: should be: method not called
assertThat("all posts", allPosts.size(), is(0)); // TODO: should be: method not called
final List<TagAndCount> actualTacs = underTest.tagsAndCount
.stream()
.sorted(comparing(TagAndCount::getCount).reversed().thenComparing(TagAndCount::getTag))
.collect(toList());
actualTacs.forEach(tac -> log.info(">>>> {} ", tac));
assertThat(actualTacs, is(expectedTags));
}
/*******************************************************************************************************************
*
******************************************************************************************************************/
@Test(dataProvider = "tagCloudRenderingTestData")
public void must_properly_render_tag_cloud2 (final int seed, // TODO: dup code from the previous test
final List<TagAndCount> expectedTags)
throws Exception
{
// given
mockPosts.createMockData(seed);
when(request.getPathParams(same(siteNode))).thenReturn(ResourcePath.of("tags"));
underTest.prepareRendering(renderContext);
// when
underTest.renderView(renderContext);
// then
final List<Content> allPosts = concat(underTest._fullPosts, underTest._leadInPosts, underTest._linkedPosts);
assertThat("full posts", underTest._fullPosts.size(), is(0)); // TODO: should be: method not called
assertThat("leadIn posts", underTest._leadInPosts.size(), is(0)); // TODO: should be: method not called
assertThat("all posts", allPosts.size(), is(0)); // TODO: should be: method not called