Skip to content

Commit

Permalink
feat: add refresh flag to navigation event (#15324) (#15333)
Browse files Browse the repository at this point in the history
Add the isRefreshEvent to BeforeEnterEvent
and AfterNavigationEvent to be make it possible
to distinguish if the event is for a refresh of
a preserve on refresh view.

Fixes #14999
  • Loading branch information
caalador authored Dec 1, 2022
1 parent 94fe049 commit 9b2c4b8
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,13 @@ public List<HasElement> getActiveChain() {
public Router getSource() {
return (Router) super.getSource();
}

/**
* Check if event is for a refresh of a preserveOnRefresh view.
*
* @return true if refresh of a preserve on refresh view
*/
public boolean isRefreshEvent() {
return event.getTrigger().equals(NavigationTrigger.REFRESH);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,13 @@ public BeforeEnterEvent(Router router, NavigationTrigger trigger,
super(router, trigger, location, navigationTarget, parameters, ui,
layouts);
}

/**
* Check if event is for a refresh of a preserveOnRefresh view.
*
* @return true if refresh of a preserve on refresh view
*/
public boolean isRefreshEvent() {
return getTrigger().equals(NavigationTrigger.REFRESH);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,10 @@ public enum NavigationTrigger {
* Navigation was triggered via
* {@link UI#navigate(String, QueryParameters)}. It's for internal use only.
*/
UI_NAVIGATE
UI_NAVIGATE,

/**
* Navigation is for a reload event on a preserveOnRefresh route.
*/
REFRESH
}
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,13 @@ public int handle(NavigationEvent event) {
clearAllPreservedChains(ui);
}

// Set navigationTrigger to RELOAD if this is a refresh of a preserve
// view.
if (preserveOnRefreshTarget && !chain.isEmpty()) {
event = new NavigationEvent(event.getSource(), event.getLocation(),
event.getUI(), NavigationTrigger.REFRESH);
}

BeforeEnterEvent beforeNavigationActivating = new BeforeEnterEvent(
event, routeTargetType, parameters, routeLayoutTypes);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
import com.vaadin.flow.component.page.Page;
import com.vaadin.flow.component.page.PendingJavaScriptResult;
import com.vaadin.flow.dom.Element;
import com.vaadin.flow.router.AfterNavigationEvent;
import com.vaadin.flow.router.AfterNavigationObserver;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.BeforeLeaveEvent;
import com.vaadin.flow.router.Location;
import com.vaadin.flow.router.NavigationEvent;
import com.vaadin.flow.router.NavigationState;
Expand Down Expand Up @@ -84,6 +89,29 @@ private static class PreservedView extends Text {
}
}

@Route(value = "preserved")
@PreserveOnRefresh
private static class PreservedEventView extends Text
implements BeforeEnterObserver, AfterNavigationObserver {
static boolean refreshBeforeEnter;
static boolean refreshAfterNavigation;

PreservedEventView() {
super("");
}

@Override
public void beforeEnter(BeforeEnterEvent event) {
refreshBeforeEnter = event.isRefreshEvent();
}

@Override
public void afterNavigation(AfterNavigationEvent event) {
refreshAfterNavigation = event.isRefreshEvent();

}
}

@Route(value = "regular")
private static class RegularView extends Text {
RegularView() {
Expand Down Expand Up @@ -326,6 +354,59 @@ public void handle_preserveOnRefreshAndWindowNameKnown_componentIsCachedRetrieve
session, new Location("preserved")));
}

@Test
public void handle_preserveOnRefresh_refreshIsFlaggedInEvent() {
// given a service with instantiator
MockVaadinServletService service = createMockServiceWithInstantiator();

// given a locked session
MockVaadinSession session = new AlwaysLockedVaadinSession(service);
session.setConfiguration(new MockDeploymentConfiguration());

// given a UI that contain a window name ROOT.123
MockUI ui = new MockUI(session);
ExtendedClientDetails details = Mockito
.mock(ExtendedClientDetails.class);
Mockito.when(details.getWindowName()).thenReturn("ROOT.123");
ui.getInternals().setExtendedClientDetails(details);

// given a NavigationStateRenderer mapping to PreservedEventView
NavigationStateRenderer renderer = new NavigationStateRenderer(
navigationStateFromTarget(PreservedEventView.class));

// when a navigation event reaches the renderer
renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()),
new Location("preserved"), ui, NavigationTrigger.PAGE_LOAD));

// then the session has a cached record of the view
Assert.assertTrue("Session expected to have cached view",
AbstractNavigationStateRenderer.getPreservedChain(session,
"ROOT.123", new Location("preserved")).isPresent());

// given the recently instantiated view
final PreservedEventView view = (PreservedEventView) ui.getInternals()
.getActiveRouterTargetsChain().get(0);
Assert.assertFalse(
"Initial view load should not be a refresh for before",
view.refreshBeforeEnter);
Assert.assertFalse(
"Initial view load should not be a refresh for after",
view.refreshAfterNavigation);

// when another navigation targets the same location
renderer.handle(new NavigationEvent(new Router(new TestRouteRegistry()),
new Location("preserved"), ui, NavigationTrigger.PAGE_LOAD));

// then the same view is routed to
Assert.assertEquals("Expected same view", view,
ui.getInternals().getActiveRouterTargetsChain().get(0));

Assert.assertTrue("Reload should be flagged for before",
view.refreshBeforeEnter);
Assert.assertTrue("Reload should be flagged for after",
view.refreshAfterNavigation);
}

@Test
public void handle_preserveOnRefresh_otherUIChildrenAreMoved() {
// given a service with instantiator
Expand Down

0 comments on commit 9b2c4b8

Please sign in to comment.