Skip to content

Commit

Permalink
Unittests für NodeSlug-Service
Browse files Browse the repository at this point in the history
  • Loading branch information
commel committed Nov 3, 2023
1 parent c31a892 commit a98af28
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.holarse.backend.db.repositories;

import de.holarse.backend.db.NodeSlug;
import de.holarse.backend.types.NodeType;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
Expand All @@ -13,4 +14,6 @@ public interface NodeSlugRepository extends JpaRepository<NodeSlug, Integer> {
@Query("FROM NodeSlug ns WHERE ns.nodeId = :nodeId ORDER BY ns.id DESC LIMIT 1")
Optional<NodeSlug> findByNodeId(@Param("nodeId") final int nodeId);

boolean existsByNameAndSlugContext(final String name, final NodeType slugContext);

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import de.holarse.backend.types.NodeType;
import de.holarse.web.controller.commands.ArticleForm;
import de.holarse.web.defines.WebDefines;
import de.holarse.web.services.SlugService;
import jakarta.validation.Valid;
import java.security.Principal;
import org.slf4j.Logger;
Expand Down Expand Up @@ -42,6 +43,9 @@ public class WorkspaceController {
@Autowired
private NodeStatusRepository nodeStatusRepository;

@Autowired
private SlugService slugService;

/**
* Übersicht über den eigenen Workspace
* @param mv
Expand Down Expand Up @@ -107,10 +111,7 @@ public ModelAndView saveArticle(@Valid @ModelAttribute("form") final ArticleForm
nodeStatus.setPublished(form.isPublished());

// Slug anlegen
final NodeSlug nodeSlug = new NodeSlug();
nodeSlug.setNodeId(nodeId);
nodeSlug.setName(articleRevision.getTitle1().toLowerCase());
nodeSlug.setSlugContext(NodeType.article);
final NodeSlug nodeSlug = slugService.slugify(articleRevision);

// Artikel anlegen
final Article article = new Article();
Expand Down
54 changes: 45 additions & 9 deletions src/main/java/de/holarse/web/services/SlugService.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package de.holarse.web.services;

import de.holarse.backend.db.Article;
import de.holarse.backend.db.ArticleRevision;
import de.holarse.backend.db.NodeSlug;
import de.holarse.backend.db.User;
import de.holarse.backend.db.UserSlug;
import de.holarse.backend.db.repositories.NodeSlugRepository;
import de.holarse.backend.db.repositories.UserRepository;
import de.holarse.backend.db.repositories.UserSlugRepository;
import de.holarse.backend.types.NodeType;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.HashSet;
Expand All @@ -21,8 +26,40 @@ public class SlugService {

private final static transient Logger log = LoggerFactory.getLogger(SlugService.class);

private final static String SLUGWORD_DELIMITER = "_";
private final static int SLUGWORD_MAXSIZE = 95;
//private final String[] removeWords = new String[]{"a","an","as","at","before","but","by","for","from","is","in","into","like","of","off","on","onto","per","since","than","the","this","that","to","up","via","with"};


@Autowired
private UserSlugRepository userSlugRepository;
NodeSlugRepository nodeSlugRepository;

@Autowired
UserSlugRepository userSlugRepository;

public NodeSlug slugify(final ArticleRevision articleRevision) {
final String title = articleRevision.getTitle1();
final String slugifiedTitle = slugify(title);
final List<String> possibleSlugs = new ArrayList<>(101);
possibleSlugs.add(slugifiedTitle);
possibleSlugs.addAll(IntStream.rangeClosed(1, 100).boxed().map(n -> String.format("%s-%d", slugifiedTitle, n)).toList());

for (final String possibleSlug : possibleSlugs) {
final boolean result = nodeSlugRepository.existsByNameAndSlugContext(possibleSlug, NodeType.article);
log.debug("User {} testing slug {} exists: {}", title, possibleSlug, result);
if (!result) {
final NodeSlug nodeSlug = new NodeSlug();
nodeSlug.setName(possibleSlug);
nodeSlug.setNodeId(articleRevision.getNodeId());
nodeSlug.setSlugContext(NodeType.article);

return nodeSlug;
}
log.debug("slug {} exists", title, possibleSlug);
}

throw new IllegalStateException("ran out of article revision slug titles");
}

/**
* Hinterlegt ein Slug für diesen Benutzer
Expand All @@ -49,13 +86,10 @@ public UserSlug slugify(final User user) {
}
}

throw new IllegalStateException("no slug for user could be found");
throw new IllegalStateException("ran out of user slug titles");
}

private final static String SLUGWORD_DELIMITER = "_";

//private final String[] removeWords = new String[]{"a","an","as","at","before","but","by","for","from","is","in","into","like","of","off","on","onto","per","since","than","the","this","that","to","up","via","with"};


public String transliterate(final String title) {
return title.toLowerCase()
.replaceAll(" of ", " ")
Expand All @@ -72,8 +106,9 @@ public String transliterate(final String title) {
}

public String slugify(final String title) {
if (title == null)
if (title == null) {
return "";
}

// Ungewollte Wörter raus
// Ungewollte Zeichen raus
Expand All @@ -98,12 +133,13 @@ public String slugify(final String title) {
final String[] words = r2.split(" ");

// Wörter zusammenfügen, solange keine 95 Zeichen überschritten sind
final StringBuffer buffer = new StringBuffer(95);
final StringBuffer buffer = new StringBuffer(SLUGWORD_MAXSIZE);
for(final String word : words) {
final String w = word.trim();
//System.out.println("WORD='" + w + "', buffer: '" + buffer.toString() + "', len: " + buffer.length());
if (StringUtils.isBlank(w))
if (StringUtils.isBlank(w)) {
continue;
}

// bisheriger slug + "_" + neues wort
if ((buffer.length() + w.length() + 1) > 95) {
Expand Down
68 changes: 65 additions & 3 deletions src/test/java/de/holarse/web/services/SlugServiceTest.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,88 @@
package de.holarse.web.services;

import static org.junit.jupiter.api.Assertions.assertEquals;
import de.holarse.backend.db.ApiUser;
import de.holarse.backend.db.ArticleRevision;
import de.holarse.backend.db.NodeSlug;
import de.holarse.backend.db.repositories.ApiUserRepository;
import de.holarse.backend.db.repositories.NodeSlugRepository;
import de.holarse.backend.types.NodeType;
import java.util.Arrays;
import java.util.stream.IntStream;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
import org.mockito.MockitoAnnotations;

public class SlugServiceTest {

private SlugService slugService;

@Mock
NodeSlugRepository nodeSlugRepositoryMock;

@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
slugService = new SlugService();
slugService.nodeSlugRepository = nodeSlugRepositoryMock;
}

@Test
public void testSlugifyArticleHappy() {
final ArticleRevision ar = new ArticleRevision();
ar.setTitle1("Hallo Welt");

when(nodeSlugRepositoryMock.existsByNameAndSlugContext(anyString(), any(NodeType.class))).thenReturn(Boolean.FALSE); // No slug of this name exists

final NodeSlug expected = new NodeSlug();
expected.setName("hallo_welt");
expected.setSlugContext(NodeType.article);

final NodeSlug result = slugService.slugify(ar);

assertEquals(expected.getName(), result.getName());
}

@Test
public void testSlugifyArticleFirstThreeBlocked() {
final ArticleRevision ar = new ArticleRevision();
ar.setTitle1("Hallo Welt");

when(nodeSlugRepositoryMock.existsByNameAndSlugContext(anyString(), any(NodeType.class))).thenReturn(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, Boolean.FALSE);


final NodeSlug expected = new NodeSlug();
expected.setName("hallo_welt-3");
expected.setSlugContext(NodeType.article);

final NodeSlug result = slugService.slugify(ar);

//verify(nodeSlugRepositoryMock, times(3)).existsByNameAndSlugContext("hallo_welt", NodeType.article);

assertEquals(expected.getName(), result.getName());
}

@Test
public void testSlugifyArticleAlllocked() {
final ArticleRevision ar = new ArticleRevision();
ar.setTitle1("Hallo Welt");

when(nodeSlugRepositoryMock.existsByNameAndSlugContext(anyString(), any(NodeType.class))).thenReturn(Boolean.TRUE);

assertThrows(IllegalStateException.class, () -> slugService.slugify(ar));
}

@Test
public void testSlugifyNull() {
String input = null;
assertEquals("", slugService.slugify(input), "should not fail");
}

@Test
@Test
public void testSlugifyAscii() {
assertEquals("abcdefg", slugService.slugify("abcdefg"));
}
Expand Down

0 comments on commit a98af28

Please sign in to comment.