mirror of https://github.com/halo-dev/halo
Merge branch 'main' into refactor/setting-config-update
commit
e2e1d1da4e
|
@ -6,6 +6,7 @@ import static run.halo.app.infra.utils.FileUtils.checkDirectoryTraversal;
|
||||||
import static run.halo.app.infra.utils.FileUtils.deleteFileSilently;
|
import static run.halo.app.infra.utils.FileUtils.deleteFileSilently;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.FileAlreadyExistsException;
|
import java.nio.file.FileAlreadyExistsException;
|
||||||
|
@ -25,6 +26,7 @@ import org.springframework.core.io.buffer.DataBuffer;
|
||||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.codec.multipart.FilePart;
|
import org.springframework.http.codec.multipart.FilePart;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
@ -156,20 +158,15 @@ class LocalAttachmentUploadHandler implements AttachmentHandler {
|
||||||
var typeValidator = file.content()
|
var typeValidator = file.content()
|
||||||
.next()
|
.next()
|
||||||
.handle((dataBuffer, sink) -> {
|
.handle((dataBuffer, sink) -> {
|
||||||
var mimeType = "Unknown";
|
var mimeType = detectMimeType(dataBuffer.asInputStream());
|
||||||
try {
|
|
||||||
mimeType = FileTypeDetectUtils.detectMimeType(dataBuffer.asInputStream());
|
|
||||||
var isAllow = setting.getAllowedFileTypes()
|
var isAllow = setting.getAllowedFileTypes()
|
||||||
.stream()
|
.stream()
|
||||||
.map(FileCategoryMatcher::of)
|
.map(FileCategoryMatcher::of)
|
||||||
.anyMatch(matcher -> matcher.match(file.filename()));
|
.anyMatch(matcher -> matcher.match(mimeType));
|
||||||
if (isAllow) {
|
if (isAllow) {
|
||||||
sink.next(dataBuffer);
|
sink.next(dataBuffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
|
||||||
log.warn("Failed to detect file type", e);
|
|
||||||
}
|
|
||||||
sink.error(new FileTypeNotAllowedException("File type is not allowed",
|
sink.error(new FileTypeNotAllowedException("File type is not allowed",
|
||||||
"problemDetail.attachment.upload.fileTypeNotSupported",
|
"problemDetail.attachment.upload.fileTypeNotSupported",
|
||||||
new Object[] {mimeType})
|
new Object[] {mimeType})
|
||||||
|
@ -180,6 +177,16 @@ class LocalAttachmentUploadHandler implements AttachmentHandler {
|
||||||
return Mono.when(validations);
|
return Mono.when(validations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private String detectMimeType(InputStream inputStream) {
|
||||||
|
try {
|
||||||
|
return FileTypeDetectUtils.detectMimeType(inputStream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("Failed to detect file type", e);
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Attachment> delete(DeleteContext deleteContext) {
|
public Mono<Attachment> delete(DeleteContext deleteContext) {
|
||||||
return Mono.just(deleteContext)
|
return Mono.just(deleteContext)
|
||||||
|
|
|
@ -12,6 +12,7 @@ import org.springframework.expression.MethodExecutor;
|
||||||
import org.springframework.expression.MethodResolver;
|
import org.springframework.expression.MethodResolver;
|
||||||
import org.springframework.expression.PropertyAccessor;
|
import org.springframework.expression.PropertyAccessor;
|
||||||
import org.springframework.expression.TypedValue;
|
import org.springframework.expression.TypedValue;
|
||||||
|
import org.springframework.expression.spel.CompilablePropertyAccessor;
|
||||||
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||||
import org.springframework.integration.json.JsonPropertyAccessor;
|
import org.springframework.integration.json.JsonPropertyAccessor;
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
|
@ -122,7 +123,7 @@ public class EvaluationContextEnhancer extends AbstractTemplateBoundariesProcess
|
||||||
public PropertyAccessor createOptimalAccessor(EvaluationContext context, Object target,
|
public PropertyAccessor createOptimalAccessor(EvaluationContext context, Object target,
|
||||||
String name) {
|
String name) {
|
||||||
var optimalAccessor = delegate.createOptimalAccessor(context, target, name);
|
var optimalAccessor = delegate.createOptimalAccessor(context, target, name);
|
||||||
if (optimalAccessor instanceof OptimalPropertyAccessor optimalPropertyAccessor) {
|
if (optimalAccessor instanceof CompilablePropertyAccessor optimalPropertyAccessor) {
|
||||||
if (ReactiveUtils.isReactiveType(optimalPropertyAccessor.getPropertyType())) {
|
if (ReactiveUtils.isReactiveType(optimalPropertyAccessor.getPropertyType())) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,10 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.security.test.context.support.WithMockUser;
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import run.halo.app.core.extension.Role;
|
import run.halo.app.core.extension.Role;
|
||||||
|
@ -47,7 +47,7 @@ class ExtensionConfigurationTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
SchemeManager schemeManager;
|
SchemeManager schemeManager;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
RoleService roleService;
|
RoleService roleService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|
|
@ -13,10 +13,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.context.TestConfiguration;
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
|
||||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import org.springframework.web.reactive.socket.WebSocketHandler;
|
import org.springframework.web.reactive.socket.WebSocketHandler;
|
||||||
import org.springframework.web.reactive.socket.WebSocketMessage;
|
import org.springframework.web.reactive.socket.WebSocketMessage;
|
||||||
|
@ -38,7 +38,7 @@ class WebFluxConfigTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
WebTestClient webClient;
|
WebTestClient webClient;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
RoleService roleService;
|
RoleService roleService;
|
||||||
|
|
||||||
@LocalServerPort
|
@LocalServerPort
|
||||||
|
|
|
@ -12,8 +12,8 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.test.StepVerifier;
|
import reactor.test.StepVerifier;
|
||||||
|
@ -46,7 +46,7 @@ class CategoryPostCountUpdaterTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
private SchemeManager schemeManager;
|
private SchemeManager schemeManager;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
private ExtensionClient client;
|
private ExtensionClient client;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -12,9 +12,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.security.test.context.support.WithMockUser;
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import run.halo.app.core.extension.Role;
|
import run.halo.app.core.extension.Role;
|
||||||
|
@ -39,7 +39,7 @@ public class PostIntegrationTests {
|
||||||
@Autowired
|
@Autowired
|
||||||
private WebTestClient webTestClient;
|
private WebTestClient webTestClient;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
RoleService roleService;
|
RoleService roleService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|
|
@ -14,8 +14,8 @@ import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.test.StepVerifier;
|
import reactor.test.StepVerifier;
|
||||||
|
@ -48,7 +48,7 @@ class CommentServiceImplIntegrationTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
private SchemeManager schemeManager;
|
private SchemeManager schemeManager;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
private ReactiveExtensionClient reactiveClient;
|
private ReactiveExtensionClient reactiveClient;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -57,7 +57,7 @@ class CommentServiceImplIntegrationTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IndexerFactory indexerFactory;
|
private IndexerFactory indexerFactory;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
private CommentServiceImpl commentService;
|
private CommentServiceImpl commentService;
|
||||||
|
|
||||||
Mono<Extension> deleteImmediately(Extension extension) {
|
Mono<Extension> deleteImmediately(Extension extension) {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package run.halo.app.content.comment;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.lenient;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
@ -12,7 +11,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
@ -61,53 +59,25 @@ import run.halo.app.security.authorization.AuthorityUtils;
|
||||||
class CommentServiceImplTest {
|
class CommentServiceImplTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private SystemConfigurableEnvironmentFetcher environmentFetcher;
|
SystemConfigurableEnvironmentFetcher environmentFetcher;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ReactiveExtensionClient client;
|
ReactiveExtensionClient client;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private UserService userService;
|
UserService userService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private RoleService roleService;
|
RoleService roleService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ExtensionGetter extensionGetter;
|
ExtensionGetter extensionGetter;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private CommentServiceImpl commentService;
|
CommentServiceImpl commentService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private CounterService counterService;
|
CounterService counterService;
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
SystemSetting.Comment commentSetting = getCommentSetting();
|
|
||||||
lenient().when(environmentFetcher.fetchComment()).thenReturn(Mono.just(commentSetting));
|
|
||||||
|
|
||||||
ListResult<Comment> comments = new ListResult<>(1, 10, 3, comments());
|
|
||||||
when(client.listBy(eq(Comment.class), any(ListOptions.class), any(PageRequest.class)))
|
|
||||||
.thenReturn(Mono.just(comments));
|
|
||||||
|
|
||||||
when(userService.getUserOrGhost(eq("A-owner")))
|
|
||||||
.thenReturn(Mono.just(createUser("A-owner")));
|
|
||||||
when(userService.getUserOrGhost(eq("B-owner")))
|
|
||||||
.thenReturn(Mono.just(createUser("B-owner")));
|
|
||||||
when(client.fetch(eq(User.class), eq("C-owner")))
|
|
||||||
.thenReturn(Mono.empty());
|
|
||||||
|
|
||||||
when(roleService.contains(Set.of("USER"),
|
|
||||||
Set.of(AuthorityUtils.COMMENT_MANAGEMENT_ROLE_NAME)))
|
|
||||||
.thenReturn(Mono.just(false));
|
|
||||||
|
|
||||||
PostCommentSubject postCommentSubject = Mockito.mock(PostCommentSubject.class);
|
|
||||||
when(extensionGetter.getExtensions(CommentSubject.class))
|
|
||||||
.thenReturn(Flux.just(postCommentSubject));
|
|
||||||
|
|
||||||
when(postCommentSubject.supports(any())).thenReturn(true);
|
|
||||||
when(postCommentSubject.get(eq("fake-post"))).thenReturn(Mono.just(post()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static User createUser(String name) {
|
private static User createUser(String name) {
|
||||||
User user = new User();
|
User user = new User();
|
||||||
|
@ -122,10 +92,21 @@ class CommentServiceImplTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void listComment() {
|
void listComment() {
|
||||||
|
var comments = new ListResult<Comment>(1, 10, 3, comments());
|
||||||
|
when(client.listBy(eq(Comment.class), any(ListOptions.class), any(PageRequest.class)))
|
||||||
|
.thenReturn(Mono.just(comments));
|
||||||
|
|
||||||
|
PostCommentSubject postCommentSubject = Mockito.mock(PostCommentSubject.class);
|
||||||
|
when(extensionGetter.getExtensions(CommentSubject.class))
|
||||||
|
.thenReturn(Flux.just(postCommentSubject));
|
||||||
|
|
||||||
|
when(postCommentSubject.supports(any())).thenReturn(true);
|
||||||
|
when(postCommentSubject.get(eq("fake-post"))).thenReturn(Mono.just(post()));
|
||||||
|
|
||||||
when(userService.getUserOrGhost(any()))
|
when(userService.getUserOrGhost(any()))
|
||||||
.thenReturn(Mono.just(ghostUser()));
|
.thenReturn(Mono.just(ghostUser()));
|
||||||
when(userService.getUserOrGhost("A-owner"))
|
// when(userService.getUserOrGhost("A-owner"))
|
||||||
.thenReturn(Mono.just(createUser("A-owner")));
|
// .thenReturn(Mono.just(createUser("A-owner")));
|
||||||
when(userService.getUserOrGhost("B-owner"))
|
when(userService.getUserOrGhost("B-owner"))
|
||||||
.thenReturn(Mono.just(createUser("B-owner")));
|
.thenReturn(Mono.just(createUser("B-owner")));
|
||||||
|
|
||||||
|
@ -170,6 +151,12 @@ class CommentServiceImplTest {
|
||||||
@Test
|
@Test
|
||||||
@WithMockUser(username = "B-owner")
|
@WithMockUser(username = "B-owner")
|
||||||
void create() throws JSONException {
|
void create() throws JSONException {
|
||||||
|
var commentSetting = getCommentSetting();
|
||||||
|
when(environmentFetcher.fetchComment()).thenReturn(Mono.just(commentSetting));
|
||||||
|
when(roleService.contains(Set.of("USER"),
|
||||||
|
Set.of(AuthorityUtils.COMMENT_MANAGEMENT_ROLE_NAME)))
|
||||||
|
.thenReturn(Mono.just(false));
|
||||||
|
|
||||||
CommentRequest commentRequest = new CommentRequest();
|
CommentRequest commentRequest = new CommentRequest();
|
||||||
commentRequest.setRaw("fake-raw");
|
commentRequest.setRaw("fake-raw");
|
||||||
commentRequest.setContent("fake-content");
|
commentRequest.setContent("fake-content");
|
||||||
|
|
|
@ -14,8 +14,8 @@ import org.junit.jupiter.api.Nested;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.test.StepVerifier;
|
import reactor.test.StepVerifier;
|
||||||
|
@ -56,7 +56,7 @@ class ReplyServiceImplIntegrationTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
private SchemeManager schemeManager;
|
private SchemeManager schemeManager;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
private ReactiveExtensionClient reactiveClient;
|
private ReactiveExtensionClient reactiveClient;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -65,7 +65,7 @@ class ReplyServiceImplIntegrationTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
private IndexerFactory indexerFactory;
|
private IndexerFactory indexerFactory;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
private ReplyServiceImpl replyService;
|
private ReplyServiceImpl replyService;
|
||||||
|
|
||||||
Mono<Extension> deleteImmediately(Extension extension) {
|
Mono<Extension> deleteImmediately(Extension extension) {
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
package run.halo.app.core.endpoint.console;
|
package run.halo.app.core.endpoint.console;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
|
||||||
import static org.mockito.Mockito.spy;
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf;
|
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
|
||||||
|
|
||||||
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
|
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
|
||||||
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
|
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
|
||||||
import io.github.resilience4j.reactor.ratelimiter.operator.RateLimiterOperator;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
@ -39,47 +35,49 @@ import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
@ExtendWith(SpringExtension.class)
|
@ExtendWith(SpringExtension.class)
|
||||||
@WithMockUser(username = "fake-user", password = "fake-password")
|
@WithMockUser(username = "fake-user", password = "fake-password")
|
||||||
class EmailVerificationCodeTest {
|
class EmailVerificationCodeTest {
|
||||||
|
|
||||||
WebTestClient webClient;
|
WebTestClient webClient;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
ReactiveExtensionClient client;
|
ReactiveExtensionClient client;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
EmailVerificationService emailVerificationService;
|
EmailVerificationService emailVerificationService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
UserService userService;
|
UserService userService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
RateLimiterRegistry rateLimiterRegistry;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
UserEndpoint endpoint;
|
UserEndpoint endpoint;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
var spyUserEndpoint = spy(endpoint);
|
webClient = WebTestClient.bindToRouterFunction(endpoint.endpoint())
|
||||||
|
.apply(springSecurity())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void sendEmailVerificationCode() {
|
||||||
var config = RateLimiterConfig.custom()
|
var config = RateLimiterConfig.custom()
|
||||||
.limitRefreshPeriod(Duration.ofSeconds(10))
|
.limitRefreshPeriod(Duration.ofSeconds(10))
|
||||||
.limitForPeriod(1)
|
.limitForPeriod(1)
|
||||||
.build();
|
.build();
|
||||||
var sendCodeRateLimiter = RateLimiterRegistry.of(config)
|
var sendCodeRateLimiter = RateLimiterRegistry.of(config)
|
||||||
.rateLimiter("send-email-verification-code-fake-user:hi@halo.run");
|
.rateLimiter("send-email-verification-code-fake-user:hi@halo.run");
|
||||||
doReturn(RateLimiterOperator.of(sendCodeRateLimiter)).when(spyUserEndpoint)
|
when(rateLimiterRegistry.rateLimiter(
|
||||||
.sendEmailVerificationCodeRateLimiter(eq("fake-user"), eq("hi@halo.run"));
|
"send-email-verification-code-fake-user:hi@halo.run",
|
||||||
|
"send-email-verification-code")
|
||||||
|
).thenReturn(sendCodeRateLimiter);
|
||||||
|
|
||||||
var verifyEmailRateLimiter = RateLimiterRegistry.of(config)
|
|
||||||
.rateLimiter("verify-email-fake-user");
|
|
||||||
doReturn(RateLimiterOperator.of(verifyEmailRateLimiter)).when(spyUserEndpoint)
|
|
||||||
.verificationEmailRateLimiter(eq("fake-user"));
|
|
||||||
|
|
||||||
webClient = WebTestClient.bindToRouterFunction(spyUserEndpoint.endpoint()).build()
|
|
||||||
.mutateWith(csrf());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void sendEmailVerificationCode() {
|
|
||||||
var user = new User();
|
var user = new User();
|
||||||
user.setMetadata(new Metadata());
|
user.setMetadata(new Metadata());
|
||||||
user.getMetadata().setName("fake-user");
|
user.getMetadata().setName("fake-user");
|
||||||
user.setSpec(new User.UserSpec());
|
user.setSpec(new User.UserSpec());
|
||||||
user.getSpec().setEmail("hi@halo.run");
|
user.getSpec().setEmail("hi@halo.run");
|
||||||
when(client.get(eq(User.class), eq("fake-user"))).thenReturn(Mono.just(user));
|
|
||||||
when(emailVerificationService.sendVerificationCode(anyString(), anyString()))
|
when(emailVerificationService.sendVerificationCode(anyString(), anyString()))
|
||||||
.thenReturn(Mono.empty());
|
.thenReturn(Mono.empty());
|
||||||
webClient.post()
|
webClient.post()
|
||||||
|
@ -100,6 +98,16 @@ class EmailVerificationCodeTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void verifyEmail() {
|
void verifyEmail() {
|
||||||
|
var config = RateLimiterConfig.custom()
|
||||||
|
.limitRefreshPeriod(Duration.ofSeconds(10))
|
||||||
|
.limitForPeriod(1)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
var verifyEmailRateLimiter = RateLimiterRegistry.of(config)
|
||||||
|
.rateLimiter("verify-email-fake-user");
|
||||||
|
when(rateLimiterRegistry.rateLimiter("verify-email-fake-user", "verify-email"))
|
||||||
|
.thenReturn(verifyEmailRateLimiter);
|
||||||
|
|
||||||
when(emailVerificationService.verify(anyString(), anyString()))
|
when(emailVerificationService.verify(anyString(), anyString()))
|
||||||
.thenReturn(Mono.empty());
|
.thenReturn(Mono.empty());
|
||||||
when(userService.confirmPassword(anyString(), anyString()))
|
when(userService.confirmPassword(anyString(), anyString()))
|
||||||
|
|
|
@ -14,9 +14,9 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.security.test.context.support.WithMockUser;
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
@ -37,7 +37,7 @@ public class UserEndpointIntegrationTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
ReactiveExtensionClient client;
|
ReactiveExtensionClient client;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
RoleService roleService;
|
RoleService roleService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|
|
@ -9,13 +9,13 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.pf4j.PluginWrapper;
|
import org.pf4j.PluginWrapper;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||||
import run.halo.app.search.SearchService;
|
import run.halo.app.search.SearchService;
|
||||||
|
|
||||||
@SpringBootTest
|
@SpringBootTest
|
||||||
class DefaultPluginApplicationContextFactoryTest {
|
class DefaultPluginApplicationContextFactoryTest {
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
SpringPluginManager pluginManager;
|
SpringPluginManager pluginManager;
|
||||||
|
|
||||||
DefaultPluginApplicationContextFactory factory;
|
DefaultPluginApplicationContextFactory factory;
|
||||||
|
|
|
@ -23,11 +23,11 @@ import org.mockito.Mock;
|
||||||
import org.mockito.Spy;
|
import org.mockito.Spy;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import org.skyscreamer.jsonassert.JSONAssert;
|
import org.skyscreamer.jsonassert.JSONAssert;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.cache.CacheManager;
|
import org.springframework.cache.CacheManager;
|
||||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import run.halo.app.core.extension.Plugin;
|
import run.halo.app.core.extension.Plugin;
|
||||||
import run.halo.app.extension.ConfigMap;
|
import run.halo.app.extension.ConfigMap;
|
||||||
|
@ -55,7 +55,7 @@ class DefaultSettingFetcherTest {
|
||||||
@Mock
|
@Mock
|
||||||
private CacheManager cacheManager;
|
private CacheManager cacheManager;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
private final PluginContext pluginContext = PluginContext.builder()
|
private final PluginContext pluginContext = PluginContext.builder()
|
||||||
.name("fake")
|
.name("fake")
|
||||||
.configMapName("fake-config")
|
.configMapName("fake-config")
|
||||||
|
|
|
@ -37,11 +37,12 @@ import run.halo.app.infra.utils.JsonUtils;
|
||||||
*/
|
*/
|
||||||
@ExtendWith(SpringExtension.class)
|
@ExtendWith(SpringExtension.class)
|
||||||
class AuthProviderServiceImplTest {
|
class AuthProviderServiceImplTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ReactiveExtensionClient client;
|
ReactiveExtensionClient client;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private AuthProviderServiceImpl authProviderService;
|
AuthProviderServiceImpl authProviderService;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testEnable() {
|
void testEnable() {
|
||||||
|
@ -57,14 +58,12 @@ class AuthProviderServiceImplTest {
|
||||||
when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG)))
|
when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG)))
|
||||||
.thenReturn(Mono.just(configMap));
|
.thenReturn(Mono.just(configMap));
|
||||||
|
|
||||||
AuthProvider local = createAuthProvider("local");
|
|
||||||
local.getMetadata().getLabels().put(AuthProvider.PRIVILEGED_LABEL, "true");
|
|
||||||
when(client.list(eq(AuthProvider.class), any(), any())).thenReturn(Flux.just(local));
|
|
||||||
|
|
||||||
// Call the method being tested
|
// Call the method being tested
|
||||||
Mono<AuthProvider> result = authProviderService.enable("github");
|
authProviderService.enable("github")
|
||||||
|
.as(StepVerifier::create)
|
||||||
|
.expectNext(authProvider)
|
||||||
|
.verifyComplete();
|
||||||
|
|
||||||
assertEquals(authProvider, result.block());
|
|
||||||
ConfigMap value = captor.getValue();
|
ConfigMap value = captor.getValue();
|
||||||
String providerSettingStr = value.getData().get(SystemSetting.AuthProvider.GROUP);
|
String providerSettingStr = value.getData().get(SystemSetting.AuthProvider.GROUP);
|
||||||
Set<String> enabled =
|
Set<String> enabled =
|
||||||
|
@ -84,7 +83,7 @@ class AuthProviderServiceImplTest {
|
||||||
|
|
||||||
AuthProvider local = createAuthProvider("local");
|
AuthProvider local = createAuthProvider("local");
|
||||||
local.getMetadata().getLabels().put(AuthProvider.PRIVILEGED_LABEL, "true");
|
local.getMetadata().getLabels().put(AuthProvider.PRIVILEGED_LABEL, "true");
|
||||||
when(client.list(eq(AuthProvider.class), any(), any())).thenReturn(Flux.just(local));
|
// when(client.list(eq(AuthProvider.class), any(), any())).thenReturn(Flux.just(local));
|
||||||
|
|
||||||
ArgumentCaptor<ConfigMap> captor = ArgumentCaptor.forClass(ConfigMap.class);
|
ArgumentCaptor<ConfigMap> captor = ArgumentCaptor.forClass(ConfigMap.class);
|
||||||
when(client.update(captor.capture())).thenReturn(Mono.empty());
|
when(client.update(captor.capture())).thenReturn(Mono.empty());
|
||||||
|
|
|
@ -10,8 +10,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
|
||||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import run.halo.app.core.extension.Role;
|
import run.halo.app.core.extension.Role;
|
||||||
import run.halo.app.core.extension.RoleBinding;
|
import run.halo.app.core.extension.RoleBinding;
|
||||||
|
@ -28,7 +28,7 @@ import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
@AutoConfigureTestDatabase
|
@AutoConfigureTestDatabase
|
||||||
class SuperAdminInitializerTest {
|
class SuperAdminInitializerTest {
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
ReactiveExtensionClient client;
|
ReactiveExtensionClient client;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.context.TestConfiguration;
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
@ -26,6 +25,7 @@ import org.springframework.security.core.userdetails.ReactiveUserDetailsPassword
|
||||||
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
|
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
|
||||||
import org.springframework.security.test.context.support.WithMockUser;
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
@ -49,13 +49,13 @@ class AuthorizationTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
WebTestClient webClient;
|
WebTestClient webClient;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
ReactiveUserDetailsService userDetailsService;
|
ReactiveUserDetailsService userDetailsService;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
ReactiveUserDetailsPasswordService userDetailsPasswordService;
|
ReactiveUserDetailsPasswordService userDetailsPasswordService;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
RoleService roleService;
|
RoleService roleService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -11,11 +11,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.context.TestConfiguration;
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.test.annotation.DirtiesContext;
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import org.springframework.web.reactive.function.server.RouterFunction;
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
@ -36,7 +36,7 @@ public class ThemeIntegrationTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
WebTestClient webClient;
|
WebTestClient webClient;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
InitializationStateGetter initializationStateGetter;
|
InitializationStateGetter initializationStateGetter;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -2,14 +2,13 @@ package run.halo.app.theme;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
@ -35,40 +34,41 @@ import reactor.test.StepVerifier;
|
||||||
class ViewNameResolverTest {
|
class ViewNameResolverTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ThemeResolver themeResolver;
|
ThemeResolver themeResolver;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ThymeleafProperties thymeleafProperties;
|
ThymeleafProperties thymeleafProperties;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private DefaultViewNameResolver viewNameResolver;
|
DefaultViewNameResolver viewNameResolver;
|
||||||
|
|
||||||
@TempDir
|
@TempDir
|
||||||
private File themePath;
|
Path themePath;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() throws IOException {
|
void setUp() throws IOException {
|
||||||
when(thymeleafProperties.getSuffix()).thenReturn(ThymeleafProperties.DEFAULT_SUFFIX);
|
when(thymeleafProperties.getSuffix()).thenReturn(ThymeleafProperties.DEFAULT_SUFFIX);
|
||||||
|
}
|
||||||
|
|
||||||
var templatesPath = themePath.toPath().resolve("templates");
|
@Test
|
||||||
|
void resolveViewNameOrDefault() throws URISyntaxException, IOException {
|
||||||
|
var templatesPath = themePath.resolve("templates");
|
||||||
if (!Files.exists(templatesPath)) {
|
if (!Files.exists(templatesPath)) {
|
||||||
Files.createDirectory(templatesPath);
|
Files.createDirectory(templatesPath);
|
||||||
}
|
}
|
||||||
Files.createFile(templatesPath.resolve("post_news.html"));
|
Files.createFile(templatesPath.resolve("post_news.html"));
|
||||||
Files.createFile(templatesPath.resolve("post_docs.html"));
|
Files.createFile(templatesPath.resolve("post_docs.html"));
|
||||||
|
|
||||||
when(themeResolver.getTheme(any()))
|
|
||||||
|
var exchange = Mockito.mock(ServerWebExchange.class);
|
||||||
|
when(themeResolver.getTheme(exchange))
|
||||||
.thenReturn(Mono.fromSupplier(() -> ThemeContext.builder()
|
.thenReturn(Mono.fromSupplier(() -> ThemeContext.builder()
|
||||||
.name("fake-theme")
|
.name("fake-theme")
|
||||||
.path(themePath.toPath())
|
.path(themePath)
|
||||||
.active(true)
|
.active(true)
|
||||||
.build())
|
.build())
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void resolveViewNameOrDefault() throws URISyntaxException {
|
|
||||||
ServerWebExchange exchange = Mockito.mock(ServerWebExchange.class);
|
|
||||||
MockServerRequest request = MockServerRequest.builder()
|
MockServerRequest request = MockServerRequest.builder()
|
||||||
.uri(new URI("/")).method(HttpMethod.GET)
|
.uri(new URI("/")).method(HttpMethod.GET)
|
||||||
.exchange(exchange)
|
.exchange(exchange)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
@ -27,10 +27,10 @@ class GeneratorMetaProcessorTest {
|
||||||
@Autowired
|
@Autowired
|
||||||
WebTestClient webClient;
|
WebTestClient webClient;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
InitializationStateGetter initializationStateGetter;
|
InitializationStateGetter initializationStateGetter;
|
||||||
|
|
||||||
@MockBean
|
@MockitoBean
|
||||||
ThemeResolver themeResolver;
|
ThemeResolver themeResolver;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
|
|
|
@ -44,21 +44,19 @@ import run.halo.app.metrics.CounterService;
|
||||||
class CommentPublicQueryServiceImplTest {
|
class CommentPublicQueryServiceImplTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ReactiveExtensionClient client;
|
ReactiveExtensionClient client;
|
||||||
@Mock
|
|
||||||
private UserService userService;
|
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private CounterService counterService;
|
UserService userService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
CounterService counterService;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private CommentPublicQueryServiceImpl commentPublicQueryService;
|
CommentPublicQueryServiceImpl commentPublicQueryService;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
User ghost = createUser();
|
|
||||||
ghost.getMetadata().setName("ghost");
|
|
||||||
when(userService.getUserOrGhost(eq("ghost"))).thenReturn(Mono.just(ghost));
|
|
||||||
when(userService.getUserOrGhost(eq("fake-user"))).thenReturn(Mono.just(createUser()));
|
when(userService.getUserOrGhost(eq("fake-user"))).thenReturn(Mono.just(createUser()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.context.TestConfiguration;
|
import org.springframework.boot.test.context.TestConfiguration;
|
||||||
import org.springframework.boot.test.mock.mockito.SpyBean;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
|
||||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
import org.springframework.web.reactive.function.server.RequestPredicates;
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
|
@ -38,14 +38,14 @@ import run.halo.app.theme.ThemeResolver;
|
||||||
@AutoConfigureWebTestClient
|
@AutoConfigureWebTestClient
|
||||||
public class ThemeMessageResolverIntegrationTest {
|
public class ThemeMessageResolverIntegrationTest {
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
private ThemeResolver themeResolver;
|
private ThemeResolver themeResolver;
|
||||||
|
|
||||||
private URL defaultThemeUrl;
|
private URL defaultThemeUrl;
|
||||||
|
|
||||||
private URL otherThemeUrl;
|
private URL otherThemeUrl;
|
||||||
|
|
||||||
@SpyBean
|
@MockitoSpyBean
|
||||||
private InitializationStateGetter initializationStateGetter;
|
private InitializationStateGetter initializationStateGetter;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -43,36 +43,40 @@ import run.halo.app.theme.finders.vo.SinglePageVo;
|
||||||
@ExtendWith(SpringExtension.class)
|
@ExtendWith(SpringExtension.class)
|
||||||
class PreviewRouterFunctionTest {
|
class PreviewRouterFunctionTest {
|
||||||
@Mock
|
@Mock
|
||||||
private ReactiveExtensionClient client;
|
ReactiveExtensionClient client;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private PostPublicQueryService postPublicQueryService;
|
PostPublicQueryService postPublicQueryService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ViewNameResolver viewNameResolver;
|
ViewNameResolver viewNameResolver;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private ViewResolver viewResolver;
|
ViewResolver viewResolver;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private PostService postService;
|
PostService postService;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private SinglePageConversionService singlePageConversionService;
|
SinglePageConversionService singlePageConversionService;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private PreviewRouterFunction previewRouterFunction;
|
PreviewRouterFunction previewRouterFunction;
|
||||||
|
|
||||||
private WebTestClient webTestClient;
|
WebTestClient webTestClient;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
void setUp() {
|
||||||
webTestClient = WebTestClient.bindToRouterFunction(previewRouterFunction.previewRouter())
|
webTestClient = WebTestClient.bindToRouterFunction(previewRouterFunction.previewRouter())
|
||||||
.handlerStrategies(HandlerStrategies.builder()
|
.handlerStrategies(HandlerStrategies.builder()
|
||||||
.viewResolver(viewResolver)
|
.viewResolver(viewResolver)
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@WithMockUser(username = "testuser")
|
||||||
|
void previewPost() {
|
||||||
when(viewResolver.resolveViewName(any(), any()))
|
when(viewResolver.resolveViewName(any(), any()))
|
||||||
.thenReturn(Mono.just(new EmptyView() {
|
.thenReturn(Mono.just(new EmptyView() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,11 +85,7 @@ class PreviewRouterFunctionTest {
|
||||||
return super.render(model, contentType, exchange);
|
return super.render(model, contentType, exchange);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@WithMockUser(username = "testuser")
|
|
||||||
public void previewPost() {
|
|
||||||
Post post = new Post();
|
Post post = new Post();
|
||||||
post.setMetadata(new Metadata());
|
post.setMetadata(new Metadata());
|
||||||
post.getMetadata().setName("post1");
|
post.getMetadata().setName("post1");
|
||||||
|
@ -123,6 +123,15 @@ class PreviewRouterFunctionTest {
|
||||||
@Test
|
@Test
|
||||||
@WithMockUser(username = "testuser")
|
@WithMockUser(username = "testuser")
|
||||||
public void previewSinglePage() {
|
public void previewSinglePage() {
|
||||||
|
when(viewResolver.resolveViewName(any(), any()))
|
||||||
|
.thenReturn(Mono.just(new EmptyView() {
|
||||||
|
@Override
|
||||||
|
public Mono<Void> render(Map<String, ?> model, MediaType contentType,
|
||||||
|
ServerWebExchange exchange) {
|
||||||
|
return super.render(model, contentType, exchange);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
SinglePage singlePage = new SinglePage();
|
SinglePage singlePage = new SinglePage();
|
||||||
singlePage.setMetadata(new Metadata());
|
singlePage.setMetadata(new Metadata());
|
||||||
singlePage.getMetadata().setName("page1");
|
singlePage.getMetadata().setName("page1");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
plugins {
|
plugins {
|
||||||
id 'org.springframework.boot' version '3.3.3' apply false
|
id 'org.springframework.boot' version '3.4.0-M3' apply false
|
||||||
id 'io.spring.dependency-management' version '1.1.6' apply false
|
id 'io.spring.dependency-management' version '1.1.6' apply false
|
||||||
id "com.gorylenko.gradle-git-properties" version "2.4.1" apply false
|
id "com.gorylenko.gradle-git-properties" version "2.4.1" apply false
|
||||||
id "de.undercouch.download" version "5.6.0" apply false
|
id "de.undercouch.download" version "5.6.0" apply false
|
||||||
|
|
|
@ -19,7 +19,6 @@ import {
|
||||||
setupCoreModules,
|
setupCoreModules,
|
||||||
setupPluginModules,
|
setupPluginModules,
|
||||||
} from "@console/setup/setupModules";
|
} from "@console/setup/setupModules";
|
||||||
import { useSystemConfigMapStore } from "@console/stores/system-configmap";
|
|
||||||
import { useThemeStore } from "@console/stores/theme";
|
import { useThemeStore } from "@console/stores/theme";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
@ -97,10 +96,6 @@ async function initApp() {
|
||||||
console.error("Failed to load plugins", e);
|
console.error("Failed to load plugins", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// load system configMap
|
|
||||||
const systemConfigMapStore = useSystemConfigMapStore();
|
|
||||||
await systemConfigMapStore.fetchSystemConfigMap();
|
|
||||||
|
|
||||||
if (globalInfoStore.globalInfo?.userInitialized) {
|
if (globalInfoStore.globalInfo?.userInitialized) {
|
||||||
await loadActivatedTheme();
|
await loadActivatedTheme();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import { Toast, VButton } from "@halo-dev/components";
|
||||||
// hooks
|
// hooks
|
||||||
import { useGlobalInfoStore } from "@/stores/global-info";
|
import { useGlobalInfoStore } from "@/stores/global-info";
|
||||||
import { useSettingFormConvert } from "@console/composables/use-setting-form";
|
import { useSettingFormConvert } from "@console/composables/use-setting-form";
|
||||||
import { useSystemConfigMapStore } from "@console/stores/system-configmap";
|
|
||||||
import type { ConfigMap, Setting } from "@halo-dev/api-client";
|
import type { ConfigMap, Setting } from "@halo-dev/api-client";
|
||||||
import { coreApiClient } from "@halo-dev/api-client";
|
import { coreApiClient } from "@halo-dev/api-client";
|
||||||
import { useQuery, useQueryClient } from "@tanstack/vue-query";
|
import { useQuery, useQueryClient } from "@tanstack/vue-query";
|
||||||
|
@ -18,7 +17,6 @@ import { useI18n } from "vue-i18n";
|
||||||
const SYSTEM_CONFIGMAP_NAME = "system";
|
const SYSTEM_CONFIGMAP_NAME = "system";
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const systemConfigMapStore = useSystemConfigMapStore();
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const group = inject<Ref<string>>("activeTab", ref("basic"));
|
const group = inject<Ref<string>>("activeTab", ref("basic"));
|
||||||
|
@ -52,7 +50,7 @@ const handleSaveConfigMap = async () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = await coreApiClient.configMap.updateConfigMap({
|
await coreApiClient.configMap.updateConfigMap({
|
||||||
name: SYSTEM_CONFIGMAP_NAME,
|
name: SYSTEM_CONFIGMAP_NAME,
|
||||||
configMap: configMapToUpdate,
|
configMap: configMapToUpdate,
|
||||||
});
|
});
|
||||||
|
@ -61,7 +59,6 @@ const handleSaveConfigMap = async () => {
|
||||||
|
|
||||||
queryClient.invalidateQueries({ queryKey: ["system-configMap"] });
|
queryClient.invalidateQueries({ queryKey: ["system-configMap"] });
|
||||||
await useGlobalInfoStore().fetchGlobalInfo();
|
await useGlobalInfoStore().fetchGlobalInfo();
|
||||||
systemConfigMapStore.configMap = data;
|
|
||||||
|
|
||||||
saving.value = false;
|
saving.value = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
import type { ConfigMap } from "@halo-dev/api-client";
|
|
||||||
import { coreApiClient } from "@halo-dev/api-client";
|
|
||||||
import { defineStore } from "pinia";
|
|
||||||
|
|
||||||
interface SystemConfigMapState {
|
|
||||||
configMap?: ConfigMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useSystemConfigMapStore = defineStore({
|
|
||||||
id: "system-configmap",
|
|
||||||
state: (): SystemConfigMapState => ({
|
|
||||||
configMap: undefined,
|
|
||||||
}),
|
|
||||||
actions: {
|
|
||||||
async fetchSystemConfigMap() {
|
|
||||||
try {
|
|
||||||
const { data } = await coreApiClient.configMap.getConfigMap(
|
|
||||||
{
|
|
||||||
name: "system",
|
|
||||||
},
|
|
||||||
{ mute: true }
|
|
||||||
);
|
|
||||||
this.configMap = data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to fetch system configMap", error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
Loading…
Reference in New Issue