Skip to content

Commit

Permalink
jbake issue jbake-org#652: prev/next post navigation only uses publis…
Browse files Browse the repository at this point in the history
…hed posts
  • Loading branch information
mhoennig committed Oct 28, 2020
1 parent c9989a3 commit 4d70a98
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 75 deletions.
48 changes: 34 additions & 14 deletions jbake-core/src/main/java/org/jbake/render/DocumentsRenderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,42 @@ public int render(Renderer renderer, ContentStore db, JBakeConfiguration config)
int renderedCount = 0;
final List<String> errors = new LinkedList<>();
for (String docType : DocumentTypes.getDocumentTypes()) {
DocumentList documentList = db.getUnrenderedContent(docType);
final DocumentList documentList = db.getUnrenderedContent(docType);

if (documentList == null) {
continue;
}

int index = 0;

Map<String, Object> nextDocument = null;
Map<String, Object> nextDocumentForNav = null;

while (index < documentList.size()) {
try {
Map<String, Object> document = documentList.get(index);
document.put("nextContent", null);
document.put("previousContent", null);
final Map<String, Object> documentToRender = documentList.get(index);
documentToRender.put("nextContent", null);
documentToRender.put("previousContent", null);

if (index > 0) {
document.put("nextContent", getContentForNav(nextDocument));
if (nextDocumentForNav != null) {
documentToRender.put("nextContent", getContentForNav(nextDocumentForNav));
}

if (index < documentList.size() - 1) {
Map<String, Object> tempNext = documentList.get(index + 1);
document.put("previousContent", getContentForNav(tempNext));
Map<String, Object> prevDocumentForNav = findPrevPublishedDocument(documentList, index);
if (prevDocumentForNav != null) {
documentToRender.put("previousContent", getContentForNav(prevDocumentForNav));
}
}

nextDocument = document;
if (isPublished(documentToRender)) {
nextDocumentForNav = documentToRender;
}

renderer.render(document);
renderer.render(documentToRender);
renderedCount++;

} catch (Exception e) {
errors.add(e.getMessage());
errors.add(e.getMessage() != null ? e.getMessage() : e.getClass().getName());
}

index++;
Expand All @@ -73,11 +77,27 @@ public int render(Renderer renderer, ContentStore db, JBakeConfiguration config)
}
}

private Map<String, Object> findPrevPublishedDocument(DocumentList documentList, int index) {
for ( int prevDocIndex = index+1; prevDocIndex < documentList.size(); ++prevDocIndex ) {
Map<String, Object> prevDocument = documentList.get(prevDocIndex);
if (isPublished(prevDocument)) {
return prevDocument;
}
}
return null;
}

private boolean isPublished(Map<String, Object> document) {
// Attributes.Status.PUBLISHED_DATE cannot occur here
// because it's converted TO either PUBLISHED or DRAFT in the Crawler.
return Attributes.Status.PUBLISHED.equals(document.get(Attributes.STATUS));
}

/**
* Creates a simple content model to use in individual post navigations.
*
* @param document
* @return
* @param document original
* @return navigation model for the 'document'
*/
private Map<String, Object> getContentForNav(Map<String, Object> document) {
Map<String, Object> navDocument = new HashMap<>();
Expand Down
125 changes: 64 additions & 61 deletions jbake-core/src/test/java/org/jbake/render/DocumentsRendererTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
Expand All @@ -19,6 +20,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
Expand All @@ -30,9 +32,7 @@

public class DocumentsRendererTest {

@Rule
public ExpectedException exception = ExpectedException.none();
private DocumentsRenderer documentsRenderer;
public DocumentsRenderer documentsRenderer;
private ContentStore db;
private Renderer renderer;
private JBakeConfiguration configuration;
Expand Down Expand Up @@ -87,94 +87,97 @@ public void shouldReturnCountOfProcessedDocuments() throws Exception {
}

@Test
public void shouldThrowAnExceptionWithCollectedErrorMessages() throws Exception {
public void shouldThrowAnExceptionWithCollectedErrorMessages() {
String fakeExceptionMessage = "fake exception";
// expect
exception.expect(RenderingException.class);
exception.expectMessage(fakeExceptionMessage + "\n" + fakeExceptionMessage);

// given
DocumentTypes.addDocumentType("customType");

DocumentList documentList = new DocumentList();
HashMap<String, Object> document = emptyDocument();
HashMap<String, Object> document2 = emptyDocument();
documentList.add(document);
documentList.add(document2);

// throw an exception for every call of renderer's render method
doThrow(new Exception(fakeExceptionMessage)).when(renderer).render(ArgumentMatchers.<String, Object>anyMap());
when(db.getUnrenderedContent(anyString())).thenReturn(emptyDocumentList);
when(db.getUnrenderedContent("customType")).thenReturn(documentList);

// when
int renderResponse = documentsRenderer.render(renderer, db, configuration);

// then
assertThat(renderResponse).isEqualTo(2);
// expect
Assertions.assertThrows(
RenderingException.class, () -> {

// given
DocumentTypes.addDocumentType("customType");

DocumentList documentList = new DocumentList();
HashMap<String, Object> document = emptyDocument();
HashMap<String, Object> document2 = emptyDocument();
documentList.add(document);
documentList.add(document2);

// throw an exception for every call of renderer's render method
doThrow(new Exception(fakeExceptionMessage)).when(renderer).render(ArgumentMatchers.anyMap());
when(db.getUnrenderedContent(anyString())).thenReturn(emptyDocumentList);
when(db.getUnrenderedContent("customType")).thenReturn(documentList);

// when
int renderResponse = documentsRenderer.render(renderer, db, configuration);

// then
assertThat(renderResponse).isEqualTo(2);
},
fakeExceptionMessage + "\n" + fakeExceptionMessage
);
}

@Test
public void shouldContainPostNavigation() throws Exception {
// given
DocumentTypes.addDocumentType("customType");

String first = "First Document";
String second = "Second Document";
String third = "Third Document";
String fourth = "Fourth Document";
String firstTitle = "First Document";
String secondTitleIsDraft = "Second Document (draft)";
String thirdTitle = "Third Document";
String fourthTitle = "Fourth Document";

DocumentList documents = new DocumentList();
documents.add(simpleDocument(fourth));
documents.add(simpleDocument(third));
documents.add(simpleDocument(second));
documents.add(simpleDocument(first));
// Attributes.Status.PUBLISHED_DATE cannot occur here
// because it's converted TO either PUBLISHED or DRAFT in the Crawler.
documents.add(simpleDocument(fourthTitle, Attributes.Status.PUBLISHED));
documents.add(simpleDocument(thirdTitle, Attributes.Status.PUBLISHED));
documents.add(simpleDocument(secondTitleIsDraft, Attributes.Status.DRAFT));
documents.add(simpleDocument(firstTitle, Attributes.Status.PUBLISHED));

when(db.getUnrenderedContent("customType")).thenReturn(documents);

// when
int renderResponse = documentsRenderer.render(renderer, db, configuration);

Map<String, Object> fourthDoc = simpleDocument(fourth);
fourthDoc.put("previousContent", simpleDocument(third));
fourthDoc.put("nextContent", null);

Map<String, Object> thirdDoc = simpleDocument(third);
thirdDoc.put("nextContent", simpleDocument(fourth));
thirdDoc.put("previousContent", simpleDocument(second));

Map<String, Object> secondDoc = simpleDocument(second);
secondDoc.put("nextContent", simpleDocument(third));
secondDoc.put("previousContent", simpleDocument(first));

Map<String, Object> firstDoc = simpleDocument(first);
firstDoc.put("nextContent", simpleDocument(second));
firstDoc.put("previousContent", null);

// then
verify(renderer, times(4)).render(argument.capture());

List<Map<String, Object>> maps = argument.getAllValues();

assertThat(maps).contains(fourthDoc);

assertThat(maps).contains(thirdDoc);

assertThat(maps).contains(secondDoc);
final Map<String, Map<String, Object>> renderedDocs = asTitleToDocMap(argument.getAllValues());
assertDocumentNavigation(renderedDocs.get(firstTitle), null, thirdTitle);
assertDocumentNavigation(renderedDocs.get(secondTitleIsDraft), firstTitle, thirdTitle);
assertDocumentNavigation(renderedDocs.get(thirdTitle), firstTitle, fourthTitle);
assertDocumentNavigation(renderedDocs.get(fourthTitle), thirdTitle, null);
assertThat(renderResponse).isEqualTo(4);
}

assertThat(maps).contains(firstDoc);
private void assertDocumentNavigation(
final Map<String, Object> renderedDoc,
final String prevDocumentTitle, String nextDocumentTitle) {
assertThat(renderedDoc).flatExtracting(
"previousContent." + Attributes.TITLE,
"nextContent." + Attributes.TITLE)
.containsExactly(prevDocumentTitle, nextDocumentTitle);
}

assertThat(renderResponse).isEqualTo(4);
private Map<String, Map<String, Object>> asTitleToDocMap(List<Map<String, Object>> values) {
return values.stream()
.collect(Collectors.toMap(doc -> doc.get(Attributes.TITLE).toString(), doc -> doc));
}

private HashMap<String, Object> emptyDocument() {
return new HashMap<>();
}

private Map<String, Object> simpleDocument(String title) {
private Map<String, Object> simpleDocument(String title, String status) {
Map<String, Object> simpleDoc = new HashMap<>();
String uri = title.replace(" ", "_");
simpleDoc.put(Attributes.NO_EXTENSION_URI, uri);
simpleDoc.put(Attributes.URI, uri);
simpleDoc.put(Attributes.TITLE, title);
simpleDoc.put(Attributes.STATUS, status);
return simpleDoc;
}

}
}

0 comments on commit 4d70a98

Please sign in to comment.