Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove route when single pages become unpublished #4318

Merged
merged 1 commit into from Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -101,15 +101,21 @@ private RequestPredicate exactPath(String path) {
public Result reconcile(Request request) {
client.fetch(SinglePage.class, request.name())
.ifPresent(page -> {
if (ExtensionOperator.isDeleted(page)
|| BooleanUtils.isTrue(page.getSpec().getDeleted())) {
quickRouteMap.remove(NameSlugPair.from(page));
var nameSlugPair = NameSlugPair.from(page);
if (ExtensionOperator.isDeleted(page)) {
quickRouteMap.remove(nameSlugPair);
return;
}
// put new one
quickRouteMap.entrySet()
.removeIf(entry -> entry.getKey().name().equals(request.name()));
quickRouteMap.put(NameSlugPair.from(page), handlerFunction(request.name()));
if (BooleanUtils.isTrue(page.getSpec().getDeleted())) {
quickRouteMap.remove(nameSlugPair);
} else {
// put new one
if (page.isPublished()) {
quickRouteMap.put(nameSlugPair, handlerFunction(request.name()));
} else {
quickRouteMap.remove(nameSlugPair);
}
}
});
return new Result(false, null);
}
Expand Down
Expand Up @@ -2,16 +2,24 @@

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.net.URI;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
Expand All @@ -31,8 +39,10 @@
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import run.halo.app.core.extension.content.SinglePage;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.GroupVersionKind;
import run.halo.app.extension.Metadata;
import run.halo.app.extension.controller.Reconciler;
import run.halo.app.theme.DefaultTemplateEnum;
import run.halo.app.theme.finders.SinglePageFinder;
import run.halo.app.theme.finders.vo.SinglePageVo;
Expand All @@ -48,16 +58,19 @@
class SinglePageRouteTest {

@Mock
private ViewNameResolver viewNameResolver;
ViewNameResolver viewNameResolver;

@Mock
private SinglePageFinder singlePageFinder;
SinglePageFinder singlePageFinder;

@Mock
protected ViewResolver viewResolver;
ViewResolver viewResolver;

@Mock
ExtensionClient client;

@InjectMocks
private SinglePageRoute singlePageRoute;
SinglePageRoute singlePageRoute;

@Test
void handlerFunction() {
Expand Down Expand Up @@ -130,4 +143,102 @@ void shouldNotThrowErrorIfSlugNameContainsSpecialChars() {
.verifyComplete();
}

@Nested
class SinglePageReconcilerTest {

@Test
void shouldRemoveRouteIfSinglePageUnpublished() {
var name = "fake-single-page";
var page = newSinglePage(name, false);
when(client.fetch(SinglePage.class, name)).thenReturn(
Optional.of(page));

var routeMap = Mockito.<Map<NameSlugPair, HandlerFunction<ServerResponse>>>mock(
invocation -> new HashMap<NameSlugPair, HandlerFunction<ServerResponse>>());
singlePageRoute.setQuickRouteMap(routeMap);
var result = singlePageRoute.reconcile(new Reconciler.Request(name));
assertNotNull(result);
assertFalse(result.reEnqueue());
verify(client).fetch(SinglePage.class, name);
verify(routeMap).remove(NameSlugPair.from(page));
}

@Test
void shouldAddRouteIfSinglePagePublished() {
var name = "fake-single-page";
var page = newSinglePage(name, true);
when(client.fetch(SinglePage.class, name)).thenReturn(
Optional.of(page));

var routeMap = Mockito.<Map<NameSlugPair, HandlerFunction<ServerResponse>>>mock(
invocation -> new HashMap<NameSlugPair, HandlerFunction<ServerResponse>>());
singlePageRoute.setQuickRouteMap(routeMap);
var result = singlePageRoute.reconcile(new Reconciler.Request(name));
assertNotNull(result);
assertFalse(result.reEnqueue());
verify(client).fetch(SinglePage.class, name);
verify(routeMap).put(eq(NameSlugPair.from(page)), any());
}

@Test
void shouldRemoveRouteIfSinglePageDeleted() {
var name = "fake-single-page";
var page = newDeletedSinglePage(name);
when(client.fetch(SinglePage.class, name)).thenReturn(
Optional.of(page));

var routeMap = Mockito.<Map<NameSlugPair, HandlerFunction<ServerResponse>>>mock(
invocation -> new HashMap<NameSlugPair, HandlerFunction<ServerResponse>>());
singlePageRoute.setQuickRouteMap(routeMap);
var result = singlePageRoute.reconcile(new Reconciler.Request(name));
assertNotNull(result);
assertFalse(result.reEnqueue());
verify(client).fetch(SinglePage.class, name);
verify(routeMap).remove(NameSlugPair.from(page));
}

@Test
void shouldRemoveRouteIfSinglePageRecycled() {
var name = "fake-single-page";
var page = newRecycledSinglePage(name);
when(client.fetch(SinglePage.class, name)).thenReturn(
Optional.of(page));

var routeMap = Mockito.<Map<NameSlugPair, HandlerFunction<ServerResponse>>>mock(
invocation -> new HashMap<NameSlugPair, HandlerFunction<ServerResponse>>());
singlePageRoute.setQuickRouteMap(routeMap);
var result = singlePageRoute.reconcile(new Reconciler.Request(name));
assertNotNull(result);
assertFalse(result.reEnqueue());
verify(client).fetch(SinglePage.class, name);
verify(routeMap).remove(NameSlugPair.from(page));
}


SinglePage newSinglePage(String name, boolean published) {
var metadata = new Metadata();
metadata.setName(name);
var page = new SinglePage();
page.setMetadata(metadata);
var spec = new SinglePage.SinglePageSpec();
spec.setSlug("/fake-slug");
page.setSpec(spec);
var status = new SinglePage.SinglePageStatus();
page.setStatus(status);
SinglePage.changePublishedState(page, published);
return page;
}

SinglePage newDeletedSinglePage(String name) {
var page = newSinglePage(name, true);
page.getMetadata().setDeletionTimestamp(Instant.now());
return page;
}

SinglePage newRecycledSinglePage(String name) {
var page = newSinglePage(name, true);
page.getSpec().setDeleted(true);
return page;
}
}
}