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

Added tester for RouterLink. #1810

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See <https://vaadin.com/commercial-license-and-service-terms> for the full
* license.
*/
package com.vaadin.flow.component.routerlink;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.Route;

import java.util.stream.Collectors;

@Tag(Tag.DIV)
@Route(value = RouterLinkQueryParameterTargetView.ROUTE, registerAtStartup = false)
public class RouterLinkQueryParameterTargetView extends Component
implements HasComponents, BeforeEnterObserver {

public static final String ROUTE = "router-link-query-parameter-target";

@Override
public void beforeEnter(BeforeEnterEvent event) {
var queryParameters = event.getLocation().getQueryParameters();

add(new Span("Query Parameter Target View: { " +
queryParameters.getParameters().entrySet().stream()
.map(entry -> entry.getKey() + " = [" +
entry.getValue().stream()
.sorted()
.collect(Collectors.joining(", ")) +
"]")
.sorted()
.collect(Collectors.joining("; ")) +
" }"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See <https://vaadin.com/commercial-license-and-service-terms> for the full
* license.
*/
package com.vaadin.flow.component.routerlink;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.Route;

import java.util.stream.Collectors;

@Tag(Tag.DIV)
@Route(value = RouterLinkRouteParameterTargetView.ROUTE + RouterLinkRouteParameterTargetView.ROUTE_PARAMETERS,
registerAtStartup = false)
public class RouterLinkRouteParameterTargetView extends Component
implements HasComponents, BeforeEnterObserver {

public static final String ROUTE = "router-link-route-parameter-target";
public static final String ROUTE_PARAMETERS = "/:segment1?/static/:segment2/:segment3*";

@Override
public void beforeEnter(BeforeEnterEvent event) {
var routeParameters = event.getRouteParameters();

add(new Span("Route Parameter Target View: { " +
routeParameters.getParameterNames().stream()
.map(name -> name + " = " + routeParameters.get(name).orElse(""))
.sorted()
.collect(Collectors.joining("; ")) +
" }"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See <https://vaadin.com/commercial-license-and-service-terms> for the full
* license.
*/
package com.vaadin.flow.component.routerlink;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.router.Route;

@Tag(Tag.DIV)
@Route(value = RouterLinkStaticTargetView.ROUTE, registerAtStartup = false)
public class RouterLinkStaticTargetView extends Component
implements HasComponents {

public static final String ROUTE = "router-link-static-target";

public RouterLinkStaticTargetView() {
add(new Span("Static Target View"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See <https://vaadin.com/commercial-license-and-service-terms> for the full
* license.
*/
package com.vaadin.flow.component.routerlink;

import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.router.RouteConfiguration;
import com.vaadin.flow.router.RouterLink;
import com.vaadin.testbench.unit.ComponentTester;
import com.vaadin.testbench.unit.UIUnitTest;
import com.vaadin.testbench.unit.ViewPackages;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

@ViewPackages
class RouterLinkTesterTest extends UIUnitTest {

private ComponentTester<RouterLinkView> $routerLinkView;

@BeforeEach
void init() {
RouteConfiguration.forApplicationScope()
.setAnnotatedRoute(RouterLinkView.class);
RouteConfiguration.forApplicationScope()
.setAnnotatedRoute(RouterLinkStaticTargetView.class);
RouteConfiguration.forApplicationScope()
.setAnnotatedRoute(RouterLinkUrlParameterTargetView.class);
RouteConfiguration.forApplicationScope()
.setAnnotatedRoute(RouterLinkQueryParameterTargetView.class);
RouteConfiguration.forApplicationScope()
.setAnnotatedRoute(RouterLinkRouteParameterTargetView.class);

var routerLinkView = navigate(RouterLinkView.class);
$routerLinkView = test(routerLinkView);
}

@Test
void routerLink_targetless() {
// get router link
var targetlessRouterLink = $routerLinkView.find(RouterLink.class)
.withText("No Target")
.single();
Comment on lines +46 to +48
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest making all RouterLink components as package protected class fields so that the test can directly wrap the instance, without relying on find.
This allows to prevent false positives in tests because of potential bugs in the component locator.
IMO it also simplifies the test code

var $targetlessRouterLink = test(targetlessRouterLink);
Assertions.assertNotNull($targetlessRouterLink,
"Tester for targetless RouterLink not initialized.");

// verify its href
Assertions.assertEquals("",
$targetlessRouterLink.getHref());

// verify its click action fails due to no navigation target
Assertions.assertThrows(IllegalStateException.class, $targetlessRouterLink::click);
}

@Test
void routerLink_static() {
// get router link
var staticRouterLink = $routerLinkView.find(RouterLink.class)
.withText("Static Target")
.single();
var $staticRouterLink = test(staticRouterLink);
Assertions.assertNotNull($staticRouterLink,
"Tester for static RouterLink not initialized.");

// verify its href
Assertions.assertEquals(RouterLinkStaticTargetView.ROUTE,
$staticRouterLink.getHref());

// verify its click action returns correct target
var targetView = $staticRouterLink.click();
Assertions.assertInstanceOf(RouterLinkStaticTargetView.class, targetView);

// verify navigation target is correct
var $targetView = test(targetView);
Assertions.assertDoesNotThrow(() -> $targetView.find(Span.class)
.withText("Static Target View")
.single());
Comment on lines +81 to +83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as for RouterLink, what about having the Span as a package protected field and simply assert on its getText()?

}

@Test
void routerLink_emptyUrlParameter() {
var emptyUrlParameterRouterLink = $routerLinkView.find(RouterLink.class)
.withText("Empty URL Parameter Target")
.single();
var $emptyUrlParameterRouterLink = test(emptyUrlParameterRouterLink);
Assertions.assertNotNull($emptyUrlParameterRouterLink,
"Tester for empty URL parameter RouterLink not initialized.");

// verify its href
Assertions.assertEquals(RouterLinkUrlParameterTargetView.ROUTE,
$emptyUrlParameterRouterLink.getHref());

// verify its click action returns correct target
var targetView = $emptyUrlParameterRouterLink.click();
Assertions.assertInstanceOf(RouterLinkUrlParameterTargetView.class, targetView);

// verify navigation target is correct
var $targetView = test(targetView);
Assertions.assertDoesNotThrow(() -> $targetView.find(Span.class)
.withText("URL Parameter Target View: { }")
.single());
}

@Test
void routerLink_urlParameter() {
var urlParameterRouterLink = $routerLinkView.find(RouterLink.class)
.withText("URL Parameter Target")
.single();
var $urlParameterRouterLink = test(urlParameterRouterLink);
Assertions.assertNotNull($urlParameterRouterLink,
"Tester for URL parameter RouterLink not initialized.");

// verify its href
Assertions.assertEquals(RouterLinkUrlParameterTargetView.ROUTE + "/parameter-value",
$urlParameterRouterLink.getHref());

// verify its click action returns correct target
var targetView = $urlParameterRouterLink.click();
Assertions.assertInstanceOf(RouterLinkUrlParameterTargetView.class, targetView);

// verify navigation target is correct
var $targetView = test(targetView);
Assertions.assertDoesNotThrow(() -> $targetView.find(Span.class)
.withText("URL Parameter Target View: { parameter-value }")
.single());
}

@Test
void routerLink_queryParameter() {
var queryParameterRouterLink = $routerLinkView.find(RouterLink.class)
.withText("Query Parameter Target")
.single();
var $queryParameterRouterLink = test(queryParameterRouterLink);
Assertions.assertNotNull($queryParameterRouterLink,
"Tester for QueryParameter RouterLink not initialized.");

// verify its href
Assertions.assertEquals(RouterLinkQueryParameterTargetView.ROUTE +
"?parameter2=parameter2-value1&parameter2=parameter2-value2&parameter1=parameter1-value",
$queryParameterRouterLink.getHref());

// verify its click action returns correct target
var targetView = $queryParameterRouterLink.click();
Assertions.assertInstanceOf(RouterLinkQueryParameterTargetView.class, targetView);

// verify navigation target is correct
var $targetView = test(targetView);
Assertions.assertDoesNotThrow(() -> $targetView.find(Span.class)
.withText("Query Parameter Target View: { parameter1 = [parameter1-value]; parameter2 = [parameter2-value1, parameter2-value2] }")
.single());
}

@Test
void routerLink_routeParameter() {
var routeParameterRouterLink = $routerLinkView.find(RouterLink.class)
.withText("Route Parameter Target")
.single();
var $routeParameterRouterLink = test(routeParameterRouterLink);
Assertions.assertNotNull($routeParameterRouterLink,
"Tester for RouteParameter RouterLink not initialized.");

// verify its href
Assertions.assertEquals(RouterLinkRouteParameterTargetView.ROUTE +
"/static/segment2-value/segment3-value1/segment3-value2",
$routeParameterRouterLink.getHref());

// verify its click action returns correct target
var targetView = $routeParameterRouterLink.click();
Assertions.assertInstanceOf(RouterLinkRouteParameterTargetView.class, targetView);

// verify navigation target is correct
var $targetView = test(targetView);
Assertions.assertDoesNotThrow(() -> $targetView.find(Span.class)
.withText("Route Parameter Target View: { segment2 = segment2-value; segment3 = segment3-value1/segment3-value2 }")
.single());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See <https://vaadin.com/commercial-license-and-service-terms> for the full
* license.
*/
package com.vaadin.flow.component.routerlink;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.router.BeforeEvent;
import com.vaadin.flow.router.HasUrlParameter;
import com.vaadin.flow.router.OptionalParameter;
import com.vaadin.flow.router.Route;

@Tag(Tag.DIV)
@Route(value = RouterLinkUrlParameterTargetView.ROUTE, registerAtStartup = false)
public class RouterLinkUrlParameterTargetView extends Component
implements HasComponents, HasUrlParameter<String> {

public static final String ROUTE = "router-link-url-parameter-target";

@Override
public void setParameter(BeforeEvent event, @OptionalParameter String parameter) {
add(new Span("URL Parameter Target View: { " + (parameter != null ? parameter : "") + " }"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See <https://vaadin.com/commercial-license-and-service-terms> for the full
* license.
*/
package com.vaadin.flow.component.routerlink;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasComponents;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.router.QueryParameters;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouteParameters;
import com.vaadin.flow.router.RouterLink;

import java.util.Map;

@Tag(Tag.DIV)
@Route(value = RouterLinkView.ROUTE, registerAtStartup = false)
public class RouterLinkView extends Component implements HasComponents {

public static final String ROUTE = "router-link-test";

public RouterLinkView() {
// targetless router link
var targetlessRouterLink = new RouterLink();
targetlessRouterLink.setText("No Target");

// static router link
var staticRouterLink = new RouterLink("Static Target",
RouterLinkStaticTargetView.class);

// url parameter router link - empty
var emptyUrlParameterRouterLink = new RouterLink("Empty URL Parameter Target",
RouterLinkUrlParameterTargetView.class);

// url parameter router link - non-empty
var urlParameterRouterLink = new RouterLink("URL Parameter Target",
RouterLinkUrlParameterTargetView.class,
"parameter-value");

// query parameter router link
var queryParameterRouterLink = new RouterLink("Query Parameter Target",
RouterLinkQueryParameterTargetView.class);
queryParameterRouterLink.setQueryParameters(
QueryParameters.empty()
.merging("parameter1", "parameter1-value")
.merging("parameter2", "parameter2-value1", "parameter2-value2"));

// route parameter router link
var routeParameterRouterLink = new RouterLink("Route Parameter Target",
RouterLinkRouteParameterTargetView.class,
new RouteParameters(Map.ofEntries(
Map.entry("segment2", "segment2-value"),
Map.entry("segment3", "segment3-value1/segment3-value2"))));

add(targetlessRouterLink);
add(staticRouterLink);
add(emptyUrlParameterRouterLink);
add(urlParameterRouterLink);
add(queryParameterRouterLink);
add(routeParameterRouterLink);
}
}
Loading