Start of the big epic refactor

The end purpose is to enable removal of entire threads. Previous attempts have failed, all because of something JPA/Hibernate related such as not-null constraint, transient/detached entities, or something else.

 The approach is to get rid of @Entitys throughout the system and use data transfer objects (DTOs) and to make the thread more of a central concept rather than an empty container with an "initial" post. This should allow a more dedicated "delete thread" method that can take care of all the issues instead of "is this the last post then do extra steps" which is causing the problems.

 Changing to DTOs will also align better with the technical future that the current developers want and have decided on "Never return @Entity classes from services" (https://gitea.dsv.su.se/DMC/scipro/wiki/Technical-future).
This commit is contained in:
Andreas Svanberg 2025-03-18 15:58:27 +01:00
parent 819d5c7935
commit 27204cba5e
18 changed files with 109 additions and 195 deletions

@ -18,4 +18,6 @@ public interface GroupForumService {
ForumPost createReply(GroupThread groupThread, User poster, String content, Set<Attachment> attachments);
List<ForumPost> getPosts(GroupThread groupThread);
IndexedForumService getForumService(Group group);
}

@ -81,4 +81,9 @@ public class GroupForumServiceImpl implements GroupForumService {
public List<ForumPost> getPosts(final GroupThread groupThread) {
return basicForumService.getPosts(groupThread.getForumThread());
}
@Override
public IndexedForumService getForumService(Group group) {
return null;
}
}

@ -0,0 +1,12 @@
package se.su.dsv.scipro.forum;
import java.util.List;
import se.su.dsv.scipro.system.User;
public interface IndexedForumService {
List<ThreadOverview> getThreads();
boolean isThreadRead(User user, Long threadId);
void setThreadRead(User user, Long threadId, boolean read);
}

@ -28,4 +28,6 @@ public interface ProjectForumService {
boolean canDelete(ProjectThread projectThread, ForumPost forumPost);
void deletePost(ProjectThread projectThread, ForumPost forumPost);
IndexedForumService getForumService(Project project);
}

@ -139,4 +139,9 @@ public class ProjectForumServiceImpl implements ProjectForumService {
public ProjectThread findOne(long threadId) {
return projectThreadRepository.findOne(threadId);
}
@Override
public IndexedForumService getForumService(Project project) {
return null;
}
}

@ -0,0 +1,15 @@
package se.su.dsv.scipro.forum;
import java.time.Instant;
import se.su.dsv.scipro.forum.dataobjects.ForumPost;
import se.su.dsv.scipro.system.User;
public record ThreadOverview(
Long id,
boolean hasAttachments,
String subject,
User author,
Instant createdAt,
int numberOfReplies,
ForumPost latestPost
) {}

@ -1,9 +0,0 @@
package se.su.dsv.scipro.forum;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.io.IClusterable;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
public interface Discussable<A> extends IClusterable {
IModel<ForumThread> discussion(IModel<A> a);
}

@ -1,15 +0,0 @@
package se.su.dsv.scipro.forum.pages.threaded;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LambdaModel;
import se.su.dsv.scipro.forum.Discussable;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
import se.su.dsv.scipro.forum.dataobjects.ProjectThread;
public class ForumThreadDiscussable implements Discussable<ProjectThread> {
@Override
public IModel<ForumThread> discussion(final IModel<ProjectThread> a) {
return LambdaModel.of(a, ProjectThread::getForumThread, ProjectThread::setForumThread);
}
}

@ -11,6 +11,7 @@ import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightAuthorMyProjects;
import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightForum;
import se.su.dsv.scipro.forum.IndexedForumService;
import se.su.dsv.scipro.forum.ProjectForumService;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
import se.su.dsv.scipro.forum.dataobjects.ProjectThread;
@ -34,29 +35,19 @@ public class ProjectThreadedForumPage
public ProjectThreadedForumPage(final PageParameters pp) {
super(pp);
add(new BookmarkablePageLink<Void>(CREATE_THREAD_LINK, ProjectCreateForumThreadPage.class, pp));
IModel<IndexedForumService> forumService = projectModel.map(projectForumService::getForumService);
add(new FeedbackPanel(FEEDBACK));
add(
new ThreadsOverviewPanel<>(FORUM, getThreads(), new ForumThreadDiscussable(), (id, thread) -> {
new ThreadsOverviewPanel(FORUM, forumService, (id, thread) -> {
PageParameters parameters = new PageParameters(pp).set(
PageParameterKeys.MAP.get(ForumThread.class),
thread.getObject().getId()
thread.getObject().id()
);
return new BookmarkablePageLink<>(id, ProjectViewForumThreadPage.class, parameters);
})
);
}
private IModel<List<ProjectThread>> getThreads() {
return new LoadableDetachableModel<>() {
@Override
protected List<ProjectThread> load() {
List<ProjectThread> threads = projectForumService.getThreads(projectModel.getObject());
threads.sort(Collections.reverseOrder(Comparator.comparing(o -> o.getForumThread().getLastModified())));
return threads;
}
};
}
static final String CREATE_THREAD_LINK = "createThread";
static final String FEEDBACK = "feedback";
static final String FORUM = "forum";

@ -3,19 +3,15 @@ package se.su.dsv.scipro.forum.pages.threaded;
import static se.su.dsv.scipro.security.auth.roles.Roles.SUPERVISOR;
import jakarta.inject.Inject;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightForum;
import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightSupervisorMyProjects;
import se.su.dsv.scipro.forum.IndexedForumService;
import se.su.dsv.scipro.forum.ProjectForumService;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
import se.su.dsv.scipro.forum.dataobjects.ProjectThread;
import se.su.dsv.scipro.forum.panels.threaded.ThreadsOverviewPanel;
import se.su.dsv.scipro.security.auth.Authorization;
import se.su.dsv.scipro.security.auth.ProjectModuleComponent;
@ -36,28 +32,18 @@ public class SupervisorThreadedForumPage
super(pp);
add(new BookmarkablePageLink<Void>(CREATE_THREAD_LINK, SupervisorCreateForumThreadPage.class, pp));
add(new FeedbackPanel(FEEDBACK));
IModel<IndexedForumService> forumService = projectModel.map(projectForumService::getForumService);
add(
new ThreadsOverviewPanel<>(FORUM, getThreads(), new ForumThreadDiscussable(), (id, thread) -> {
new ThreadsOverviewPanel(FORUM, forumService, (id, thread) -> {
PageParameters parameters = new PageParameters(pp).set(
PageParameterKeys.MAP.get(ForumThread.class),
thread.getObject().getId()
thread.getObject().id()
);
return new BookmarkablePageLink<>(id, SupervisorViewForumThreadPage.class, parameters);
})
);
}
private IModel<List<ProjectThread>> getThreads() {
return new LoadableDetachableModel<>() {
@Override
protected List<ProjectThread> load() {
List<ProjectThread> threads = projectForumService.getThreads(projectModel.getObject());
threads.sort(Collections.reverseOrder(Comparator.comparing(o -> o.getForumThread().getLastModified())));
return threads;
}
};
}
static final String CREATE_THREAD_LINK = "createThread";
static final String FEEDBACK = "feedback";
static final String FORUM = "forum";

@ -1,10 +1,9 @@
package se.su.dsv.scipro.forum.panels.threaded;
import jakarta.inject.Inject;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.model.IModel;
import se.su.dsv.scipro.forum.BasicForumService;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
import se.su.dsv.scipro.forum.IndexedForumService;
import se.su.dsv.scipro.forum.ThreadOverview;
import se.su.dsv.scipro.forum.panels.AbstractReadStatePanel;
import se.su.dsv.scipro.session.SciProSession;
@ -14,24 +13,23 @@ import se.su.dsv.scipro.session.SciProSession;
*/
public class ThreadReadStatePanel extends AbstractReadStatePanel {
@Inject
private BasicForumService basicForumService;
private final IModel<IndexedForumService> forumService;
private final IModel<ThreadOverview> model;
private final IModel<ForumThread> model;
public ThreadReadStatePanel(String id, IModel<ForumThread> model) {
public ThreadReadStatePanel(String id, IModel<IndexedForumService> forumService, IModel<ThreadOverview> model) {
super(id);
this.forumService = forumService;
this.model = model;
}
@Override
protected boolean isRead() {
return basicForumService.isThreadRead(SciProSession.get().getUser(), model.getObject());
return forumService.getObject().isThreadRead(SciProSession.get().getUser(), model.getObject().id());
}
@Override
protected void onFlagClick(final AjaxRequestTarget target) {
boolean read = isRead();
basicForumService.setThreadRead(SciProSession.get().getUser(), model.getObject(), !read);
forumService.getObject().setThreadRead(SciProSession.get().getUser(), model.getObject().id(), !read);
}
}

@ -1,8 +1,6 @@
package se.su.dsv.scipro.forum.panels.threaded;
import jakarta.inject.Inject;
import java.io.Serializable;
import java.util.List;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
@ -11,46 +9,39 @@ import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LambdaModel;
import org.apache.wicket.model.LoadableDetachableModel;
import se.su.dsv.scipro.components.DateLabel;
import se.su.dsv.scipro.data.enums.DateStyle;
import se.su.dsv.scipro.forum.BasicForumService;
import se.su.dsv.scipro.forum.Discussable;
import se.su.dsv.scipro.forum.IndexedForumService;
import se.su.dsv.scipro.forum.ThreadOverview;
import se.su.dsv.scipro.forum.dataobjects.ForumPost;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
import se.su.dsv.scipro.profile.UserLinkPanel;
import se.su.dsv.scipro.system.User;
public class ThreadsOverviewPanel<A> extends Panel {
@Inject
private BasicForumService basicForumService;
public class ThreadsOverviewPanel extends Panel {
public ThreadsOverviewPanel(
final String id,
final IModel<List<A>> model,
final Discussable<A> discussable,
final ThreadLinkSupplier<A> threadLinkSupplier
final IModel<IndexedForumService> forumService,
final ThreadLinkSupplier threadLinkSupplier
) {
super(id, model);
super(id, forumService);
add(
new ListView<>("threads", model) {
new ListView<>("threads", forumService.map(IndexedForumService::getThreads)) {
@Override
protected void populateItem(final ListItem<A> item) {
final IModel<ForumThread> discussion = discussable.discussion(item.getModel());
item.add(new ThreadReadStatePanel("readState", discussion));
protected void populateItem(final ListItem<ThreadOverview> item) {
item.add(new ThreadReadStatePanel("readState", forumService, item.getModel()));
item.add(
new WebMarkupContainer("attachmentIcon") {
@Override
protected void onConfigure() {
super.onConfigure();
setVisibilityAllowed(basicForumService.hasAttachments(discussion.getObject()));
setVisibilityAllowed(item.getModelObject().hasAttachments());
}
}
);
item.add(new ThreadTitleColumn<>("threadTitle", discussion, item.getModel(), threadLinkSupplier));
item.add(new Label("replies", discussion.map(ForumThread::getPostCount)));
item.add(new LastPostColumn("lastPost", discussion));
item.add(new ThreadTitleColumn<>("threadTitle", item.getModel(), threadLinkSupplier));
item.add(new Label("replies", item.getModel().map(ThreadOverview::numberOfReplies)));
item.add(new LastPostColumn("lastPost", item.getModel().map(ThreadOverview::latestPost)));
}
}
);
@ -60,34 +51,26 @@ public class ThreadsOverviewPanel<A> extends Panel {
public ThreadTitleColumn(
final String id,
final IModel<ForumThread> thread,
final IModel<A> model,
final ThreadLinkSupplier<A> threadLinkSupplier
final IModel<ThreadOverview> model,
final ThreadLinkSupplier threadLinkSupplier
) {
super(id);
final BookmarkablePageLink<Void> threadLink = threadLinkSupplier.newThreadLink("threadLink", model);
threadLink.setBody(LambdaModel.of(thread, ForumThread::getSubject, ForumThread::setSubject));
threadLink.setBody(model.map(ThreadOverview::subject));
add(threadLink);
add(new Label("createdBy", thread.map(ForumThread::getCreatedBy).map(User::getFullName).orElse("SciPro")));
add(
new DateLabel(
"dateCreated",
LambdaModel.of(thread, ForumThread::getDateCreated, ForumThread::setDateCreated),
DateStyle.DATETIME
)
);
add(new Label("createdBy", model.map(ThreadOverview::author).map(User::getFullName).orElse("SciPro")));
add(new Label("dateCreated", model.map(ThreadOverview::createdAt)));
}
}
public interface ThreadLinkSupplier<A> extends Serializable {
BookmarkablePageLink<Void> newThreadLink(String id, IModel<A> thread);
public interface ThreadLinkSupplier extends Serializable {
BookmarkablePageLink<Void> newThreadLink(String id, IModel<ThreadOverview> thread);
}
private class LastPostColumn extends WebMarkupContainer {
public LastPostColumn(String id, final IModel<ForumThread> model) {
public LastPostColumn(String id, final IModel<ForumPost> postModel) {
super(id);
IModel<ForumPost> postModel = getLastPost(model);
add(
new UserLinkPanel("postedBy", LambdaModel.of(postModel, ForumPost::getPostedBy, ForumPost::setPostedBy))
);
@ -108,14 +91,5 @@ public class ThreadsOverviewPanel<A> extends Panel {
)
);
}
private IModel<ForumPost> getLastPost(final IModel<ForumThread> model) {
return new LoadableDetachableModel<>() {
@Override
protected ForumPost load() {
return basicForumService.getLastPost(model.getObject());
}
};
}
}
}

@ -1,18 +1,14 @@
package se.su.dsv.scipro.group;
import jakarta.inject.Inject;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightAuthorMyGroups;
import se.su.dsv.scipro.forum.GroupForumService;
import se.su.dsv.scipro.forum.IndexedForumService;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
import se.su.dsv.scipro.forum.dataobjects.GroupThread;
import se.su.dsv.scipro.forum.panels.threaded.ThreadsOverviewPanel;
import se.su.dsv.scipro.util.PageParameterKeys;
@ -25,25 +21,15 @@ public class AuthorGroupPage extends AbstractAuthorGroupPage implements MenuHigh
super(pp);
add(new FeedbackPanel("feedback"));
add(new BookmarkablePageLink<Void>("createThread", CreateThreadPage.class, pp));
IModel<IndexedForumService> forumService = getGroup().map(groupForumService::getForumService);
add(
new ThreadsOverviewPanel<>("threads", getThreads(), new GroupThreadDiscussable(), (id, thread) -> {
new ThreadsOverviewPanel("threads", forumService, (id, thread) -> {
PageParameters parameters = new PageParameters(pp).set(
PageParameterKeys.MAP.get(ForumThread.class),
thread.getObject().getId()
thread.getObject().id()
);
return new BookmarkablePageLink<>(id, ViewThreadPage.class, parameters);
})
);
}
private IModel<List<GroupThread>> getThreads() {
return new LoadableDetachableModel<>() {
@Override
protected List<GroupThread> load() {
List<GroupThread> threads = groupForumService.getThreads(getGroup().getObject());
threads.sort(Collections.reverseOrder(Comparator.comparing(o -> o.getForumThread().getLastModified())));
return threads;
}
};
}
}

@ -1,14 +0,0 @@
package se.su.dsv.scipro.group;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LambdaModel;
import se.su.dsv.scipro.forum.Discussable;
import se.su.dsv.scipro.forum.dataobjects.*;
public class GroupThreadDiscussable implements Discussable<GroupThread> {
@Override
public IModel<ForumThread> discussion(final IModel<GroupThread> a) {
return LambdaModel.of(a, GroupThread::getForumThread, GroupThread::setForumThread);
}
}

@ -1,20 +1,15 @@
package se.su.dsv.scipro.supervisor.pages;
import jakarta.inject.Inject;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import se.su.dsv.scipro.components.menuhighlighting.MenuHighlightSupervisorMyGroups;
import se.su.dsv.scipro.forum.GroupForumService;
import se.su.dsv.scipro.forum.IndexedForumService;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
import se.su.dsv.scipro.forum.dataobjects.GroupThread;
import se.su.dsv.scipro.forum.panels.threaded.ThreadsOverviewPanel;
import se.su.dsv.scipro.group.GroupThreadDiscussable;
import se.su.dsv.scipro.util.PageParameterKeys;
public class SupervisorGroupPage extends AbstractSupervisorGroupPage implements MenuHighlightSupervisorMyGroups {
@ -26,25 +21,15 @@ public class SupervisorGroupPage extends AbstractSupervisorGroupPage implements
super(pp);
add(new FeedbackPanel("feedback"));
add(new BookmarkablePageLink<Void>("createThread", SupervisorGroupCreateThreadPage.class, pp));
IModel<IndexedForumService> forumService = groupModel.map(groupForumService::getForumService);
add(
new ThreadsOverviewPanel<>("threads", getThreads(), new GroupThreadDiscussable(), (id, thread) -> {
new ThreadsOverviewPanel("threads", forumService, (id, thread) -> {
PageParameters parameters = new PageParameters(pp).set(
PageParameterKeys.MAP.get(ForumThread.class),
thread.getObject().getId()
thread.getObject().id()
);
return new BookmarkablePageLink<>(id, SupervisorViewGroupThreadPage.class, parameters);
})
);
}
private IModel<List<GroupThread>> getThreads() {
return new LoadableDetachableModel<>() {
@Override
protected List<GroupThread> load() {
List<GroupThread> threads = groupForumService.getThreads(groupModel.getObject());
threads.sort(Collections.reverseOrder(Comparator.comparing(o -> o.getForumThread().getLastModified())));
return threads;
}
};
}
}

@ -50,6 +50,7 @@ import se.su.dsv.scipro.finalthesis.FinalThesisService;
import se.su.dsv.scipro.finalthesis.PublishingConsentService;
import se.su.dsv.scipro.forum.BasicForumService;
import se.su.dsv.scipro.forum.GroupForumService;
import se.su.dsv.scipro.forum.IndexedForumService;
import se.su.dsv.scipro.forum.ProjectForumService;
import se.su.dsv.scipro.gdpr.Reporter;
import se.su.dsv.scipro.generalsystemsettings.GeneralSystemSettings;
@ -219,6 +220,9 @@ public abstract class SciProTest {
@Mock
protected GroupForumService groupForumService;
@Mock
protected IndexedForumService indexedForumService;
@Mock
protected GeneralSystemSettingsService generalSystemSettingsService;

@ -4,22 +4,22 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.*;
import org.apache.wicket.model.Model;
import java.time.Instant;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import se.su.dsv.scipro.SciProTest;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
import se.su.dsv.scipro.forum.ThreadOverview;
import se.su.dsv.scipro.forum.dataobjects.ForumPost;
import se.su.dsv.scipro.forum.panels.AbstractReadStatePanel;
import se.su.dsv.scipro.system.User;
import se.su.dsv.scipro.test.ForumBuilder;
import se.su.dsv.scipro.test.UserBuilder;
public class ThreadReadStatePanelTest extends SciProTest {
ThreadReadStatePanel panel;
User user;
ForumThread forumThread;
ThreadOverview forumThread;
@BeforeEach
public void setUp() throws Exception {
@ -27,8 +27,7 @@ public class ThreadReadStatePanelTest extends SciProTest {
setLoggedIn(true);
setLoggedInAs(user);
forumThread = new ForumBuilder().createThread().getForumThread();
forumThread.addPost(new ForumBuilder().createPost(forumThread));
forumThread = new ThreadOverview(1L, false, "Subject", user, Instant.now(), 0, new ForumPost());
}
@Test
@ -40,22 +39,24 @@ public class ThreadReadStatePanelTest extends SciProTest {
@Test
public void testTogglingCallsCorrectService() {
// given
when(basicForumService.isThreadRead(eq(user), eq(forumThread))).thenReturn(true);
when(indexedForumService.isThreadRead(eq(user), eq(forumThread.id()))).thenReturn(true);
// when
startPanel();
tester.executeAjaxEvent(path(panel.getId(), AbstractReadStatePanel.TOGGLE), "click");
verify(basicForumService, times(1)).setThreadRead(eq(user), eq(forumThread), eq(false));
verify(indexedForumService, times(1)).setThreadRead(eq(user), eq(forumThread.id()), eq(false));
// then
ArgumentCaptor<Boolean> captor = ArgumentCaptor.forClass(Boolean.class);
verify(basicForumService).setThreadRead(eq(user), eq(forumThread), captor.capture());
verify(indexedForumService).setThreadRead(eq(user), eq(forumThread.id()), captor.capture());
assertEquals(false, captor.getValue(), "Does not toggle to the correct state");
}
private void startPanel() {
panel = tester.startComponentInPage(new ThreadReadStatePanel("panel", Model.of(forumThread)));
panel = tester.startComponentInPage(
new ThreadReadStatePanel("panel", () -> indexedForumService, () -> forumThread)
);
}
}

@ -1,33 +1,28 @@
package se.su.dsv.scipro.forum.panels.threaded;
import java.util.Arrays;
import java.time.Instant;
import java.util.List;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.pages.InternalErrorPage;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import se.su.dsv.scipro.SciProTest;
import se.su.dsv.scipro.forum.Discussable;
import se.su.dsv.scipro.forum.ThreadOverview;
import se.su.dsv.scipro.forum.dataobjects.ForumPost;
import se.su.dsv.scipro.forum.dataobjects.ForumThread;
import se.su.dsv.scipro.system.User;
@ExtendWith(MockitoExtension.class)
public class ThreadsOverviewPanelTest extends SciProTest {
private List<ForumThread> threads;
private ForumPost post;
@BeforeEach
public void setUp() throws Exception {
ForumThread forumThread = createThread();
threads = Arrays.asList(forumThread);
Mockito.when(basicForumService.getLastPost(forumThread)).thenReturn(post);
ThreadOverview forumThread = createThread();
Mockito.when(indexedForumService.getThreads()).thenReturn(List.of(forumThread));
}
@Test
@ -36,17 +31,10 @@ public class ThreadsOverviewPanelTest extends SciProTest {
}
private void startPanel() {
IModel<List<ForumThread>> listIModel = Model.ofList(threads);
tester.startComponentInPage(
new ThreadsOverviewPanel<>(
new ThreadsOverviewPanel(
"id",
listIModel,
new Discussable<ForumThread>() {
@Override
public IModel<ForumThread> discussion(final IModel<ForumThread> a) {
return a;
}
},
() -> indexedForumService,
(id, thread) -> {
final BookmarkablePageLink<Void> link = new BookmarkablePageLink<>(id, InternalErrorPage.class);
return link;
@ -55,12 +43,10 @@ public class ThreadsOverviewPanelTest extends SciProTest {
);
}
private ForumThread createThread() {
private ThreadOverview createThread() {
User bob = User.builder().firstName("Bob").lastName("the Builder").emailAddress("bob@building.com").build();
post = new ForumPost();
post.setPostedBy(bob);
ForumThread groupForumThread = new ForumThread();
groupForumThread.addPost(post);
return groupForumThread;
return new ThreadOverview(1L, true, "Subject", bob, Instant.now(), 1, post);
}
}